Skip to content

Commit

Permalink
client/web: add support for zst precomppressed assets
Browse files Browse the repository at this point in the history
This will enable us to reduce the size of these embedded assets.

Updates tailscale/corp#20099

Signed-off-by: James Tucker <james@tailscale.com>
  • Loading branch information
raggi committed May 17, 2024
1 parent 8fa3026 commit c6cfb56
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 2 deletions.
30 changes: 29 additions & 1 deletion client/web/assets.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ import (
"strings"
"time"

"github.com/klauspost/compress/zstd"
prebuilt "github.com/tailscale/web-client-prebuilt"
"tailscale.com/tsweb"
)

var start = time.Now()
Expand Down Expand Up @@ -63,7 +65,33 @@ func assetsHandler(devMode bool) (_ http.Handler, cleanup func()) {
}), nil
}

func openPrecompressedFile(w http.ResponseWriter, r *http.Request, path string, fs fs.FS) (fs.File, error) {
type zstFile struct {
f fs.File
*zstd.Decoder
}

func newZSTFile(f fs.File) (*zstFile, error) {
zr, err := zstd.NewReader(f)
if err != nil {
return nil, err
}
return &zstFile{f: f, Decoder: zr}, nil
}

func (z *zstFile) Close() error {
z.Close()

Check warning on line 82 in client/web/assets.go

View workflow job for this annotation

GitHub Actions / lint

unconditional-recursion: unconditional recursive call (revive)
return z.f.Close()
}

func openPrecompressedFile(w http.ResponseWriter, r *http.Request, path string, fs fs.FS) (io.ReadCloser, error) {
if f, err := fs.Open(path + ".zst"); err == nil {
if tsweb.AcceptsEncoding(r, "zstd") {
w.Header().Set("Content-Encoding", "zstd")
return f, nil
}
return newZSTFile(f)
}
// TODO(raggi): remove this code path when no longer used
if f, err := fs.Open(path + ".gz"); err == nil {
w.Header().Set("Content-Encoding", "gzip")
return f, nil
Expand Down
6 changes: 5 additions & 1 deletion cmd/build-webclient/build-webclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,14 @@ func build(toolDir, appDir string) error {
if err := os.Remove(f); err != nil {
log.Printf("Failed to cleanup %q: %v", f, err)
}
// Removing intermediate ".br" version, we use ".gz" asset.
// Removing ".br" version, we use the ".zst" asset.
if err := os.Remove(f + ".br"); err != nil {
log.Printf("Failed to cleanup %q: %v", f+".gz", err)
}
// Removing ".gz" version, we use the ".zst" asset.
if err := os.Remove(f + ".gz"); err != nil {
log.Printf("Failed to cleanup %q: %v", f+".gz", err)
}
}

return nil
Expand Down
14 changes: 14 additions & 0 deletions util/precompress/precompress.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"path/filepath"

"github.com/andybalholm/brotli"
"github.com/klauspost/compress/zstd"
"golang.org/x/sync/errgroup"
"tailscale.com/tsweb"
)
Expand Down Expand Up @@ -63,6 +64,12 @@ type Options struct {
// OpenPrecompressedFile opens a file from fs, preferring compressed versions
// generated by PrecompressDir if possible.
func OpenPrecompressedFile(w http.ResponseWriter, r *http.Request, path string, fs fs.FS) (fs.File, error) {
if tsweb.AcceptsEncoding(r, "zstd") {
if f, err := fs.Open(path + ".zst"); err == nil {
w.Header().Set("Content-Encoding", "zstd")
return f, nil
}
}
if tsweb.AcceptsEncoding(r, "br") {
if f, err := fs.Open(path + ".br"); err == nil {
w.Header().Set("Content-Encoding", "br")
Expand Down Expand Up @@ -104,6 +111,13 @@ func Precompress(path string, options Options) error {
if err != nil {
return err
}
zstdLevel := zstd.WithEncoderLevel(zstd.SpeedBestCompression)
if options.FastCompression {
zstdLevel = zstd.WithEncoderLevel(zstd.SpeedFastest)
}
err = writeCompressed(contents, func(w io.Writer) (io.WriteCloser, error) {
return zstd.NewWriter(w, zstdLevel)
}, path+".zst", fi.Mode())
brotliLevel := brotli.BestCompression
if options.FastCompression {
brotliLevel = brotli.BestSpeed
Expand Down

0 comments on commit c6cfb56

Please sign in to comment.