小ネタ。
Electron が採用している Chromium は ECMAScript 対応がかなり進んでいる。よって Babel を使用しつつも変換を最小におさえたくなる。
この点について以前 babel-preset-env と minify という記事を書いたのだが、uglify-js の ES2015 以降への対応が暫定版なため、よりよい選択肢として babel-preset-babili を試してみた。その記事のコメントで mysticatea さんが提案されているように Browserify へ -g
オプションをつければ node_modules
部分も含めて minify 可能だが、それでも Browserify の Bundle 処理は minify されない。
よって uglify-js harmony 版が正式リリースされるのを待っていたところ、uglify-es が提供されたので試してみる。
uglify-es
従来 uglify-js で harmony と呼ばれていた ES2015 以降へ対応する仕向け。README によれば uglify-js@3.x
系に対して API と CLI 互換がある。CLI 名も uglifyjs
のまま。よって最新の uglify-js を使用しているなら、特に処理を変えず移行可能。
移行は package.json
の devDependencies
で uglify-js を uglify-es へ置き換えればよい。uglify-js@3.x
から提供となるので、バージョン系は 3.x 以降となる。安全のため npm un -D uglify-js
してから npm i -D uglify-es
するのがよいだろう。
余談だが Support UglifyJS 3 と関連 issue にて webpack の uglify-es 対応が検討されている。難航しているようだ。
babel-preset-env
uglify-es により ES2015 以降を解析可能となるため、Babel 変換も最小にする。babel-preset-env へ開発で使用している Electron のバージョンを指定。以下は package.json
の例。.babelrc
なら "babel"
プロパティの値をルートにする。
"babel": { "presets": [ [ "env", { "targets": { "electron": "1.6" } } ] ] }
この設定で akabekobeko/examples-electron のプロジェクトをビルドして class
、const
、let
といった ES2015 以降の機能はそのままに uglify-es で minify されることを確認できた。
問題点
uglify-es は ES2015 なら対応しているけれど async/await
を含むコードはエラーになる。試しに async function – JavaScript | MDN のサンプルを含めてみたところ、
Parse error at 0:2932,6 async function add1(x) { ^ ERROR: Unexpected token: keyword (function) at JS_Parse_Error.get (eval at <anonymous> (.../examples-electron/audio-player/node_modules/uglify-es/tools/node.js:21:1), <anonymous>:86:23) at fatal (.../examples-electron/audio-player/node_modules/uglify-es/bin/uglifyjs:286:52) at run (.../examples-electron/audio-player/node_modules/uglify-es/bin/uglifyjs:241:9) at Socket.<anonymous> (.../examples-electron/audio-player/node_modules/uglify-es/bin/uglifyjs:179:9) at emitNone (events.js:110:20) at Socket.emit (events.js:207:7) at endReadableNT (_stream_readable.js:1045:12) at _combinedTickCallback (internal/process/next_tick.js:102:11) at process._tickCallback (internal/process/next_tick.js:161:9)
となった。ちなみに Browserify も以前は es6 async class function fails to parse? という問題があったが修正済み。uglify-es の issue [ES8] async/await not supported also in harmony を読むに、近く修正されそうな気がする。
まとめ
async/await 対応の問題はあるものの、babel-preset-env + uglify-es の組み合わせで Electron 向けの Babel 変換を最小におさえられた。
Chrome Canary 60 はフラグ付きで ES Modules が有効になるそうで、これが Electron に採用されたら Bundle と minify 事情も変わりそう。しかし node_modules
も含めたサイズ圧縮の観点から Bundle と minify はしばらく必要な処理なので、今後も動向は継続的にチェックしたい。