Parcel とは

Parcel は、ゼロ設定 をウリとした Web アプリバンドラーです。 React + TypeScript + SCSS + CSS Modules といった環境を自力でセットアップしようとすると なかなか大変な設定が必要 なのですが、Parcel を使うと、開発環境がサクサクッと完成します。
React プロジェクトを作成するときは、create-react-app を使って雛形を生成する方法もありますが、余計なファイルがたくさん作られたりして、あまり分かりやすいとは言えません。 そんなときは Parcel を使ってみると、そのシンプルさに驚くと思います。
Parcel を使うと、次のような機能がほとんど設定なしでいきなり使えます。 コマンドラインオプションの一覧 を見ると、どのような機能があるかをざっと把握することができます。
- 開発用の Web サーバー機能(HMR: Hot Module Replacement 対応)
- TypeScript の自動変換(HTML ファイルから直接ロードする記述が可能)
- PostCSS による CSS 生成(SCSS、ベンダープレフィックス)
- CSS ファイルのインポート (CSS Modules)
- JSON ファイルのインポート
- PNG ファイルのインポート
- Pug (Jade) による HTML 生成
- リリース用の minify
また、Parcel は Node モジュールの自動インストール機能を備えており、parcel
コマンドで開発用 Web サーバーを起動すると、自動的に依存モジュールをインストールしてくれます。
例えば、HTML ファイルから TypeScript ファイルを読み込んでいると、typescript
モジュールが自動的にインストールされます。
Parcel のインストール
Web サイト用のディレクトリを作成し、parcel
モジュールを開発用にインストールします。
$ mkdir myapp && cd myapp
$ npm init -y
$ npm install --save-dev parcel
これで、Parcel の開発用サーバーを起動したり、Web サイトコンテンツのビルドを行えるようになります。
TypeScript のインストールは Parcel による自動インストールに任せることができるので、ここでは手動ではインストールしないことにします。 明示的にインストールしておきたければ次のように実行しておきます。
$ npm install --save-dev typescript
parcel build
) を行う場合はデフォルトで無効になっています。
自動インストール機能は便利ですが、基本的には Node モジュールは明示的にインストールした方がよいかもしれません。
Parcel によって依存モジュールが自動インストールされるときは、package.json
の依存情報が更新されます。
更新された package.json
をコミットするのを忘れないようにしてください。Web サイトのコンテンツを用意する
Web サイトのコンテンツとして、適当な HTML ファイルと TypeScript ファイルを用意します。
ソースコードとなる HTML ファイルおよび TypeScript ファイルは、src
ディレクトリ以下に配置することにします。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>My App</title>
<script src="script/index.ts" async></script>
</head>
<body>
<div id="root"></div>
</body>
</html>
HTML ファイルの中から、直接 TypeScript ファイル (index.ts
) を読み込んでいる ことに注目してください。
このように記述しておくだけで、Parcel が自動的に TypeScript トランスパイルを実行し、HTML ファイルから正しい JavaScript ファイルを読み込むように変換してくれます。
下記の TypeScript コードは、上記の HTML ファイルから読み込むファイルです。
const root = document.getElementById('root') as HTMLElement;
root.innerText = 'Hello Parcel';
これくらいのコードであれば TypeScript にする必要はほとんどありませんが、ここでは TypeScript のトランスパイルが自動的に実行されることを示すために .js
ではなく .ts
ファイルを使用しています。
開発用 Web サーバーを起動する (parcel serve)
src
ディレクトリ以下に必要な HTML ファイルと TypeScript ファイルを作成したら、次のように parcel (parcel server)
コマンドを実行して、開発用の Web サーバーを起動します。
--open
オプションを付けると、自動的に Web ブラウザを開いてくれます。
ポート番号をデフォルトの 1234
から変更したい場合は、--port
オプションを使用してください。
$ npx parcel src/index.html --open
Server running at http://localhost:1234
✨ Built in 131ms.
この時点で、TypeScript モジュールがインストールされていない場合は、Parcel が自動的にインストールし、さらにトランスパイルまで実行してくれます。
変換後の HTML ファイルや JavaScript ファイルは、デフォルトで dist
ディレクトリに出力されます。
出力先のディレクトリを変更したい場合は、-d
オプションを使用します。
開発用の Web サーバーでは HMR (Hot Module Replacement) 機能が有効になっているので、TypeScript コード (index.ts
) の内容を変更すると、再起動なしで自動的に反映されます。
root.innerText = 'Hello Parcel'
の行を変更して、表示が変更されることを試してみてください。
開発用の Web サーバーでは、環境変数 NODE_ENV=development
が設定されます。
これを利用して、開発時のみ有効なコードブロックを記述できます。
if (process.env.NODE_ENV === 'development') {
// 開発中のみ有効なコード
}
デプロイ用にビルドする (parcel build)
parcel build
コマンドを実行すると、公開用の Web サーバーにデプロイするためのファイル群を作成します。
デフォルトの出力先が、parcel (serve)
で開発用サーバーを起動した場合と同じ dist
ディレクトリになっているので、ファイルが混在しないように、-d
オプションで出力先を変えておいた方がよいでしょう。
次の例では、出力先を build
ディレクトリに設定しています。
$ npx parcel build src/index.html -d build
✨ Built in 1.50s.
build/script.6d3c0223.js 1.18 KB 757ms
build/script.6d3c0223.js.map 280 B 2ms
build/index.html 193 B 693ms
あとは、build
ディレクトリ以下に生成されたファイル群を Web サーバーにデプロイするだけです。
parcel build
によるバンドル時には、デフォルトで HTML、CSS、JS ファイルの圧縮(改行削除や、変数名の簡略化)が有効になっています。
その他の特徴は、下記の公式ドキュメントを参照してください。
package.json にビルド用スクリプトを追加する
ここまでの例では、直接 parcel
コマンドを実行していましたが、npm のスクリプトとして登録しておくと便利です。
"scripts": {
"start": "parcel src/index.html --open",
"build": "rm -rf build && parcel build src/index.html -d build"
},
このように記述しておくと、npm start
で開発用サーバーの起動、npm run build
で本番用ビルドを行えるようになります。
parcel build
コマンドは、前回のビルド時に出力したファイルを削除してくれません。
余計なファイルがデプロイされてしまうのを防ぐため、上記のように build
スクリプトで古いファイルを削除しておくとよいでしょう。React (Preact) のセットアップ
次に React コンポーネント (.tsx
) を読み込めるようにしてみます。
React 関連の NPM パッケージは先に手動でインストールしておきます。 React 本体は Parcel による自動インストールに任せることもできるのですが、TypeScript の型定義ファイルは自動インストールしてくれないみたいです。
$ npm install --save react react-dom
$ npm install --save-dev @types/react @types/react-dom
ここでは、次のような簡単な App
コンポーネントを作って表示してみます。
JSX コードが含まれているので、拡張子を .tsx
にすることに注意してください。
import * as React from 'react';
export const App: React.FC = () => {
return <h1>Hello React</h1>;
};
index.ts
ファイルの拡張子も .tsx
に変更し、上記の App
コンポーネントを読み込んで使用します。
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { App } from './components/App';
ReactDOM.render(<App />, document.getElementById('root'));
最後に index.html
ですが、index.ts
ではなく index.tsx
を読み込むようにするところだけ変更します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>My App</title>
<script src="script/index.tsx" async></script>
</head>
<body>
<div id="root"></div>
</body>
</html>
あとは何も設定しなくても、次のようにおもむろに Parcel の開発用サーバを起動するだけで、React を使った Web サイトが表示されます。
$ npm start
本当に「ゼロ設定」ですね! こんなに簡単でよいのでしょうか。
おまけ:SCSS の有効化
生の CSS をゴリゴリ記述するのはつらいので、SCSS は使えるようにしておいた方がよいでしょう。 Parcel で SCSS を使用するには、ちょっとだけ設定が必要です。
Parcel で SCSS を使うための設定
公式サイト の記述通りですが、次のように sass
モジュールをインストールし、
$ npm install --save-dev sass
下記のような設定ファイル (.sassrc
) をプロジェクトルートに配置すれば OK です。
{
"includePaths": ["node_modules"]
}
SCSS を使ってみる
次のような簡単な SCSS ファイルを使ってみます。
$BG_COLOR: yellow;
.app-title {
background: $BG_COLOR;
}
あとは、HTML ファイルから次のように参照しておけば、
<link rel="stylesheet" href="css/main.scss">
React コンポーネント (.tsx
) から次のように CSS クラスを参照できるようになります。
import * as React from 'react';
export const App: React.FC = () => {
return <h1 className="app-title">Hello React</h1>
};
index.html
の中でスタイルシートを読み込むのではなく、.tsx
の中でインポートして参照することもできます。
この場合は、.tsx
ファイルのあるディレクトリからの相対パスになることに注意してください。
CSS クラスの使用方法は上記と同様です。
import '../../css/main.scss';
ただ、このように .tsx
ファイルの中から CSS ファイルをインポートするのであれば、下記の CSS Modules の仕組みを使って、そのコンポーネント専用の CSS ファイルをインポートするようにした方がよいでしょう。
おまけ:CSS Modules の有効化
CSS Modules の仕組みを使用するときも、ちょっとだけ設定が必要です。
Parcel で CSS Modules を使うための設定
ほぼ 公式サイトの説明 通りですが、postcss-modules
のインストールが必要です。
$ npm install --save-dev postcss-modules
そして、プロジェクトルートに次のような設定ファイル (.postcssrc
) を配置します。
{
"modules": true
}
CSS Modules を使ってみる
CSS Modules の仕組みでスタイル定義する場合は、React コンポーネントと同じディレクトリに .css
ファイル(あるいは .scss
ファイル)を置いておくと、コンポーネントとしてのまとまりがよくなります。
前述の SCSS の設定を行っておけば、.scss
ファイルも CSS Modules の仕組みで読み込むことができます。
下記の App.scss
ファイルでは、App
コンポーネント用のスタイル定義を行っています。
CSS Modules の仕組みを使うと、CSS クラス名の名前空間がファイルごとに分離されるため、シンプルなクラス名を付けることができます。
.title {
background: red;
}
ここでは、app-title
というクラス名から app
プレフィックスを省略して、title
というシンプルなクラス名に変更してみました。
モジュール化されたスタイシートは、.tsx
ファイルから次のように使用します。
import * as React from 'react';
import styles from './App.scss';
export const App: React.FC = () => {
return <h1 className={styles.title}>Hello React</h1>
};
おまけ: favicon の設定
エントリポイントとなる index.html
の head
要素の中に、次のように favicon 設定をしておくと、Parcel によるサイトビルド時に自動的に favicon ファイルがコピーされます。
<link rel="icon" type="image/png" href="assets/img/favicon-32x32.png" />
favicon ファイルは、この index.html
からの相対パスで配置します。
今回は index.html
を src
ディレクトリ以下に置くことにしたので、favicon ファイルを src/assets/img/favicon-32x32.png
というパスで配置します。