調べてもパッと出てこなかったので自分用メモとして。
もっといいやり方があれば教えてください。
やりたいこと
各ディレクトリにある起点ファイルを元にバンドルしてそれぞれ吐き出したかった。
フォルダ構成
root/
├─ apps/
│ ├─ app1/
│ │ └─ index.ts <-個別でバンドルしたい!
│ │
│ └─ app2/
│ └─ index.ts <-個別でバンドルしたい!
└─ other/
理想の出力結果
root/
├─ apps/
│ ├─ app1/
│ │ ├─ index.ts
│ │ └─ index.bundle.js <-それぞれ吐き出してほしい!
│ └─ app2/
│ ├─ index.ts
│ └─ index.bundle.js <-それぞれ吐き出してほしい!
│
└─ other/
やり方
1. npm globでパターンにマッチしたファイルパスを動的に取得する。
globのインストール
npm i glob --save-dev
const glob = require("glob");
const pattern = "./apps/*/index.ts";
const filePaths = glob.sync(pattern);
2. マッチしたファイルパスを元にwebpackの構成ファイルに合わせてオブジェクトを組み立てる。
JavaScript歴は激浅なのでココは超絶適当です...。
//拡張子を除いたファイルパスを取得する関数
getBaseName = str => str.substring(0, str.lastIndexOf("."));
//拡張子を除くファイルパスをキー名としたオブジェクトを組み立てる
// { "file/path/to/index" : "file/path/to/index.ts" }
const entries = {};
for (const filePath of filePaths) {
const baseName = getBaseName(filePath);
entries[baseName] = filePath;
}
3. webpackの構成ファイルに組み立てたオブジェクトを指定する。
outputのfilenameに [name].bundle.js を指定するのがミソです。
[name]には先程組み立てたオブジェクトのキー名が展開されるので出力先が分岐します。
細かい仕様に関しては全く理解していません。。。
const path = require("path");
module.exports = {
mode: 'production',
devtool: 'source-map',
entry: entries, //組み立てたファイルパスを直接entryに指定する
output: {
path: path.resolve(__dirname),
filename: "[name].bundle.js" //[name]にパスが展開されて出力先が分岐する
},
module: {
...
}
};
完成形
webpack.config.js
const glob = require("glob");
const pattern = "./apps/*/index.ts";
const filePaths = glob.sync(pattern);
getBaseName = str => str.substring(0, str.lastIndexOf("."));
const entries = {};
for (const filePath of filePaths) {
const baseName = getBaseName(filePath);
entries[baseName] = filePath;
}
//ここから基本設定
const path = require("path");
module.exports = {
mode: 'production',
devtool: 'source-map',
entry: entries, //組み立てたファイルパスを直接entryに指定する
output: {
path: path.resolve(__dirname),
filename: "[name].bundle.js"
},
module: {
...
}
};
まとめ
やりたいことができてよかったです。webpackの構成ややこしすぎる...。