設定なしのバンドラー「Parcel」がWeb開発には最強の予感!だがしかし(期待を込めて)・・・
昨年末あたりから、よく聞くようになった「Parcel」を使いはじめました。
敷居が低くて簡単・便利。でも不安定な動作や実行時エラーに引っかかったりもしましたので、以下に紹介がてら対処法なども書いておきます。
現時点で、自分の知識不足や経験不足に起因する点があるかもしれません。 以下、おかしなことを書いていたら、コメント等で御教示ください。 よろしくお願いいたします m(_ _)m。
「Parcel」は、最近のWebアプリの開発でほぼ必須ツールと言ってよいバンドラー(およびタスクランナー)ですね。 なにが凄いって、常識破りの売り文句「設定不要」というところでしょう。
ワタシはこれまで Grunt+Browserify+Uglify でやっていまして、特にこだわりはないのですが、既に設定が固まっていて、「Grunt遅いよ」「Gulpが速いよ」「WebPackのほうが便利でしょ」などと聞いても、腰が重くて動じない。 新たなツールの新たな設定を覚えるのって邪魔くさいでしょ。そういうのが好きな人がいるのも知っているけどワタシ自身はそうではない。
そんなときに「Parcel は設定不要ですよー」と知って「それならば」と、新規のnpmで使ってみたら「めっちゃ便利ですやんコレ!スゲー!」となったわけです。 前述のように、まだ安定しない点もあるようですが、今後どんどん便利になっていくことを期待しつつてな感じで、以下どうぞー。
※ ちなみに本記事執筆時点のワタシの環境はこちらになります:
- OS: Windows 10 / MSYS2
- node: 8.10.0
- npm: 5.6.0
- devDependencies(parcel関連の一部)
- parcel-bundler: 1.9.7
- babel-plugin-transform-runtime; 6.23.0
- babel-runtime: 6.26.0
Parcelの凄いところ
Parcelの凄いところは、すでにたくさん紹介サイトがありますので、ここでは箇条書きにしておきます。 これ以外にもたくさんあると思います。
- 本当に設定不要(疑ってたわけじゃないけどホントに設定不要で驚いた)
- ソースを更新すると自動でビルド。
- HTTPサーバーが立ち上がっていて、ビルド後モジュールが置き換えられる(HMR - Hot Module Replacement)。
- ビルドはかなり速い気がする。2回目以降はキャッシュを使ってるんですよね。初回も速い気がしますけど。
- 最初からTypeScriptに対応している。
Parcelのいまいちなところ
決してダメだっつってんじゃありませんよ。 今後の改善に期待しつつ、ハマったことなどを書いています。 また、自分の開発環境に依存するところもあるのかも。
自動ビルドがおかしくなることがある。
困り事
長く自動ビルドを繰り返していると、ソースの変更が正しくビルド結果に反映されていないと感じることが何度かありました。 Parcelはキャッシュを利用して高速化を図っているようですが、その辺に何かあるんだと思います。
対処法
Parcelを強制停止して、出力ディレクトリと、キャッシュディレクトリを消去して再度Parcelを立ち上げれば正しい結果が得られました。
$ rm -r dist/ .cache/
ビルドエラーで自動ビルドが止まっちゃう?
困り事
複数ファイルを編集していて、ひとつのファイルを先に保存した時点では整合が取れていなくてエラーになっちゃうことがありますよね。 このとき、当然ビルドは失敗して、HMRでブラウザにエラーが表示されます。 しかし、ソースファイルをキチンと修正しても、ビルドが走ってくれません。
対処法
こちらも、とりあえずParcelを再起動すれば治ります。
それでもおかしいと感じる場合、 rm -r dist .cache
で出力ファイルとビルドキャッシュを消去して再起動ですね。
HMRがうまく動かないことがあります
困り事
どういう状況なのか詳細はまだわかっていないのですが、HMRが動いたタイミングで、ブラウザで延々エラーログが吐かれる状態になったりします。 単純にページをリロードしてくれるとよいのですけど。 それだと再読み込みに時間がかかるのかもしれませんが、動かないよりマシじゃないかと。
対処法
Webページをリロードします。大抵これでなんとかなりますが、それでもだめなら Parcelを再起動しましょう。 必要ならば出力ファイルとキャッシュクリア(ここまですることはないと思います)。
Asyncを使っていると実行時にエラーが出る
困り事
Asyncを使っていると、実行時に regeneratorRuntime is not defined
というエラーが発生します。
対処法
エラーメッセージでググったらGitHub の Issue#871 に解決法が載っていました。
以下のコマンドで、npmにbabelのランタイム?と変換プラグイン?をインストールし、
$ npm install --save-dev babel-plugin-transform-runtime babel-runtime
モジュールのルートに以下のbabelの設定ファイル? .babelrc
を追加すればとりあえずエラーはなくなります。
{ "plugins": [ ["transform-runtime", { "polyfill": false, "regenerator": true }] ] }
しかしワタシ Babel に詳しくないので、今のところ何がどうなってるのか理解していません(Regeneratorってなんでしょう?)。
そもそもAsync/Awaitをそのまま使うって選択肢はないのかな。
Babelのせい?でAsync関数がAsyncFunctionでなくなっちゃう
困り事
上の .babelrc でAsyncが使えるようになりましたけど、実行時にAsync関数の constructor.name が Function
のままなんです。
通常なら async宣言された関数の constructor.name は、 AsyncFunction
のはずなのですが。
何が困るってコールバックを呼び出すときに「 AsyncFunction
なら Async関数でラップして実行をawaitしたい」のですが、全部Functionになっているので同期できないんですよね。
対処法
こちら、今のところ解決法が見つかっていません。 ParcelではなくBabelの問題だと思っていますが。
Parcelの使い方
parcelをnpmにインストール
npmで使う場合、リポジトリ内で、npm install --save-dev parcel-bundler
でインストールして、
package.json の scripts に parcel を登録(以下参照)しておきます。
こうしておけばこのnpmの内部では npm run parcel <パラメータ>
でParcelを実行できます。
グローバルにインストールすれば parcel だけで実行できますが、npmの場合は、依存関係が明記されているほうが親切ですよね。
package.json
... "scripts": { "parcel": "parcel", "test": "mocha" } ...
ビルドする
例えば index.html をビルドするには、コマンドラインから以下のように実行するだけです。 (何がビルド対象かを明示するためにscriptsにindex.htmlまで指定したコマンドも登録しておくほうが良いかもしれません)。
$ npm run parcel index.html > package-name@1.0.0 parcel path/to/repo > parcel "index.html" Server running at http://localhost:1234 √ Built in 4.39s.
ビルド結果は ./dist/
以下に出力されます。
ビルドの前にWebサーバーが起動しており、http://localhost:1234/index.html
をブラウザで開けます。
ビルド後もparcelは動き続けており、ソースファイルが更新されると自動的にビルドされて、HMRでブラウザのアプリも更新されます。
あとがき
結局「設定なし」だけケチが付かず、もろ手を挙げて「最強!」とは言えない感じでもあります。 でもやっぱり設定ファイルを書いていないという点は、それだけでも最強といえるかも。 安定すれば「これしかないっ」て言いきっちゃうぞ。
ホント、現時点でもWebアプリの開発では使わない手はないと思います。 npm scriptsとのシンプルな構成が便利かな。
ワタシ自身、まだ使い始めでよくわかっていない点もあります。 他にもCSSの統合なども便利なようで、継続して追いかけていきたいと思っております。 今後、あっちゅう間に使いやすくなっていくんじゃないかな?