reload

package module
v1.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 27, 2024 License: MIT Imports: 18 Imported by: 0

README

Reload

Tests

Reload is a Go package, which enables "soft reloading" of web server assets and templates, reloading the browser instantly via Websockets. The strength of Reload lies in it's simple API and easy integration to any Go projects.

Installation

go get github.com/aarol/reload

Usage

  1. Create a new Reloader and insert the middleware to your handler chain:

    // handler can be anything that implements http.Handler,
    // like chi.Router, echo.Echo or gin.Engine
    var handler http.Handler = http.DefaultServeMux
    
    if isDevelopment {
       // Call `New()` with a list of directories to recursively watch
       reloader := reload.New("ui/")
    
       // Optionally, define a callback to
       // invalidate any caches
       reloader.OnReload = func() {
          app.parseTemplates()
       }
    
       // Use the Handle() method as a middleware
       handler = reloader.Handle(handler)
    }
    
    http.ListenAndServe(addr, handler)
    
  2. Run your application, make changes to files in the specified directories, and see the updated page instantly!

See the full example at https://github.com/aarol/reload/blob/main/example/main.go

How it works

When added to the top of the middleware chain, (*Reloader).Handle() will inject a small <script/> at the end of any HTML file sent by your application. This script will instruct the browser to open a WebSocket connection back to your server, which will be also handled by the middleware.

The injected script is at the bottom of this file.

You can also do the injection yourself, as the package also exposes the methods (*Reloader).ServeWS and (*Reloader).WatchDirectories, which are used by the (*Reloader).Handle middleware.

Currently, injecting the script is done by appending to the end of the document, even after the </html> tag. This makes the library code much simpler, but may break older/less forgiving browsers.

Caveats

  • Reload works with everything that the server sends to the client (HTML,CSS,JS etc.), but it cannot restart the server itself, since it's just a middleware running on the server.

    To reload the entire server, you can use another file watcher on top, like watchexec:

    watchexec -r --exts .go -- go run .

    When the websocket connection to the server is lost, the browser will try to reconnect every second. This means that when the server comes back, the browser will still reload, although not as fast :)

  • Reload will not work for embedded assets, since all go:embed files are baked into the executable at build time.

Documentation

Overview

Package reload exposes the middleware Handle(), which can be used to trigger a reload in the browser whenever a file is changed.

Reload doesn't require any external tools and is can be integrated into any project that uses the standard net/http interface.

Typically, integrating this package looks like this:

1. Create a new Reloader and insert the middleware to your handler chain:

// handler can be anything that implements http.Handler,
// like chi.Router, echo.Echo or gin.Engine
var handler http.Handler = http.DefaultServeMux

if isDevelopment {
   // Call `New()` with a list of directories to recursively watch
   reloader := reload.New("ui/")

   // Optionally, define a callback to
   // invalidate any caches
   reloader.OnReload = func() {
      app.parseTemplates()
   }

   // Use the Handle() method as a middleware
   handler = reloader.Handle(handler)
}

http.ListenAndServe(addr, handler)

2. Run your application, make changes to files in the specified directories, and see the updated page instantly! The package also exposes `ServeWS`, `InjectScript`, `Wait` and `WatchDirectories`, which can be used to embed the script in the templates directly.

See the full example at https://github.com/aarol/reload/blob/main/example/main.go

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func InjectedScript

func InjectedScript(endpoint string) string

Returns the javascript that will be injected on each HTML page.

Types

type Reloader

type Reloader struct {
	// OnReload will be called after a file changes, but before the browser reloads.
	OnReload func()

	// Endpoint defines what path the WebSocket connection is formed over.
	// It is set to "/reload_ws" by default.
	Endpoint string
	// When set to true, prevents the middleware from sending a "Cache-Control=no-cache" header on each request.
	//
	// Some handlers, like http.FileServer send Last-Modified headers, which prevent the browser from refetching changed files correctly.
	//
	// To prevent confusion, caching is disabled by default.
	// It is also possible to enable this option, and use a middleware like Chi's NoCache (https://github.com/go-chi/chi/blob/master/middleware/nocache.go)
	AllowCaching bool

	Log *log.Logger

	// Used to upgrade connections to Websocket connections
	Upgrader websocket.Upgrader
	// contains filtered or unexported fields
}

func New

func New(directories ...string) *Reloader

New returns a new Reloader with the provided directories.

func (*Reloader) Handle

func (reload *Reloader) Handle(next http.Handler) http.Handler

Handle starts the reload middleware, watching the specified directories and injecting the script into HTML responses.

func (*Reloader) ServeWS

func (reload *Reloader) ServeWS(w http.ResponseWriter, r *http.Request)

ServeWS is the default websocket endpoint. Implementing your own is easy enough if you don't want to use 'gorilla/websocket'

func (*Reloader) Wait

func (reload *Reloader) Wait()

func (*Reloader) WatchDirectories

func (reload *Reloader) WatchDirectories()

WatchDirectories listens for changes in directories and broadcasts on write.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL