Skip to content

Commit

Permalink
JS: use average character frequency of sample of JS files for variabl…
Browse files Browse the repository at this point in the history
…e renaming, reduces GZIP size
  • Loading branch information
tdewolff committed Jan 4, 2022
1 parent fb5ce73 commit f2684cf
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 11 deletions.
9 changes: 5 additions & 4 deletions js/js.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ var DefaultMinifier = &Minifier{}

// Minifier is a JS minifier.
type Minifier struct {
Precision int // number of significant digits
KeepVarNames bool
NoNullishOperator bool
Precision int // number of significant digits
KeepVarNames bool
useAlphabetVarNames bool
NoNullishOperator bool
}

// Minify minifies JS data, it reads from r and writes to w.
Expand Down Expand Up @@ -56,7 +57,7 @@ func (o *Minifier) Minify(_ *minify.M, w io.Writer, r io.Reader, _ map[string]st
m := &jsMinifier{
o: o,
w: w,
renamer: newRenamer(!o.KeepVarNames),
renamer: newRenamer(!o.KeepVarNames, !o.useAlphabetVarNames),
}
m.hoistVars(&ast.BlockStmt)
ast.List = m.optimizeStmtList(ast.List, functionBlock)
Expand Down
4 changes: 2 additions & 2 deletions js/js_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,7 @@ func TestJSVarRenaming(t *testing.T) {
}

m := minify.New()
o := Minifier{}
o := Minifier{useAlphabetVarNames: true}
for _, tt := range jsTests {
t.Run(tt.js, func(t *testing.T) {
r := bytes.NewBufferString(tt.js)
Expand Down Expand Up @@ -804,7 +804,7 @@ func TestWriterError(t *testing.T) {
}

func TestRenamerIndices(t *testing.T) {
renamer := newRenamer(true)
renamer := newRenamer(true, true)
for _, i := range []int{0, 1, 2, 53, 54, 55, 117, 118} {
name := renamer.getName([]byte{' '}, i)
j := renamer.getIndex(name)
Expand Down
15 changes: 10 additions & 5 deletions js/vars.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,28 @@ import (
"github.com/tdewolff/parse/v2/js"
)

// TODO: use character frequency for variable name mangling to improve gzip compression

type renamer struct {
identStart []byte
identContinue []byte
reserved map[string]struct{}
rename bool
}

func newRenamer(rename bool) *renamer {
func newRenamer(rename, useCharFreq bool) *renamer {
reserved := make(map[string]struct{}, len(js.Keywords))
for name := range js.Keywords {
reserved[name] = struct{}{}
}
identStart := []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$")
identContinue := []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$0123456789")
if useCharFreq {
// sorted based on character frequency of a collection of JS samples (incl. the var names!)
identStart = []byte("etnsoiarclduhmfpgvbjy_wOxCEkASMFTzDNLRPHIBV$WUKqYGXQZJ")
identContinue = []byte("etnsoiarcldu14023hm8f6pg57v9bjy_wOxCEkASMFTzDNLRPHIBV$WUKqYGXQZJ")
}
return &renamer{
identStart: []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$"),
identContinue: []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$0123456789"),
identStart: identStart,
identContinue: identContinue,
reserved: reserved,
rename: rename,
}
Expand Down

0 comments on commit f2684cf

Please sign in to comment.