Scss に続いて JS でも動的に読み込むファイルを切り替えたいと考えました。
今回の方法
ディレクトリ構造
サンプルとして、以下のようなディレクトリ構造にしたとします。
/
├ dist/
│ └ js/
│ ├ app.min.js // app.js からビルド
│ └ parts.min.js // parts/ ディレクトリ下のjsをバンドル
└ src/
└ js/
├ app.js
│
└ parts/
├ parts1.js // 単独
├ parts2.js // parts3.js に依存
└ parts3.js
src/js/app.js
: (存在すれば)常に出力、通常の処理dist/js/app.min.js
にビルド
src/js/parts/
ディレクトリ下: フラグによって動的に読み込むファイルを切り替えるdist/js/parts.min.js
にバンドル
状況的にはこのようにしたいと考えています。
webpack.config.js
以上を踏まえて webpack.config.js
。
const webpackTerser = require('terser-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const path = require('path');
const glob = require('glob');
const devFlag = true;
// dynamic import test
const partsPath = 'src/js/parts';
const flag = {
parts1: true,
parts2: true
};
const entry = () => {
const entries = glob
.sync(
'**/*.js',
{
cwd: 'src/js',
//ignore
ignore: [
'parts/**/*.js',
'**/_*.js'
]
}
)
.map(function (key) {
return [key, path.resolve('src/js', key)];
});
// `{ 'app.js': 'PATH/TO/PROJECT/src/js/app.js' }` のようなオブジェクトを entriesObj とする
let entriesObj = Object.fromEntries(entries);
// 以下、 parts に関する処理
partsCount = 0;
// flag の中で true になっている個数をカウント
Object.keys(flag).forEach(function (index) {
if (flag[index]) {
partsCount++;
}
});
if (partsCount > 0) {
// flag の中で true になっている個数が少なくとも1つある場合は、 `parts.js` キーを entriesObj に追加
entriesObj[`parts.js`] = [];
// entriesObj の `parts.js` キー に配列で複数のファイル (parts1.js, parts2.js) を指定
Object.keys(flag).forEach(function (index) {
if (flag[index]) {
entriesObj[`parts.js`].push(path.resolve(partsPath, `${index}.js`));
}
});
}
return entriesObj;
};
const configs = {
mode: development,
entry: entry(),
output: {
filename: '[name]',
},
devtool: 'inline-source-map',
plugins: [
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: [
'dist/js/**/*.js'
],
}),
],
optimization: {
minimizer: [
new webpackTerser({
extractComments: 'some',
terserOptions: {
compress: {
drop_console: false,
},
},
}),
],
},
};
module.exports = configs;
- エントリーポイントには
glob.sync
から始まる処理で指定src/js
下 の.js
ファイルを{ 'app.js': 'PATH/TO/PROJECT/src/js/app.js' }
のようにキーはファイル名、値がファイルへのフルパス、となるようなオブジェクトを作っていますignore
でsrc/js/parts/
下 は最初は除外しています- 本題からは逸れますが
_*.js
で_
始まりのファイルもignore
指定しています
- オブジェクト
flag
のキーとsrc/js/parts/
下 のファイル名を一致させている、という条件下でフラグのtrue
orfalse
によりエントリーポイントを変化させています- 今回の出力は
dist/js/parts.min.js
でひとまとめにする前提にしています。app.min.js
の中には混ぜません - そのため、エントリーポイントを
{ 'app.js': [ 'PATH/TO/PROJECT/src/js/app.js', 'PATH/TO/PROJECT/src/js/parts/parts1.js', ... ] }
とするのではなく、{ 'app.js': 'PATH/TO/PROJECT/src/js/app.js', 'parts.js': [ 'PATH/TO/PROJECT/src/js/parts1.js', 'PATH/TO/PROJECT/src/js/parts/parts2.js', ... ] }
となるように処理を加えました
- 今回の出力は
Gulpタスク (JavaScriptに関する部分)
const { dest } = require('gulp');
const plumber = require('gulp-plumber');
const notify = require('gulp-notify');
const rename = require('gulp-rename');
const webpackStream = require('webpack-stream');
const webpackConfig = require('webpack.config');
const jsBuild = () => {
return webpackStream(webpackConfig)
.pipe(plumber({
errorHandler: notify.onError({
message: 'Error: <%= error.message %>',
title: 'jsLibBuild'
})
}))
.pipe(rename((path) => {
path.basename += '.min'
path.extname = '.js'
}))
.pipe(dest('dist/js'));
};
module.exports = jsBuild;
これでひとまず意図した出力が得られました。