JavaScript
入門
webpack
parcel

Parcel 入門 ~Parcelはwebpackの代わりになるのか~

2018/05/08追記

記事内容をv1.1.0からv1.8.1に対応したものに更新しました。

はじめに

Parcelというモジュールバンドラを触ってみたので、その備忘録になります。

webpack時代の終わりと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とは

モジュールバンドラのこと。読み方はパーセル(のはず)。

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を利用してモジュールをバンドルしたファイルを出力してみる。
以下は出力までのイメージ図。

parcel-image.png

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に対してもビルドが実行される。

src/index.html
<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のトランスパイルを自動でしてくれる。

src/js/app.js
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

引数のnumber1number2を合算して返すモジュール。

src/js/modules/add.js
export default function add(number1, number2) {
  return number1 + number2;
}

style.scss

index.htmlに適用するスタイルが記述されたモジュール。

src/scss/style.scss
$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は以下の通り。

public/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を確認できる。

parcel2.jpg

コンソールは表示され、スタイルも適用され、画像も読み込まれているため、正常に動作していることがわかる。

また、ファイルはwatchされているため、以下のようにファイルの更新をすればリロードされる。

watch.gif

サーバーを起動せずにファイルだけwatchしたい場合は以下のようにコマンドを実行する。

parcel watch src/index.html -d public

webpackと比べてみてParcelはどうなのか(webpackの代わりになるのか)

記事の冒頭でも記載したが、Parcelはwebpackのような細かい設定ができないため、webpackの代わりにはならない。具体的には以下の通り。

  • 出力先や出力するファイル名を指定できない
  • 複数のhtml(エントリーポイント)から読み込む共通のバンドルファイルを出力できない
  • webpackのoptimization.splitChunksexternalsなどに該当する機能がParcelにはない

出力先や出力するファイル名を指定できない

上記の例のように、依存関係を解決したファイルは全て同じディレクトリ(今回の例だとpublicディレクトリ)に出力される。
「画像やcssだけは別のディレクトリに出力する」などができない。
また、出力するファイル名も指定できない。

複数のhtml(エントリーポイント)から読み込む共通のバンドルファイルを出力できない

index.htmlabout.htmlpage.htmlなどの複数のhtml(エントリーポイント)から読み込む共通のバンドルファイルを出力できない。
そのため、htmlをエントリーポイントとする場合、処理は共通でもエントリーポイントの数に応じたバンドルファイルを出力する必要がある。

webpackのoptimization.splitChunksexternalsなどに該当する機能がParcelにはない

optimization.splitChunksexternalsなど、実務で利用しているwebpackの様々な機能がParcelにはない。

終わり

冒頭でも記載しましたが、Parcel自体は便利なビルドツールですので、用途に合わせて使っていけば良いと思います。

初めて記事を書いたv1.1.0からv1.8.1に至るまでに、様々な機能が追加されており、将来はより使いやすくなっている可能性もあります。

興味がある方は

などを追うことをお勧めします。

ということで、webpackを学習しても無駄ではないので、webpackを学習したい方はこちらの記事をどうぞ。

webpack 4入門