From 225eabf87e36b2c763b365ebe0c16cfb6fce0833 Mon Sep 17 00:00:00 2001 From: imago Date: Fri, 23 Aug 2024 18:32:35 +0300 Subject: [PATCH] Added -forceReload flag which forces page reload on any file change I'm developing a blog which is using fetch to lazy load html pages. So currently it doesnt refresh whenever the lazy loaded html is changed since origins html page won't ever be the same. So this is a quick and dirty way of solving the problem, might also solve some similar problems down the line. --- cmd/serve/serve.go | 16 +++++++++------- internal/wsinject/delta_streamer.ws.go | 8 ++++++-- internal/wsinject/wsinject.go | 19 ++++++++++++------- internal/wsinject/wsinject_test.go | 4 ++-- 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/cmd/serve/serve.go b/cmd/serve/serve.go index 28a3de2..182cabd 100644 --- a/cmd/serve/serve.go +++ b/cmd/serve/serve.go @@ -23,12 +23,13 @@ type Fileserver interface { type command struct { binPath string // master, as in adjective 'master record' non-slavery kind - masterPath string - mirrorPath string - port *int - wsPath *string - flagset *flag.FlagSet - fileserver Fileserver + masterPath string + mirrorPath string + port *int + wsPath *string + forceReload *bool + flagset *flag.FlagSet + fileserver Fileserver } func Command() *command { @@ -52,7 +53,7 @@ func (c *command) Setup() error { c.masterPath = path.Clean(relPath) if c.masterPath != "" { - c.fileserver = wsinject.NewFileServer(*c.port, *c.wsPath) + c.fileserver = wsinject.NewFileServer(*c.port, *c.wsPath, *c.forceReload) mirrorPath, err := c.fileserver.Setup(c.masterPath) if err != nil { return fmt.Errorf("failed to setup websocket injected mirror filesystem: %v", err) @@ -121,6 +122,7 @@ func (c *command) Flagset() *flag.FlagSet { fs := flag.NewFlagSet("server", flag.ExitOnError) c.port = fs.Int("port", 8080, "port to serve http server on") c.wsPath = fs.String("wsPort", "/delta-streamer-ws", "the path which the delta streamer websocket should be hosted on") + c.forceReload = fs.Bool("forceReload", false, "set to true if you wish to reload all attached browser pages on any file change") c.flagset = fs return fs } diff --git a/internal/wsinject/delta_streamer.ws.go b/internal/wsinject/delta_streamer.ws.go index f424502..7b8ed65 100644 --- a/internal/wsinject/delta_streamer.ws.go +++ b/internal/wsinject/delta_streamer.ws.go @@ -1,6 +1,6 @@ package wsinject -const DeltaStreamerSourceCode = `/** +const deltaStreamerSourceCode = `/** * This file has been injected by the wd-41 web development * hot reload tool. */ @@ -33,7 +33,11 @@ function startWebsocket() { if(event.data === fileName || // Always reload on js and css files since its difficult to know where these are used event.data.includes(".js") || - event.data.includes(".css")) { + event.data.includes(".css") || + // This funny-looking comparison is set using string interpolation from the -forceReload flag + // when writing this script + %v === true + ) { location.reload(); } }); diff --git a/internal/wsinject/wsinject.go b/internal/wsinject/wsinject.go index 2d73bd5..b4bd363 100644 --- a/internal/wsinject/wsinject.go +++ b/internal/wsinject/wsinject.go @@ -19,11 +19,12 @@ import ( ) type Fileserver struct { - masterPath string - mirrorPath string - wsPort int - wsPath string - watcher *fsnotify.Watcher + masterPath string + mirrorPath string + forceReload bool + wsPort int + wsPath string + watcher *fsnotify.Watcher pageReloadChan chan string wsDispatcher sync.Map @@ -36,7 +37,7 @@ var ErrNoHeaderTagFound = errors.New("no header tag found") const deltaStreamer = ` ` -func NewFileServer(wsPort int, wsPath string) *Fileserver { +func NewFileServer(wsPort int, wsPath string, forceReload bool) *Fileserver { mirrorDir, err := os.MkdirTemp("", "wd-41_*") if err != nil { panic(err) @@ -46,6 +47,7 @@ func NewFileServer(wsPort int, wsPath string) *Fileserver { mirrorPath: mirrorDir, wsPort: wsPort, wsPath: wsPath, + forceReload: forceReload, pageReloadChan: make(chan string), wsDispatcher: sync.Map{}, wsDispatcherStarted: &started, @@ -95,7 +97,10 @@ func (fs *Fileserver) mirrorMaker(p string, info os.DirEntry, err error) error { } func (fs *Fileserver) writeDeltaStreamerScript() error { - err := os.WriteFile(path.Join(fs.mirrorPath, "delta-streamer.js"), []byte(fmt.Sprintf(DeltaStreamerSourceCode, fs.wsPort, fs.wsPath)), 0o755) + err := os.WriteFile( + path.Join(fs.mirrorPath, "delta-streamer.js"), + []byte(fmt.Sprintf(deltaStreamerSourceCode, fs.wsPort, fs.wsPath, fs.forceReload)), + 0o755) if err != nil { return fmt.Errorf("failed to write delta-streamer.js: %w", err) } diff --git a/internal/wsinject/wsinject_test.go b/internal/wsinject/wsinject_test.go index 0bc3784..3f007f4 100644 --- a/internal/wsinject/wsinject_test.go +++ b/internal/wsinject/wsinject_test.go @@ -76,7 +76,7 @@ func Test_Setup(t *testing.T) { } nestedFile := path.Join(nestedDir, "nested.html") os.WriteFile(nestedFile, []byte(mockHtml), 0o777) - fs := NewFileServer(8080, "/delta-streamer-ws.js") + fs := NewFileServer(8080, "/delta-streamer-ws.js", false) _, err = fs.Setup(tmpDir) if err != nil { t.Fatalf("failed to setup: %v", err) @@ -145,7 +145,7 @@ func Test_Start(t *testing.T) { if err != nil { t.Fatalf("failed to create temp dir: %v", err) } - return NewFileServer(8080, "/delta-streamer-ws.js"), testFileSystem{ + return NewFileServer(8080, "/delta-streamer-ws.js", false), testFileSystem{ root: tmpDir, nestedDir: nestedDir, }