Open17

JavaScriptにおけるバンドルサイズの最適化を色々調べる&試す

kobakazu0429kobakazu0429

terser

https://terser.org/

よく聞くやつ

It removes comments, makes variable names smaller, and removes whitespace.
Some variable references and function calls can be inlined into the places they're used.

kobakazu0429kobakazu0429

swc

https://swc.rs/

最近よく聞くやつ

  • Compilation
  • Bundling (swcpack, under development)
  • Minification
  • Transforming with WebAssembly
  • Usage inside webpack (swc-loader)
  • Improving Jest performance (@swc/jest)

terserはminifyのみだが、swcは色々できるのか

kobakazu0429kobakazu0429

ベンチマーク

それぞれのベンチが見たい
適当にネットで調べると次が出た

https://github.com/privatenumber/minification-benchmarks#-results

tdewolff-minify

https://github.com/tdewolff/minify

初めて知った
圧縮率はまだまだだが、とにかく早い

google-closure-compiler

めちゃくちゃ頑張るので遅いけど、圧縮率はいいって聞いたことがある(要出典)
初めてベンチを見たけど、正直遅くてもプロダクションビルドならば圧縮率優先でもいい気がした
あんまり使われているのを聞かない気がするけどなんでだろう

kobakazu0429kobakazu0429

gzip

ハフマン符号化で圧縮していて、CDNとかで配信する際に圧縮に使っている、はず、というぐらいの認識

brotli

Googleが作ってる、辞書を持ってるのでgzipより圧縮率がいいやつ、という認識

kobakazu0429kobakazu0429

ベンチまとめ

  • swc:Minzipped sizeで見ると多くの場合で優勢
  • terser:swcに勝つこともある
  • google-closure-compiler:向き不向きがありそう
  • uglify-js:今は使われていないはず

→swcで色々試そうと思う

kobakazu0429kobakazu0429

https://speakerdeck.com/mizchi/bandoruzui-shi-hua-maniakusu-at-tfconf?slide=29

in

- enum COLOR {
+ const enum COLOR {
   RED,
   GREEN,
   BLUE
 }

 const STOP_COLOR = COLOR.RED;
 console.log(STOP_COLOR);

out(preserveConstEnums: true)

"use strict";
var COLOR;
(function (COLOR) {
    COLOR[COLOR["RED"] = 0] = "RED";
    COLOR[COLOR["GREEN"] = 1] = "GREEN";
    COLOR[COLOR["BLUE"] = 2] = "BLUE";
})(COLOR || (COLOR = {}));
const STOP_COLOR = 0 /* COLOR.RED */;
console.log(STOP_COLOR);

out(preserveConstEnums: false)

"use strict";
const STOP_COLOR = 0 /* COLOR.RED */;
console.log(STOP_COLOR);

https://www.typescriptlang.org/play?target=99&jsx=0&preserveConstEnums=true&noEmitHelpers=true#code/MYewdgzgLgBApmArgWxgYQPIBkMCUYDeAUDDLgKIAiANCTAOIXkBytpAQlgKrlEC+RIqEiwAygBUMABQD6mHPgC86bHgB0FSgG4h4CCAA2cNQZABzABQTpc1bgCUWoA

enum使うと爆発するのは知ってたけど、const enumにしてpreserveConstEnums: falseならばenumでもOKなのか


in

const enum COLOR {
  RED,
  GREEN,
  BLUE
}

console.log(COLOR[COLOR.BLUE]);

out(preserveConstEnums: false)

"use strict";
console.log(COLOR[2 /* COLOR.BLUE */]);

https://www.typescriptlang.org/play?target=99&jsx=0&ssl=8&ssc=1&pln=1&pc=1&preserveConstEnums=true&noEmitHelpers=true#code/MYewdgzgLgBApmArgWxgYQPIBkMCUYDeAUDDLgKIAiANCTAOIXkBytpAQlgKrlEC+RIqEggANnAB0okAHMAFJhy4A2orwTOPALoBKANxEgA

でもこういう書き方するとダメなのか

kobakazu0429kobakazu0429

tslib

https://speakerdeck.com/mizchi/bandoruzui-shi-hua-maniakusu-at-tfconf?slide=32

存在は知ってるけど、なんであるのかは知らないので調べる

本体

https://github.com/microsoft/tslib/blob/main/tslib.js

https://mizchi.dev/202008081732-effect-by-tslib

tldr

  • target: es2017 以降なら tslib 使っても置き換えられるコードはないので、使う必要はない
  • target: es5/es2015 で async await を多く使っている場合はファイル数に比例して削れる

なるほど

kobakazu0429kobakazu0429

「import * as を避ける」べきなのか

https://zenn.dev/link/comments/e8825d1e4d35e9

「import * as」の名前を調べようと思ったらアンサー記事が見つかってしまった

https://qiita.com/uhyo/items/842e51e0d8cc46856d04


一応自分でも確かめる

https://github.com/kobakazu0429/swc-minify-example

cloneしてyarn install && yarn buildすると、webpackでbundleしたものと、swcでminifyしたものが出る

次はその様子

$ yarn build
  yarn run v1.22.19
  $ yarn bundle && yarn minify
  $ webpack build
  $ swc bundled -d minified
  Successfully compiled: 2 files with swc (89.97ms)
  ✨  Done in 3.68s.

$ find bundled minified -type f -exec sh -c "ls -l {}" \;
-rw-r--r--  1 kazu  staff  115395  5 27 01:33 bundled/alias.js
-rw-r--r--  1 kazu  staff  115399  5 27 01:33 bundled/named.js
-rw-r--r--  1 kazu  staff  25950  5 27 01:46 minified/alias.js
-rw-r--r--  1 kazu  staff  25954  5 27 01:46 minified/named.js

ファイルサイズを比較するとほとんど一緒(4文字だけ違っている)


結果的に、「import * as」は常に避けるべきではなさそう

問題になるとしたらここだけ?
https://qiita.com/uhyo/items/842e51e0d8cc46856d04#補足-メソッド呼び出しの場合