Skip to content

Commit

Permalink
feat: brotli precompressed assets (resolve #284)
Browse files Browse the repository at this point in the history
  • Loading branch information
muety committed Dec 20, 2021
1 parent 7809c8f commit 07a367c
Show file tree
Hide file tree
Showing 11 changed files with 72 additions and 308 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,9 @@ $ yarn build # or: yarn watch

New icons can be added by editing the `icons` array in [scripts/bundle_icons.js](scripts/bundle_icons.js).

#### Precompression
As explained in [#284](https://github.com/muety/wakapi/issues/284), precompressed (using Brotli) versions of some of the assets are delivered to save additional bandwidth. This was inspired by Caddy's [`precompressed`](https://caddyserver.com/docs/caddyfile/directives/file_server) directive. `gzipped.FileServer` checks for every static file's `.br` or `.gz` equivalents and, if present, delivers those instead of the actual file, alongside `Content-Encoding: br`. Currently, compressed assets are simply checked in to Git. Later we might want to have this be part of a new build step.

## ❔ FAQs
Since Wakapi heavily relies on the concepts provided by WakaTime, [their FAQs](https://wakatime.com/faq) apply to Wakapi for large parts as well. You might find answers there.

Expand Down
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@ go 1.16

require (
github.com/BurntSushi/toml v0.4.1 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac
github.com/emersion/go-smtp v0.15.0
github.com/emvi/logbuch v1.2.0
github.com/felixge/httpsnoop v1.0.2 // indirect
github.com/getsentry/sentry-go v0.11.0
github.com/go-co-op/gocron v1.11.0
github.com/go-kit/kit v0.10.0 // indirect
github.com/go-openapi/spec v0.20.2 // indirect
github.com/gorilla/handlers v1.5.1
github.com/gorilla/mux v1.8.0
Expand All @@ -22,6 +20,7 @@ require (
github.com/jinzhu/configor v1.2.1
github.com/jinzhu/now v1.1.4 // indirect
github.com/leandro-lugaresi/hub v1.1.1
github.com/lpar/gzipped/v2 v2.0.2
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
github.com/mitchellh/hashstructure/v2 v2.0.2
Expand Down
303 changes: 4 additions & 299 deletions go.sum

Large diffs are not rendered by default.

13 changes: 11 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"embed"
"github.com/lpar/gzipped/v2"
"github.com/muety/wakapi/models"
"github.com/muety/wakapi/routes/relay"
"io/fs"
Expand All @@ -19,7 +20,7 @@ import (
"github.com/muety/wakapi/repositories"
"github.com/muety/wakapi/routes/api"
"github.com/muety/wakapi/services/mail"
"github.com/muety/wakapi/utils"
fsutils "github.com/muety/wakapi/utils/fs"
"gorm.io/gorm/logger"

"github.com/gorilla/mux"
Expand Down Expand Up @@ -244,7 +245,15 @@ func main() {
// https://github.com/golang/go/issues/43431
embeddedStatic, _ := fs.Sub(staticFiles, "static")
static := conf.ChooseFS("static", embeddedStatic)
fileServer := http.FileServer(utils.NeuteredFileSystem{Fs: http.FS(static)})

fileServer := gzipped.FileServer(fsutils.NewExistsHttpFs(
fsutils.ExistsFS{
Fs: fsutils.NeuteredFileSystem{
Fs: static,
},
}),
)

router.PathPrefix("/contribute.json").Handler(fileServer)
router.PathPrefix("/assets").Handler(fileServer)
router.PathPrefix("/swagger-ui").Handler(fileServer)
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
"build": "npm run build:icons && npm run build:tailwind",
"build:tailwind": "tailwindcss build -i static/assets/css/app.css -o static/assets/css/app.dist.css --minify",
"build:icons": "node scripts/bundle_icons.js",
"watch": "chokidar \"./views/**/*.html\" \"./static/assets/js/**/*.js\" \"./static/assets/css/**/*.css\" -i \"**/vendor/*\" -i \"**/*.dist.*\" -c \"npm run build\""
"build:all:compress": "npm run build && npm run compress",
"watch": "chokidar \"./views/**/*.html\" \"./static/assets/js/**/*.js\" \"./static/assets/css/**/*.css\" -i \"**/vendor/*\" -i \"**/*.dist.*\" -c \"npm run build\"",
"watch:compress": "chokidar \"./views/**/*.html\" \"./static/assets/js/**/*.js\" \"./static/assets/css/**/*.css\" -i \"**/vendor/*\" -i \"**/*.dist.*\" -c \"npm run build:all:compress\"",
"compress": "brotli -f static/assets/css/*.dist.css && brotli -f static/assets/js/*.dist.js"
},
"devDependencies": {
"@iconify/json": "^1.1.444",
Expand Down
Binary file added static/assets/js/icons.dist.js.br
Binary file not shown.
Binary file added static/assets/vendor/chart.min.js.br
Binary file not shown.
Binary file added static/assets/vendor/petite-vue.min.js.br
Binary file not shown.
Binary file added static/assets/vendor/seedrandom.min.js.br
Binary file not shown.
45 changes: 45 additions & 0 deletions utils/fs/exists.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package fs

import (
"io/fs"
"net/http"
"strings"
)

type ExistsFS struct {
Fs fs.FS
}

func (efs ExistsFS) Exists(name string) bool {
_, err := fs.Stat(efs.Fs, name)
return err == nil
}

func (efs ExistsFS) Open(name string) (fs.File, error) {
return efs.Fs.Open(name)
}

// ---

type ExistsHttpFS struct {
Fs ExistsFS
httpFs http.FileSystem
}

func NewExistsHttpFs(fs ExistsFS) ExistsHttpFS {
return ExistsHttpFS{
Fs: fs,
httpFs: http.FS(fs),
}
}

func (ehfs ExistsHttpFS) Exists(name string) bool {
if strings.HasPrefix(name, "/") {
name = name[1:]
}
return ehfs.Fs.Exists(name)
}

func (ehfs ExistsHttpFS) Open(name string) (http.File, error) {
return ehfs.httpFs.Open(name)
}
8 changes: 4 additions & 4 deletions utils/filesystem.go → utils/fs/neutered.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package utils
package fs

import (
"net/http"
"io/fs"
"path/filepath"
)

// https://www.alexedwards.net/blog/disable-http-fileserver-directory-listings

type NeuteredFileSystem struct {
Fs http.FileSystem
Fs fs.FS
}

func (nfs NeuteredFileSystem) Open(path string) (http.File, error) {
func (nfs NeuteredFileSystem) Open(path string) (fs.File, error) {
f, err := nfs.Fs.Open(path)
if err != nil {
return nil, err
Expand Down

0 comments on commit 07a367c

Please sign in to comment.