アカベコマイリ

HEAR NOTHING SEE NOTHING SAY NOTHING

babelify v7.2 を試す

2015/10/29 に JavaScript の Transpiler である Babel の 6.0.0 がリリースされた。

これまでの Babel はデフォルトで ES6 と React JSX 変換に対応していたが、これからはプラグイン化されたものを指定する形式になるのだという。Browserify 用 Babel の babelify も同様で、これを最新に更新してコンパイルを実行すると ES6 部分が SyntaxError になる。

$ npm run build:js-main

> electron-starter@1.0.4 build:js-main .../examples-electron/electron-starter
> browserify -t babelify ./src/js/main/Main.js --im --no-detect-globals --node -d | exorcist ./src/main.js.map > ./src/main.js

.../examples-electron/electron-starter/src/js/main/Main.js:1
import App from 'app';
^
ParseError: 'import' and 'export' may appear only with 'sourceType: module'
The code that you piped into exorcist contains no source map!
Therefore it was piped through as is and no external map file generated.

babel/babelify の README に記載されている対応方法を electron-starter で試す。このプロジェクトでは Browserify、watchify を package.json の npm-scripts から CLI で実行、そのなかで babelify を指定している。

関係する部分を抜粋。

{
  "scripts": {
    "build:js-main": "browserify -t babelify ./src/js/main/Main.js --im --no-detect-globals --node -d | exorcist ./src/main.js.map > ./src/main.js",
    "build:js-renderer": "browserify -t babelify ./src/js/renderer/App.js -d | exorcist ./src/bundle.js.map > ./src/bundle.js",
    "watch:js-main": "watchify -v -t babelify ./src/js/main/Main.js --im --no-detect-globals --node -o \"exorcist ./src/main.js.map > ./src/main.js\" -d",
    "watch:js-renderer": "watchify -v -t babelify ./src/js/renderer/App.js -o \"exorcist ./src/bundle.js.map > ./src/bundle.js\" -d",
    "release:js-main": "browserify -t babelify ./src/js/main/Main.js --im --no-detect-globals --node | uglifyjs -c warnings=false -d DEBUG=false > ./dist/src/main.js",
    "release:js-renderer": "browserify -t babelify ./src/js/renderer/App.js | uglifyjs -c warnings=false -d DEBUG=false > ./dist/src/bundle.js"
  }
}

環境構築にあたり、まずは babelify も含めたすべての npm を最新にする。この作業は npm-check-updates で実行した。

$ ncu -a

babelify     ^6.3.0  →   ^7.2.0
browserify  ^11.2.0  →  ^12.0.1

The following dependencies are satisfied by their declared version range, but the installed versions are behind. You can install the latest versions without modifying your package file by using npm update. If you want to update the dependencies in your package file anyway, use --upgradeAll.

react              ^0.14.0  →  ^0.14.2
react-dom          ^0.14.0  →  ^0.14.2
electron-packager   ^5.1.0  →   ^5.1.1
electron-prebuilt  ^0.34.0  →  ^0.34.2
esdoc               ^0.4.1  →   ^0.4.3
watchify            ^3.4.0  →   ^3.6.0

Upgraded .../examples-electron/electron-starter/package.json

ncu -apackage.jsondependencies に設定された全 npm の更新をチェック、最新版に書き換えてくれる。この後に npm i を実行することで node_modules 側も更新される。

次に ES6 と React JSX をコンパイルするための Babel プラグインをインストール。

$ npm i -D babel-preset-es2015 babel-preset-react

ややこしいのだが babelify は Babel の Browserify 用インターフェースで実体は Babel になる。そのため機能を追加する場合も babelify プラグインがあるわけではなく Babel プラグインを用意することになる。

コンパイルするための npm が揃ったので npm-scripts を修正。babelify の README にある CLI サンプルを元に以下のようにした。

{
  "scripts": {
    "build:js-main": "browserify -t [ babelify --presets [ es2015 react ] ] ./src/js/main/Main.js --im --no-detect-globals --node -d | exorcist ./src/main.js.map > ./src/main.js",
    "build:js-renderer": "browserify -t [ babelify --presets [ es2015 react ] ] ./src/js/renderer/App.js -d | exorcist ./src/bundle.js.map > ./src/bundle.js",
    "watch:js-main": "watchify -v -t [ babelify --presets [ es2015 react ] ] ./src/js/main/Main.js --im --no-detect-globals --node -o \"exorcist ./src/main.js.map > ./src/main.js\" -d",
    "watch:js-renderer": "watchify -v -t [ babelify --presets [ es2015 react ] ] ./src/js/renderer/App.js -o \"exorcist ./src/bundle.js.map > ./src/bundle.js\" -d",
    "release:js-main": "browserify -t [ babelify --presets [ es2015 react ] ] ./src/js/main/Main.js --im --no-detect-globals --node | uglifyjs -c warnings=false -d DEBUG=false > ./dist/src/main.js",
    "release:js-renderer": "browserify -t [ babelify --presets [ es2015 react ] ] ./src/js/renderer/App.js | uglifyjs -c warnings=false -d DEBUG=false > ./dist/src/bundle.js"
  }
}

改めてコンパイルを実行してみると、無事にコンパイルが通った。

$ npm run build:js-main

> electron-starter@1.0.4 build:js-main .../examples-electron/electron-starter
> browserify -t [ babelify --presets [ es2015 react ] ] ./src/js/main/Main.js --im --no-detect-globals --node -d | exorcist ./src/main.js.map > ./src/main.js

この対応が Windows 環境で有効なことも確認済み。

watchify に関する朗報

今回の確認で気づいたのだが watchify の -o オプションによる pipe 処理が Windows でも動作するようになっていた。関連しそうな issue と commit は以下だろうか。

従来は -o オプションの問題により Windows 環境を考慮するなら exorcist による Source Maps 生成を諦めるか gulp を採用しなければならなかった。しかし最新の watchify であれば -o がそのまま通る。今回の npm-scripts で Source Maps が生成されること、Developer Tools で Source Maps 参照とブレーク ポイントが機能することを確認できた。

watchify & exorcist が生成した Source Maps

すばらしい!

この対応により前に書いた gulp なしの Web フロントエンド開発 における Windows 対応の課題がすべて解決。喉につかえた小骨が取れた気分。動作を確認できたとき思わずガッツポーズをとってしまった。

watchify の README を読むと -o オプションの説明にはまだ not available on Windows と書いてあるけど、これもいずれ無くなるだろうか。

サンプル プロジェクト

今回の変更を以下のサンプル プロジェクトに反映。

npm-scripts の修正と一緒に Windows 用 npm-scripts 変更が不要になったので README の説明も訂正しておいた。