はじめに
Parcelというモジュールバンドラを触ってみたので、その備忘録になります。
結論から言いますと、機能がシンプルすぎて自分の実務での利用は難しいと感じました。
そのため、現時点(v1.1.0)ではwebpackの代わりにはならないです。
とは言えども、webpackと比べてビルドが楽なので、個人でちょっとしたコードを書いてビルドしたい時には便利なツールだと思いました。
本記事の目的は以下の通りです。
- Parcelの基本的な使い方を理解する。
- webpackとどんなところが異なるのかをざっくり理解する。
解説に利用しているコードの最終形態はGitHub上にあります。
本記事の前提や注意点
- v1.1.0時点で書いた記事になります。
- Parcelの使い方は公式ドキュメントの内容を、より丁寧に解説したものになります。そのため、公式ドキュメントで基礎が理解できるのであればこの記事を読む必要はありません。
- webpackなどのモジュールバンドラを触ったことがある人向けの記事のため、モジュールバンドラ自体の説明は省きます。
- webpackやモジュールバンドラの基礎について学習したい方はこちらの記事(webpack 入門)をご覧ください。
- 本記事ではParcelのことを「モジュールバンドラ」と説明しています。他の記事や公式では「ビルドツール」や「アプリケーションバンドラ」などと説明されていますが、言葉の意味合いはあまり変わらないです。とりあえず「複数のファイルを1つ(もしくは複数)にまとめてくれるツール」という認識さえあれば問題ありません。
Parcelとは
モジュールバンドラのこと。読み方はパーセル(のはず)。
- https://github.com/parcel-bundler/parcel(GitHub)
- Parcel(ドキュメント)
Parcelの特徴(webpackとの違いは何か)
Parcelには以下のような特徴がある。
- ビルド速度がwebpackと比べてかなり速い
-
webpack.config.js
のような設定ファイルが必要ない - JavaScript以外のファイル(HTMLなど)をエントリーポイントに指定できる
上記のようにwebpackの辛さ(設定ファイルの肥大化、規模が大きいとビルド速度が遅いなど)を解消しているモジュールバンドラ。
もちろん、辛さを解消したからと言って全ての点がwebpackより優れているわけではない。
ビルド速度がwebpackと比べてかなり速い
公式のベンチマークによると、キャッシュを利用するとwebpackの約8倍。
webpack.config.js
のような設定ファイルが必要ない
以下のようにエントリーポイントに対してparcelを実行すれば、ファイルがバンドルされる。
parcel app.js
JavaScript以外のファイル(HTMLなど)をエントリーポイントに指定できる
任意のファイルをエントリーポイントに指定できるらしいが、公式ではJavaScriptかHTMLファイルをエントリーポイントにすることはお勧めしていた。
Parcelを利用してみる
Parcelを利用してモジュールをバンドルしたファイルを出力してみる。
以下は出力までのイメージ図。
webpackの場合、cssや画像なども1つのJavaScriptファイルにまとめられて出力される。
一方でParcelの場合、依存関係を解決したファイルがそれぞれ出力される。
そのため、今回は4つのファイルが出力される。
Parcelのインストール
npmか、yarnでインストールできる。
npm install -g parcel-bundler
yarn global add parcel-bundler
ディレクトリ構成
今回Parcelを利用するディレクトリ構成は以下を前提とする。
.
├── .babelrc
├── package.json
├── public
└── src
├── scss
│ └── style.scss
├── images
│ └── parcel.png
├── index.html
└── js
├── app.js
└── modules
└── add.js
必要なパッケージのインストール
パッケージをローカルインストールするため、package.json
は以下のどちらかのコマンドで生成する。
npm init
yarn init
Babel
ES2015のコードをES5に変換するため、Babelをインストールする。
以下のどちらかのコマンドでインストール。
npm i babel-preset-env -D
yarn add babel-preset-env -D
次にBabelの設定ファイルである.babelrc
を設置する。
{
"presets": [
"env"
]
}
webpackではBabelで変換するために、babel-loader
をインストールし、webpack.config.js
にbabel-loader
を利用する設定を記述する必要があった。
一方Parcelは.babelrc
を検出するとBabelでの変換を自動的に実行するため、これでBabelを利用する準備はできた。
node-sass
scssをcssに変換するため、node-sassをインストールする。
以下のどちらかのコマンドでインストール。
npm i node-sass -D
yarn add node-sass -D
こちらもParcelが自動でnode-sassを利用して変換してくれるため、これで準備完了。
各ファイルの詳細
index.html
(エントリーポイント)
エントリーポイント。このファイルをエントリーポイントとしてparcel
コマンドを実行すると読み込んでいるapp.js
に対してもビルドが実行される。
<html>
<head>
<meta charset="utf-8">
<title>Parcel tutorial</title>
</head>
<body>
<h1>Parcel</h1>
<div class="parcel"></div>
<script src="js/app.js"></script>
</body>
</html>
app.js
add.js
を読みこんで数値を計算したり、style.css
を読み込んでHTMLにスタイル適用しているメインのJavaScriptファイル(webpackでいうエントリーポイント)。
import '../scss/style.scss';
import add from './modules/add';
const number1 = 400;
const number2 = 600;
const total = add(number1, number2);
console.log(total);
add.js
引数のnumber1
とnumber2
を合算して返すモジュール。
export default function add(number1, number2) {
return number1 + number2;
}
style.scss
index.html
に適用するスタイルが記述されたモジュール。
$baseColor: #000;
body {
background: $baseColor;
h1 {
margin: 0;
padding: 0;
color: #fff;
text-align: center;
}
.parcel {
width: 400px;
height: 374px;
margin: 0 auto;
background: url('../images/parcel.png');
}
}
parcel.png
style.scss
から読み込んでいる画像(モジュール)。
parcel
コマンドでバンドルされたファイルを出力
上記構成のpackage.json
が存在する階層でparcel
コマンドを実行すれば、バンドルされたファイルが出力される。
デフォルトだと、バンドルしたファイルはdist
ディレクトリに出力されるが、今回はpublic
ディレクトリに出力させたいため、以下のようにオプションをつけて実行する。
parcel src/index.html -d public
実行すると、以下のようにpublic
ディレクトリにバンドルされたファイルと.cache
ディレクトリにキャッシュファイルが出力される。
.
├── .babelrc
├── .cache
│ └── fd1fb8126031fa8d090710737434e806.json
├── package.json
├── public
│ ├── dddf7ef8a771ea836c5c4ad7d53dfb78.css
│ ├── dddf7ef8a771ea836c5c4ad7d53dfb78.js
│ ├── e55a1d909b7adad3efe4170b8bfee1d8.png
│ └── index.html
└── src
├── scss
│ └── style.scss
├── images
│ └── parcel.png
├── index.html
└── js
├── app.js
└── modules
└── add.js
バンドルされたファイルを確認する
出力されたindex.html
は以下の通り。
<html>
<head>
<meta charset="utf-8">
<title>Parcel tutorial</title>
<link rel="stylesheet" href="/public/dddf7ef8a771ea836c5c4ad7d53dfb78.css"></head>
<body>
<h1>Parcel</h1>
<div class="parcel"></div>
<script src="/public/dddf7ef8a771ea836c5c4ad7d53dfb78.js"></script>
</body>
</html>
同じくpublic
ディレクトリに出力されたdddf7ef8a771ea836c5c4ad7d53dfb78.css
を読み込む記述が追加されている。
また、dddf7ef8a771ea836c5c4ad7d53dfb78.js
を読み込んでおり、依存関係を解決していることがわかる。
バンドルされたファイル(ページ)をブラウザで確認する
parcel
コマンド実行時にサーバーも起動するため、http://localhost:1234/にアクセスしてバンドル後のindex.html
を確認できる。
コンソールは表示され、スタイルも適用され、画像も読み込まれているため、正常に動作していることがわかる。
また、ファイルはwatchされているため、以下のようにファイルの更新をすればリロードされる。
サーバーを起動せずにファイルだけwatchしたい場合は以下のようにコマンドを実行する。
parcel watch src/index.html -d public
webpackと比べてみてParcelはどうなのか(webpackの代わりになるのか)
ただ単純にバンドルされたファイルを出力されるまではwebpackより楽だった。
しかし、現時点(v1.1.0)では以下のような理由で自分の実務で利用するのは難しく、webpackの代わりにはならない。
- 出力先や出力するファイル名を指定できない
- 複数のhtml(エントリーポイント)から読み込む共通のバンドルファイルを出力できない
- webpackでいう
CommonsChunkPlugin
やexternals
などに該当する機能がない
出力先や出力するファイル名を指定できない
上記の例のように、依存関係を解決したファイルは全て同じディレクトリ(今回の例だとpublic
ディレクトリ)に出力される。
「画像やcssだけは別のディレクトリに出力する」などができない。
また、出力するファイル名も指定できない。
複数のhtml(エントリーポイント)から読み込む共通のバンドルファイルを出力できない
index.html
、about.html
、page.html
などの複数のhtml(エントリーポイント)から読み込む共通のバンドルファイルを出力できない。
そのため、処理は共通でもエントリーポイントの数に応じたバンドルファイルを出力する必要がある。
webpackでいうCommonsChunkPlugin
やexternals
などに該当する機能がない
CommonsChunkPluginやexternalsなど、実務で利用しているwebpackの様々な機能がParcelにはないため、Parcelを利用できない。
終わり
あくまでv1.1.0時点で書いた記事ですので、将来はもっと使いやすくなっている可能性もあります(機能が増えて結局複雑になる可能性もあります)。興味がある方はissuesやPull Requestを追うことをお勧めします。
まだまだwebpackを学習しても無駄ではないので、webpackを学習したい方はこちらの記事をどうぞ。