❯ go-clikit
v0.10.0 pkg.go.dev ↗

packages › local web › localweb/assets

assets

import "github.com/GSI-HPC/go-clikit/localweb/assets"

Serve the static files of a page at addresses with a hash of them all, so that a browser keeps each one for good.

since v0.9.0 imports: no package of the kit decisions 35
The place of localweb/assets in go-clikit: the packages it imports, and the packages that import it.termtextprogressdisplaycliprogressprogresstestmcpprogresseventlogfanoutfanouttestclioutdoctorfsutilcobratreecobratreetestlocalwebsessionsselocalwebtestlaunchassetspagehtmx

A program embeds its files, so it works offline and loads nothing from elsewhere. assets.New serves them at PREFIX/VERSION/NAME, where the version is a hash of every file. A new build serves its files at new addresses, so a browser can keep each one for good.

files := fstest.MapFS{
	"app.css":    {Data: []byte("body { margin: 0 }")},
	"css/a.css":  {Data: []byte("a {}")},
	"css/b.css":  {Data: []byte("b {}")},
	"css/c.json": {Data: []byte("{}")},
}
a, err := assets.New(files, "/static/", assets.Options{})
if err != nil {
	fmt.Println(err)
	return
}
hide := func(s string) string { return strings.ReplaceAll(s, a.Version(), "VERSION") }

fmt.Println(len(a.Version()))
fmt.Println(hide(a.URL("app.css")))
for _, u := range a.URLs("css/*.css") {
	fmt.Println(hide(u))
}

mux := http.NewServeMux()
mux.Handle("GET /static/", a)
w := httptest.NewRecorder()
mux.ServeHTTP(w, httptest.NewRequest(http.MethodGet, a.URL("app.css"), nil))
fmt.Println(w.Code)
fmt.Println(w.Header().Get("Content-Type"))
fmt.Println(w.Header().Get("Cache-Control"))
12
/static/VERSION/app.css
/static/VERSION/css/a.css
/static/VERSION/css/b.css
200
text/css; charset=utf-8
private, max-age=31536000, immutable
ExampleNew in localweb/assets/example_test.go. CI runs it and checks its output.

A page links to a file with URL, such as from a template function:

<link rel="stylesheet" href="{{asset "app.css"}}">

With Options.Dev, the files are read again for each request from a directory that the program names, and the browser checks them each time. Use it to work on the files without building the program again.