commands: Simplify the browser live reload logic

And improve the logging for live reload.

Closes #12643
This commit is contained in:
Bjørn Erik Pedersen 2024-07-06 17:04:51 +02:00
parent fb8909d5b0
commit 094f746751

View file

@ -744,6 +744,20 @@ func (c *hugoBuilder) handleEvents(watcher *watcher.Batcher,
staticEvents := []fsnotify.Event{} staticEvents := []fsnotify.Event{}
dynamicEvents := []fsnotify.Event{} dynamicEvents := []fsnotify.Event{}
filterDuplicateEvents := func(evs []fsnotify.Event) []fsnotify.Event {
seen := make(map[string]bool)
var n int
for _, ev := range evs {
if seen[ev.Name] {
continue
}
seen[ev.Name] = true
evs[n] = ev
n++
}
return evs[:n]
}
h, err := c.hugo() h, err := c.hugo()
if err != nil { if err != nil {
c.r.logger.Errorln("Error getting the Hugo object:", err) c.r.logger.Errorln("Error getting the Hugo object:", err)
@ -833,6 +847,11 @@ func (c *hugoBuilder) handleEvents(watcher *watcher.Batcher,
} }
} }
lrl := c.r.logger.InfoCommand("livereload")
staticEvents = filterDuplicateEvents(staticEvents)
dynamicEvents = filterDuplicateEvents(dynamicEvents)
if len(staticEvents) > 0 { if len(staticEvents) > 0 {
c.printChangeDetected("Static files") c.printChangeDetected("Static files")
@ -853,19 +872,20 @@ func (c *hugoBuilder) handleEvents(watcher *watcher.Batcher,
if c.s != nil && c.s.doLiveReload { if c.s != nil && c.s.doLiveReload {
// Will block forever trying to write to a channel that nobody is reading if livereload isn't initialized // Will block forever trying to write to a channel that nobody is reading if livereload isn't initialized
// force refresh when more than one file
if !c.errState.wasErr() && len(staticEvents) == 1 { if !c.errState.wasErr() && len(staticEvents) == 1 {
ev := staticEvents[0]
h, err := c.hugo() h, err := c.hugo()
if err != nil { if err != nil {
c.r.logger.Errorln("Error getting the Hugo object:", err) c.r.logger.Errorln("Error getting the Hugo object:", err)
return return
} }
path := h.BaseFs.SourceFilesystems.MakeStaticPathRelative(ev.Name)
path := h.BaseFs.SourceFilesystems.MakeStaticPathRelative(staticEvents[0].Name)
path = h.RelURL(paths.ToSlashTrimLeading(path), false) path = h.RelURL(paths.ToSlashTrimLeading(path), false)
lrl.Logf("refreshing static file %q", path)
livereload.RefreshPath(path) livereload.RefreshPath(path)
} else { } else {
lrl.Logf("got %d static file change events, force refresh", len(staticEvents))
livereload.ForceRefresh() livereload.ForceRefresh()
} }
} }
@ -889,43 +909,30 @@ func (c *hugoBuilder) handleEvents(watcher *watcher.Batcher,
}() }()
if c.s != nil && c.s.doLiveReload { if c.s != nil && c.s.doLiveReload {
if len(partitionedEvents.ContentEvents) == 0 && len(partitionedEvents.AssetEvents) > 0 { if c.errState.wasErr() {
if c.errState.wasErr() { livereload.ForceRefresh()
livereload.ForceRefresh() return
return }
}
changed := c.changeDetector.changed() changed := c.changeDetector.changed()
if c.changeDetector != nil && len(changed) == 0 { if c.changeDetector != nil {
lrl.Logf("build changed %d files", len(changed))
if len(changed) == 0 {
// Nothing has changed. // Nothing has changed.
return return
} else if len(changed) == 1 { }
pathToRefresh := h.PathSpec.RelURL(paths.ToSlashTrimLeading(changed[0]), false) }
livereload.RefreshPath(pathToRefresh)
// If this change set also contains one or more CSS files, we need to
// refresh these as well.
var cssChanges []string
var otherChanges []string
for _, ev := range changed {
if strings.HasSuffix(ev, ".css") {
cssChanges = append(cssChanges, ev)
} else { } else {
livereload.ForceRefresh() otherChanges = append(otherChanges, ev)
// See https://github.com/gohugoio/hugo/issues/12600.
// If this change set also contains one or more CSS files, we need to
// refresh these as well.
var cssChanges []string
var otherChanges []string
for _, ev := range changed {
if strings.HasSuffix(ev, ".css") {
cssChanges = append(cssChanges, ev)
} else {
otherChanges = append(otherChanges, ev)
}
}
if len(otherChanges) > 0 {
livereload.ForceRefresh()
// Allow some time for the live reload script to get reconnected.
time.Sleep(200 * time.Millisecond)
}
for _, ev := range cssChanges {
livereload.RefreshPath(h.PathSpec.RelURL(paths.ToSlashTrimLeading(ev), false))
}
} }
} }
@ -942,10 +949,35 @@ func (c *hugoBuilder) handleEvents(watcher *watcher.Batcher,
} }
if p != nil { if p != nil {
livereload.NavigateToPathForPort(p.RelPermalink(), p.Site().ServerPort()) link, port := p.RelPermalink(), p.Site().ServerPort()
lrl.Logf("navigating to %q using port %d", link, port)
livereload.NavigateToPathForPort(link, port)
} else { } else {
lrl.Logf("no page to navigate to, force refresh")
livereload.ForceRefresh() livereload.ForceRefresh()
} }
} else if len(otherChanges) > 0 {
if len(otherChanges) == 1 {
// Allow single changes to be refreshed without a full page reload.
pathToRefresh := h.PathSpec.RelURL(paths.ToSlashTrimLeading(otherChanges[0]), false)
lrl.Logf("refreshing %q", pathToRefresh)
livereload.RefreshPath(pathToRefresh)
} else if len(cssChanges) == 0 {
lrl.Logf("force refresh")
livereload.ForceRefresh()
}
}
if len(cssChanges) > 0 {
// Allow some time for the live reload script to get reconnected.
if len(otherChanges) > 0 {
time.Sleep(200 * time.Millisecond)
}
for _, ev := range cssChanges {
pathToRefresh := h.PathSpec.RelURL(paths.ToSlashTrimLeading(ev), false)
lrl.Logf("refreshing CSS %q", pathToRefresh)
livereload.RefreshPath(pathToRefresh)
}
} }
} }
} }