|
@@ -18,6 +18,7 @@ type app struct {
|
|
|
store *Store
|
|
store *Store
|
|
|
config *configFile
|
|
config *configFile
|
|
|
pages map[string]*template.Template
|
|
pages map[string]*template.Template
|
|
|
|
|
+ assets map[string]string // static file -> content hash
|
|
|
about template.HTML
|
|
about template.HTML
|
|
|
siteURL string // absolute base URL, no trailing slash
|
|
siteURL string // absolute base URL, no trailing slash
|
|
|
siteName string
|
|
siteName string
|
|
@@ -34,6 +35,10 @@ func newApp(contentDir, siteURL string) (*app, error) {
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return nil, err
|
|
return nil, err
|
|
|
}
|
|
}
|
|
|
|
|
+ assets, err := assetHashes()
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return nil, err
|
|
|
|
|
+ }
|
|
|
md := newMarkdown()
|
|
md := newMarkdown()
|
|
|
var about bytes.Buffer
|
|
var about bytes.Buffer
|
|
|
if err := md.Convert(aboutMarkdown, &about); err != nil {
|
|
if err := md.Convert(aboutMarkdown, &about); err != nil {
|
|
@@ -43,6 +48,7 @@ func newApp(contentDir, siteURL string) (*app, error) {
|
|
|
store: NewStore(contentDir, md),
|
|
store: NewStore(contentDir, md),
|
|
|
config: newConfigFile(filepath.Join(contentDir, "site.json")),
|
|
config: newConfigFile(filepath.Join(contentDir, "site.json")),
|
|
|
pages: pages,
|
|
pages: pages,
|
|
|
|
|
+ assets: assets,
|
|
|
about: template.HTML(about.String()),
|
|
about: template.HTML(about.String()),
|
|
|
siteURL: siteURL,
|
|
siteURL: siteURL,
|
|
|
siteName: u.Host,
|
|
siteName: u.Host,
|
|
@@ -67,7 +73,13 @@ func (a *app) routes() http.Handler {
|
|
|
a.notFound(w, r)
|
|
a.notFound(w, r)
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
- w.Header().Set("Cache-Control", "public, max-age=3600")
|
|
|
|
|
|
|
+ // A URL carrying the file's current hash never changes content, so it
|
|
|
|
|
+ // can be cached for a year; anything else gets an hour.
|
|
|
|
|
+ cache := "public, max-age=3600"
|
|
|
|
|
+ if v := r.URL.Query().Get("v"); v != "" && v == a.assets[strings.TrimPrefix(r.URL.Path, "/static/")] {
|
|
|
|
|
+ cache = "public, max-age=31536000, immutable"
|
|
|
|
|
+ }
|
|
|
|
|
+ w.Header().Set("Cache-Control", cache)
|
|
|
files.ServeHTTP(w, r)
|
|
files.ServeHTTP(w, r)
|
|
|
})
|
|
})
|
|
|
mux.HandleFunc("/", a.notFound)
|
|
mux.HandleFunc("/", a.notFound)
|