bundle assets

This commit is contained in:
Nazar Kanaev 2020-08-20 00:10:30 +01:00
parent bd43cb60f6
commit 4f6e9e5c7c
3 changed files with 132 additions and 3 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
yarr
*.db
server/assets_bundle.go

81
bundle.go Normal file
View File

@ -0,0 +1,81 @@
package main
import (
"bytes"
"compress/gzip"
"crypto/sha256"
"encoding/base64"
"fmt"
"io/ioutil"
"path/filepath"
"strings"
"text/template"
)
var code_template = `// autogenerated. do not edit!
package server
var assets_bundle = map[string]asset{
{{- range .}}
"{{.Name}}": {etag: "{{.Etag}}", body: "{{.Body}}"},
{{- end }}
}
func init() {
assets = assets_bundle
}
`
type asset struct {
Name, Etag, Body string
}
func shasum(b []byte) string {
h := sha256.New()
h.Write(b)
return fmt.Sprintf("%x", h.Sum(nil))[:16]
}
func encode(b []byte) string {
var buf bytes.Buffer
zw := gzip.NewWriter(&buf)
zw.Write(b)
zw.Close()
return base64.StdEncoding.EncodeToString(buf.Bytes())
}
func main() {
outfile := "server/assets_bundle.go"
assets := make([]asset, 0)
filepatterns := []string{
"assets/index.html",
"assets/graphicarts/*.svg",
"assets/graphicarts/*.png",
"assets/javascripts/*.js",
"assets/stylesheets/*.css",
"assets/stylesheets/*.map",
}
fmt.Printf("%8s %8s %s\n", "original", "encoded", "filename")
for _, pattern := range filepatterns {
filenames, _ := filepath.Glob(pattern)
for _, filename := range filenames {
content, _ := ioutil.ReadFile(filename)
assets = append(assets, asset{
Name: strings.TrimPrefix(filename, "assets/"),
Etag: shasum(content),
Body: encode(content),
})
fmt.Printf(
"%8d %8d %s\n",
len(content),
len(assets[len(assets)-1].Body),
filename,
)
}
}
var buf bytes.Buffer
template := template.Must(template.New("code").Parse(code_template))
template.Execute(&buf, assets)
ioutil.WriteFile(outfile, buf.Bytes(), 0644)
}

View File

@ -1,7 +1,10 @@
package server
import (
"bytes"
"encoding/json"
"encoding/base64"
"compress/gzip"
"fmt"
"github.com/nkanaev/yarr/storage"
"html"
@ -37,6 +40,36 @@ var routes []Route = []Route{
p("/page", PageCrawlHandler),
}
type asset struct {
etag string
body string // base64(gzip(content))
gzipped *[]byte
decoded *string
}
func (a *asset) gzip() *[]byte {
if a.gzipped == nil {
gzipped, _ := base64.StdEncoding.DecodeString(a.body)
a.gzipped = &gzipped
}
return a.gzipped
}
func (a *asset) text() *string {
if a.decoded == nil {
gzipped, _ := base64.StdEncoding.DecodeString(a.body)
reader, _ := gzip.NewReader(bytes.NewBuffer(gzipped))
decoded, _ := ioutil.ReadAll(reader)
reader.Close()
decoded_string := string(decoded)
a.decoded = &decoded_string
}
return a.decoded
}
var assets map[string]asset
type FolderCreateForm struct {
Title string `json:"title"`
}
@ -58,6 +91,9 @@ type ItemUpdateForm struct {
func IndexHandler(rw http.ResponseWriter, req *http.Request) {
t := template.Must(template.New("index.html").Delims("{%", "%}").Funcs(template.FuncMap{
"inline": func(svg string) template.HTML {
if asset, ok := assets["graphicarts/" + svg]; ok {
return template.HTML(*asset.text())
}
content, _ := ioutil.ReadFile("assets/graphicarts/" + svg)
return template.HTML(content)
},
@ -67,14 +103,25 @@ func IndexHandler(rw http.ResponseWriter, req *http.Request) {
}
func StaticHandler(rw http.ResponseWriter, req *http.Request) {
path := "assets/" + Vars(req)["path"]
f, err := os.Open(path)
path := Vars(req)["path"]
ctype := mime.TypeByExtension(filepath.Ext(path))
if assets != nil {
if asset, ok := assets[path]; ok {
rw.Header().Set("Content-Type", ctype)
rw.Header().Set("Content-Encoding", "gzip")
rw.Header().Set("Etag", asset.etag)
rw.Write(*asset.gzip())
}
}
f, err := os.Open("assets/" + path)
if err != nil {
rw.WriteHeader(http.StatusNotFound)
return
}
defer f.Close()
rw.Header().Set("Content-Type", mime.TypeByExtension(filepath.Ext(path)))
rw.Header().Set("Content-Type", ctype)
io.Copy(rw, f)
}