1
0
Fork 0
mirror of https://github.com/miniflux/v2.git synced 2025-08-11 17:51:01 +00:00

refactor(static): use a simple struct instead of two slices to store assets data and checksums

- Use a simple struct instead of two slices to store the data and the checksums
  of resources
- Remove a superfluous call to Sprintf
- Factorise presence check and data retrieval in some maps
- Size the maps when possible
This commit is contained in:
Julien Voisin 2025-08-06 04:35:27 +02:00 committed by GitHub
parent b1cbaae71c
commit 798bc4cd2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 33 additions and 29 deletions

View file

@ -15,12 +15,16 @@ import (
"github.com/tdewolff/minify/v2/js" "github.com/tdewolff/minify/v2/js"
) )
type asset struct {
Data []byte
Checksum string
}
// Static assets. // Static assets.
var ( var (
StylesheetBundleChecksums map[string]string StylesheetBundles map[string]asset
StylesheetBundles map[string][]byte JavascriptBundles map[string]asset
JavascriptBundleChecksums map[string]string binaryFileChecksums map[string]string
JavascriptBundles map[string][]byte
) )
//go:embed bin/* //go:embed bin/*
@ -32,16 +36,13 @@ var stylesheetFiles embed.FS
//go:embed js/*.js //go:embed js/*.js
var javascriptFiles embed.FS var javascriptFiles embed.FS
var binaryFileChecksums map[string]string
// CalculateBinaryFileChecksums generates hash of embed binary files. // CalculateBinaryFileChecksums generates hash of embed binary files.
func CalculateBinaryFileChecksums() error { func CalculateBinaryFileChecksums() error {
binaryFileChecksums = make(map[string]string)
dirEntries, err := binaryFiles.ReadDir("bin") dirEntries, err := binaryFiles.ReadDir("bin")
if err != nil { if err != nil {
return err return err
} }
binaryFileChecksums = make(map[string]string, len(dirEntries))
for _, dirEntry := range dirEntries { for _, dirEntry := range dirEntries {
data, err := LoadBinaryFile(dirEntry.Name()) data, err := LoadBinaryFile(dirEntry.Name())
@ -57,15 +58,16 @@ func CalculateBinaryFileChecksums() error {
// LoadBinaryFile loads an embed binary file. // LoadBinaryFile loads an embed binary file.
func LoadBinaryFile(filename string) ([]byte, error) { func LoadBinaryFile(filename string) ([]byte, error) {
return binaryFiles.ReadFile(fmt.Sprintf(`bin/%s`, filename)) return binaryFiles.ReadFile("bin/" + filename)
} }
// GetBinaryFileChecksum returns a binary file checksum. // GetBinaryFileChecksum returns a binary file checksum.
func GetBinaryFileChecksum(filename string) (string, error) { func GetBinaryFileChecksum(filename string) (string, error) {
if _, found := binaryFileChecksums[filename]; !found { data, found := binaryFileChecksums[filename]
if !found {
return "", fmt.Errorf(`static: unable to find checksum for %q`, filename) return "", fmt.Errorf(`static: unable to find checksum for %q`, filename)
} }
return binaryFileChecksums[filename], nil return data, nil
} }
// GenerateStylesheetsBundles creates CSS bundles. // GenerateStylesheetsBundles creates CSS bundles.
@ -79,8 +81,7 @@ func GenerateStylesheetsBundles() error {
"system_sans_serif": {"css/system.css", "css/sans_serif.css", "css/common.css"}, "system_sans_serif": {"css/system.css", "css/sans_serif.css", "css/common.css"},
} }
StylesheetBundles = make(map[string][]byte) StylesheetBundles = make(map[string]asset, len(bundles))
StylesheetBundleChecksums = make(map[string]string)
minifier := minify.New() minifier := minify.New()
minifier.AddFunc("text/css", css.Minify) minifier.AddFunc("text/css", css.Minify)
@ -102,8 +103,10 @@ func GenerateStylesheetsBundles() error {
return err return err
} }
StylesheetBundles[bundle] = minifiedData StylesheetBundles[bundle] = asset{
StylesheetBundleChecksums[bundle] = crypto.HashFromBytes(minifiedData) Data: minifiedData,
Checksum: crypto.HashFromBytes(minifiedData),
}
} }
return nil return nil
@ -125,8 +128,7 @@ func GenerateJavascriptBundles() error {
}, },
} }
JavascriptBundles = make(map[string][]byte) JavascriptBundles = make(map[string]asset, len(bundles))
JavascriptBundleChecksums = make(map[string]string)
jsMinifier := js.Minifier{Version: 2020} jsMinifier := js.Minifier{Version: 2020}
@ -150,8 +152,10 @@ func GenerateJavascriptBundles() error {
return err return err
} }
JavascriptBundles[bundle] = minifiedData JavascriptBundles[bundle] = asset{
JavascriptBundleChecksums[bundle] = crypto.HashFromBytes(minifiedData) Data: minifiedData,
Checksum: crypto.HashFromBytes(minifiedData),
}
} }
return nil return nil

View file

@ -21,14 +21,14 @@ const licenseSuffix = "\n//@license-end"
func (h *handler) showJavascript(w http.ResponseWriter, r *http.Request) { func (h *handler) showJavascript(w http.ResponseWriter, r *http.Request) {
filename := request.RouteStringParam(r, "name") filename := request.RouteStringParam(r, "name")
etag, found := static.JavascriptBundleChecksums[filename] js, found := static.JavascriptBundles[filename]
if !found { if !found {
html.NotFound(w, r) html.NotFound(w, r)
return return
} }
response.New(w, r).WithCaching(etag, 48*time.Hour, func(b *response.Builder) { response.New(w, r).WithCaching(js.Checksum, 48*time.Hour, func(b *response.Builder) {
contents := static.JavascriptBundles[filename] contents := js.Data
if filename == "service-worker" { if filename == "service-worker" {
variables := fmt.Sprintf(`const OFFLINE_URL=%q;`, route.Path(h.router, "offline")) variables := fmt.Sprintf(`const OFFLINE_URL=%q;`, route.Path(h.router, "offline"))

View file

@ -15,15 +15,15 @@ import (
func (h *handler) showStylesheet(w http.ResponseWriter, r *http.Request) { func (h *handler) showStylesheet(w http.ResponseWriter, r *http.Request) {
filename := request.RouteStringParam(r, "name") filename := request.RouteStringParam(r, "name")
etag, found := static.StylesheetBundleChecksums[filename] m, found := static.StylesheetBundles[filename]
if !found { if !found {
html.NotFound(w, r) html.NotFound(w, r)
return return
} }
response.New(w, r).WithCaching(etag, 48*time.Hour, func(b *response.Builder) { response.New(w, r).WithCaching(m.Checksum, 48*time.Hour, func(b *response.Builder) {
b.WithHeader("Content-Type", "text/css; charset=utf-8") b.WithHeader("Content-Type", "text/css; charset=utf-8")
b.WithBody(static.StylesheetBundles[filename]) b.WithBody(m.Data)
b.Write() b.Write()
}) })
} }

View file

@ -41,10 +41,10 @@ func New(tpl *template.Engine, r *http.Request, sess *session.Session) *View {
"flashErrorMessage": sess.FlashErrorMessage(request.FlashErrorMessage(r)), "flashErrorMessage": sess.FlashErrorMessage(request.FlashErrorMessage(r)),
"theme": theme, "theme": theme,
"language": request.UserLanguage(r), "language": request.UserLanguage(r),
"theme_checksum": static.StylesheetBundleChecksums[theme], "theme_checksum": static.StylesheetBundles[theme].Checksum,
"app_js_checksum": static.JavascriptBundleChecksums["app"], "app_js_checksum": static.JavascriptBundles["app"].Checksum,
"sw_js_checksum": static.JavascriptBundleChecksums["service-worker"], "sw_js_checksum": static.JavascriptBundles["service-worker"].Checksum,
"webauthn_js_checksum": static.JavascriptBundleChecksums["webauthn"], "webauthn_js_checksum": static.JavascriptBundles["webauthn"].Checksum,
"webAuthnEnabled": config.Opts.WebAuthn(), "webAuthnEnabled": config.Opts.WebAuthn(),
}} }}
} }