Minify html on-the-fly before sending it to users

This commit is contained in:
Tom Wiesing 2023-01-04 12:45:33 +01:00
parent b3039768af
commit 785130dc36
No known key found for this signature in database
7 changed files with 66 additions and 6 deletions

View file

@ -72,6 +72,6 @@ var (
return json.Marshal(map[string]any{"status": text, "code": code})
})
HTMLInterceptor = StatusInterceptor("text/html", func(code int, text string) ([]byte, error) {
return []byte(`<!DOCTYPE HTML><title>` + text + `</title>` + text), nil
return MinifyHTML([]byte(`<!DOCTYPE HTML><title>` + text + `</title>` + text)), nil
})
)

View file

@ -17,10 +17,15 @@ func WriteHTML[T any](result T, err error, template *template.Template, template
w.Header().Set("Content-Type", "text/html")
w.WriteHeader(http.StatusOK)
// minify html!
minifier := MinifyHTMLWriter(w)
defer minifier.Close()
// and return the template
if templateName != "" {
template.ExecuteTemplate(w, templateName, result)
template.ExecuteTemplate(minifier, templateName, result)
} else {
template.Execute(w, result)
template.Execute(minifier, result)
}
}

42
pkg/httpx/html_minify.go Normal file
View file

@ -0,0 +1,42 @@
package httpx
import (
"io"
"regexp"
"github.com/tdewolff/minify"
"github.com/tdewolff/minify/css"
"github.com/tdewolff/minify/html"
"github.com/tdewolff/minify/js"
"github.com/tdewolff/minify/svg"
)
// minifier holds the minfier used for all html minification
//
// NOTE(twiesing): We can't use an init function for this, because otherwise initialization order is incorrect.
var minifier = (func() *minify.M {
m := minify.New()
m.AddFunc("text/html", html.Minify)
m.AddFunc("text/css", css.Minify)
m.AddFunc("image/svg+xml", svg.Minify)
m.AddFuncRegexp(regexp.MustCompile("^(application|text)/(x-)?(java|ecma)script$"), js.Minify)
return m
})()
// MinifyHTMLWriter wraps the given io.Writer to minify the given html instead.
// The writer must be closed explicitly.
//
// Specific environments may chose to disable http minification, in which case MinifyHTMLWriter becomes the identity function.
func MinifyHTMLWriter(dest io.Writer) io.WriteCloser {
return minifier.Writer("text/html", dest)
}
// MinifyHTML minifies the html source.
// If an error occurs, returns the unmodified source instead.
func MinifyHTML(source []byte) []byte {
result, err := minifier.Bytes("text/html", source)
if err != nil {
return source
}
return result
}

View file

@ -5,7 +5,7 @@ import (
)
// Lazy holds a lazily initialized value of T.
// Lazy non-zero lazy must not be copied after first use.
// A non-zero lazy must not be copied after first use.
type Lazy[T any] struct {
once sync.Once