Webpack
概要
Webpack とは、モジュールバンドラーである。基本的な動きは、あるファイルからその依存ファイルを辿って依存グラフを作成し、それらをまとめて1つのファイルにバンドルする。 Webpack はスケーラブルな設定の記述が可能になるように設計されている。ある1つの設定ファイルが再利用可能であったり、他の設計と組み合わせて利用することができようになっている。これにより、環境やビルドターゲット、ランタイム毎に関心毎を分離させることができ、最終的には webpack-merge 等で設定をマージできる。 CLI
Webpack は JavaScript の Module をコンパイルするのに利用でき、CLI もしくは API (Node のインタフェース) 経由で利用できる。 概念
Entry
依存グラフを作成する際のエントリーポイント。Webpack はここから依存を辿っていき、全ての依存をパッケージングする。 Output
作成した バンドル を出力する場所。デフォルトでは ./dist/main.js。
Loaders
test プロパティは、Loader を適用するファイルを示す
use プロパティは、どの Loader を適用するかを示す
Plugins
Plugin は、Loader よりも広範囲なタスクを実施するために導入できる。例えば、バンドルの最適化や、アセット群の管理、環境変数の注入など。
Mode
development, production, none から選択できる。Webpack はモードによって異なる最適化を行う。デフォルトは production。 Entry
code:webpack.config.js
module.exports = {
entry: {
main: './path/to/my/entry/file.js'
}
};
// 上記の省略記法として、以下のように記述できる
module.exports = {
entry: './path/to/my/entry/file.js'
};
// 複数のエントリーポイントを記載する場合
module.exports = {
entry: {
app: './src/app.js',
adminApp: './src/adminApp.js'
}
};
Output
code:webpack.config.js
// 単一ファイルの出力
module.exports = {
output: {
filename: 'bundle.js',
}
};
// 複数のエントリーポイントが存在する場合、各ファイルが別名になるよう、substitution を利用すべき
module.exports = {
entry: {
app: './src/app.js',
search: './src/search.js'
},
output: {
path: __dirname + '/dist'
}
};
Modules
背景
Module という概念自体はプログラミングでは一般的で、各 Module は限られた影響範囲の中で動作し、個々の検証、デバッグ、テストが用意であり、特に良い Module はその詳細はカプセル化し、安定した抽象を提供する。
Node.js では初期から Modular programming がサポートされており、Web では多少導入が遅れたが、サポートするための様々なツールが、各々のメリット/デメリットを持って登場している。 Webpack はこれらの既存ツールを参考にして、プロジェクト内のあらゆるファイルに Module の概念を適用できるようにしている。 Module に依存する
...
Module の依存を解決する
上記のように記述された依存を解決するライブラリは、Resolver という。ある Module が他の Module (同一アプリ内のコードかもしれないし、サードパーティ製のライブラリかもしれない) を利用したい場合は、以下のように記述できる。
code:js
import foo from 'path/to/module';
// or
require('path/to/module');
enhanced-resolve では、3種類のファイルパスが解決できる。
code:.js
// 絶対パス
// resolver は特に解決のための処理を行う必要はない
import '/home/me/file';
import 'C:\\Users\\me\\file';
// 相対パス
// import, require が記載されたファイルが格納されたディレクトリが、context ディレクトリとして扱われ、
// import/require に context パスが追加され、絶対パスに変換される
import '../src/file1';
import './file2';
// モジュールパス
// resolve.module に定義された全てのディレクトリ内を探索する
import 'module';
import 'module/lib/file';
Resolver が上記のようにパスを解決すると、今度はそのパスに存在するのがファイルか?ディレクトリか?をチェックする。
ファイルだった場合
パスに拡張子が含まれていれば、ファイルをそのまま処理する
パスに拡張子が含まれていなければ、パスに存在するファイルが resolve.extensions オプションに記載されている拡張子と一致しているか?比較し、一致が存在すれば処理する
フォルダだった場合
このケースは、主にインポート対象が npm パッケージの場合になるはず
webpack.config.js 内の resolve.mainFields が利用される
resolve.mainFields に設定されているプロパティが package.json 内に存在するか、順に見ていき、見つかったらそこに記載されたパスを解決する フォルダに package.json が含まれていなかった場合 (あるいは resolve.mainFields の設定が不正だった場合) webpack.config.js 内の resolve.mainFiles内のパスがフォルダ内で探索される
ファイルの拡張子の解決は、「ファイルだった場合」と同様
Module を作成する
また、Module 自体の記述 も様々な言語で行える。
Targets
JavaScript はサーバサイドでもブラウザ上でも動作させることができる。target を指定するとで、異なるデプロイターゲット用にビルドが行える。 利用可能な target 一覧は以下にある。web, node, electron などがある。
環境変数
--env オプション
--env コマンドラインオプションを利用すると、webpack に 環境変数を渡すことができる。