2018/05/08追記
記事内容をv1.1.0からv1.8.1に対応したものに更新しました。
はじめに
Parcelというモジュールバンドラを触ってみたので、その備忘録になります。
結論から言いますと、機能がシンプルすぎて自分の実務での利用は難しいと感じました。~~~~そのため、2017/12/10時点(v1.1.0)ではwebpackの代わりにはならないです。
2018/05/08時点でv1.8.1になり、様々な機能が追加されました。しかし現在もwebpackで利用している機能がParcelにはないため、実務での利用は難しいです。
とは言えども設定ファイルなしでReact、Vue、ES2015などをビルドできるようになっているため、個人でちょっとしたコードを書いてビルドしたい時はこちらを使っていくと便利だと思いました。
そのため
- webpackは多機能で痒いところまで手が届くモジュールバンドラ
- Parcelは細かい設定はできないが、ビルドがお手軽にできるモジュールバンドラ
という認識を持って、用途に合わせて使っていけば良いと思います。
本記事の目的は以下の通りです。
- Parcelの基本的な使い方を理解する。
- webpackとどんなところが異なるのかをざっくり理解する。
解説に利用しているコードの最終形態はGitHub上にあります。
https://github.com/hira777/parcel-tutorial
本記事の前提や注意点
- v1.8.1時点で書いた記事になります。
- Parcelの使い方は公式ドキュメントの内容を、より丁寧に解説したものになります。そのため、公式ドキュメントで基礎が理解できるのであればこの記事を読む必要はありません。
- webpackなどのモジュールバンドラを触ったことがある人向けの記事のため、モジュールバンドラ自体の説明は省きます。
- webpackやモジュールバンドラの基礎について学習したい方はこちらの記事(webpack 入門)をご覧ください。
- 本記事ではParcelのことを「モジュールバンドラ」と説明しています。他の記事や公式では「ビルドツール」や「アプリケーションバンドラ」などと説明されていますが、言葉の意味合いはあまり変わらないです。とりあえず「複数のファイルを1つ(もしくは複数)にまとめてくれるツール」という認識さえあれば問題ありません。
Parcelとは
モジュールバンドラのこと。読み方はパーセル(のはず)。
- https://github.com/parcel-bundler/parcel(GitHub)
- Parcel(ドキュメント)
Parcelの特徴(webpackとの違いは何か)
Parcelには以下のような特徴がある。
-
ビルド速度がwebpackと比べてかなり速い(webpack3時点なので、webpack4と比較すると速いかどうかは不明) -
webpack.config.js
のような設定ファイルが必要ない(一応webpack4も設定ファイルなしでビルドできるようになった) - JavaScript以外のファイル(HTMLなど)をエントリーポイントに指定できる
上記のようにwebpackの辛さ(設定ファイルの肥大化など)を解消しているモジュールバンドラ。
もちろん、辛さを解消したからと言って全ての点がwebpackより優れているわけではない。
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を利用するディレクトリ構成は以下を前提とする。
.
├── package.json
├── public
└── src
├── scss
│ └── style.scss
├── images
│ └── parcel.png
├── index.html
└── js
├── app.js
└── modules
└── add.js
必要なパッケージのインストール
パッケージをローカルインストールするため、package.json
は以下のどちらかのコマンドで生成する。今回はParcelが必要なパッケージ(scssをcssに変換するためのnode-sass)を自動でインストールしてくれるためpackage.json
を生成しておくだけで良い
npm init
yarn init
各ファイルの詳細
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でいうエントリーポイント)。
ES2015で記述されているが、ParcelがBabelのトランスパイルを自動でしてくれる。
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の代わりになるのか)
記事の冒頭でも記載したが、Parcelはwebpackのような細かい設定ができないため、webpackの代わりにはならない。具体的には以下の通り。
- 出力先や出力するファイル名を指定できない
複数のhtml(エントリーポイント)から読み込む共通のバンドルファイルを出力できない- webpackの
optimization.splitChunks
やexternals
などに該当する機能がParcelにはない
出力先や出力するファイル名を指定できない
上記の例のように、依存関係を解決したファイルは全て同じディレクトリ(今回の例だとpublic
ディレクトリ)に出力される。
「画像やcssだけは別のディレクトリに出力する」などができない。
また、出力するファイル名も指定できない。
複数のhtml(エントリーポイント)から読み込む共通のバンドルファイルを出力できない
index.html
、about.html
、page.html
などの複数のhtml(エントリーポイント)から読み込む共通のバンドルファイルを出力できない。
そのため、htmlをエントリーポイントとする場合、処理は共通でもエントリーポイントの数に応じたバンドルファイルを出力する必要がある。
2018/12/22 追記
申し訳ありません。こちら誤りでした。
以下のリポジトリで検証しましたが、記事を執筆した時点でのバージョンでもできました。
また、@shibukawaさんからコメントをいただいた通り、Code Splittingという機能を利用すれば、共通処理だけのバンドルファイルを出力することも可能です。
こちらもサンプルを置きましたのでご参照ください。
webpackのoptimization.splitChunks
やexternals
などに該当する機能がParcelにはない
optimization.splitChunksやexternalsなど、実務で利用しているwebpackの様々な機能がParcelにはない。
終わり
冒頭でも記載しましたが、Parcel自体は便利なビルドツールですので、用途に合わせて使っていけば良いと思います。
初めて記事を書いたv1.1.0からv1.8.1に至るまでに、様々な機能が追加されており、将来はより使いやすくなっている可能性もあります。
興味がある方は
などを追うことをお勧めします。
ということで、webpackを学習しても無駄ではないので、webpackを学習したい方はこちらの記事をどうぞ。
お知らせ
Udemy で webpack の講座を公開したり、Kindle で技術書を出版しています。
Udemy:
webpack 最速入門(10,800 円 -> 2,000 円)
Kindle(Kindle Unlimited だったら無料):
React Hooks 入門(500 円)
興味を持ってくださった方はご購入いただけると大変嬉しいです。よろしくお願いいたします。