Skip to content
quarry Artifact [868775ab80]
Login

Artifact [868775ab80]

Artifact 868775ab8024b2489504094eba465971f2bbdc8cde80cdc6088cfe7078b547cf:


// 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)))
}