// minify.go compacts quarry's scripts once, at start, on the embedded
// sources, before their content hashes are taken.
//
// The sources in assets/ are written to be read — comments, long names,
// indentation — and every byte of that went to every browser on its
// first visit. Measured on the served files: onerror.js 2,343 gzipped
// bytes to 788, activity.js 7,180 to 4,043. A page's scripts halve.
// The stylesheet is not here: leanCSS already takes its comments and
// indentation, a full minifier would save a further 7% of 28KB, and
// the tests that guard the sheet's structure read the lean form. Nothing
// runs per request and nothing runs at build: the deploy stays
// `go build`.
//
// Deterministic for a given source and library version, which the
// immutable content-hashed URLs depend on: every node of a forge mints
// the same name for the same bytes.
package web
import (
"log"
"os"
"github.com/tdewolff/minify/v2"
"github.com/tdewolff/minify/v2/js"
)
// assetsRaw serves the sources as written. A developer editing a
// script wants to see the file they edited in the browser, not its
// compact twin; set QUARRY_ASSETS_RAW=1 for that. Off in every normal
// build, and a test says so.
var assetsRaw = os.Getenv("QUARRY_ASSETS_RAW") != ""
var minifier = func() *minify.M {
m := minify.New()
m.AddFunc("text/javascript", js.Minify)
return m
}()
// compact returns the served form of one asset. A source the minifier
// cannot parse is served as written and logged: a syntax slip must
// reach the exceptions page as a client error, never take the asset
// down with it. The unit test runs every asset through here and fails
// on the same error, so the slip is caught before it is deployed.
func compact(mediatype, name string, src []byte) []byte {
if assetsRaw {
return src
}
out, err := minifier.Bytes(mediatype, src)
if err != nil {
log.Printf("web: %s served as written: minify: %v", name, err)
return src
}
return out
}
// compactJS and compactCSS name the two media types once.
func compactJS(name string, src []byte) []byte { return compact("text/javascript", name, src) }
func compactCSS(name string, src string) string {
return string(compact("text/css", name, []byte(src)))
}