gulp 4とwebpack 5を使用してJSのコンパイル環境を構築します。
よく紹介されている方法は、webpack.config.jsのentryに対象ファイルを設定をしていますが、ファイルが増えるたびにentryも増やす必要があり手間なので、ここではgulpfile.jsで自動で処理されるようにします。
またビルドファイルはソースと同じディレクトリ構成で出力するようにします。
- webpackのコンパイル環境を構築
- webpack.config.jsのentryは使用しない
- ビルドファイルはソースと同じディレクトリ構成で出力
node.jsやyarnのインストールについては省いています。
webpackのコンパイル環境を構築
全体構造
src/assets/js
をコンパイルしてpublic/assets/js
に出力します。
├─ public/
│ └─ assets/
│ └─ js/
│ └─ コンパイルされたjs
│
├─ src/
│ └─ assets/
│ └─ js/
│ ├─ child/
│ │ └─ child-index.js
│ └─ index.js
│
├─ gulpfile.js
├─ webpack.config.js
└─ package.json
パッケージの追加
まずはgulpを実行するために必要なパッケージを入れます。
yarn add -D gulp gulp-notify gulp-plumber gulp-debug
パッケージ | 説明 |
---|---|
gulp | gulp本体 |
gulp-notify | エラー通知 |
gulp-plumber | エラーが発生した場合にタスクが停止するのを防止 |
gulp-debug | 処理中のファイルをログに表示 |
次にwebpackでコンパイルするために必要なパッケージを追加します。
yarn add -D webpack webpack-stream babel-loader @babel/core @babel/preset-env vinyl-named gulp-filter
パッケージ | 説明 |
---|---|
webpack | webpack本体 |
webpack-stream | gulpでwebpackを使えるようにする |
babel~ | トランスパイル関係のパッケージ |
vinyl-named | gulpでwebpackのentryを自動作成 |
gulp-filter | _から始まるファイル名をコンパイル対象外にする |
最低限これだけあれば良いかと思います。
jsファイルの作成
src/assets/js
ディレクトリにindex.js
とchild/child-index.js
を作成していきます。
index.js
はビルド後にimport文のバンドルとトランスパイルされているか確認できる内容にします。
import $ from 'jquery';
console.log($);
const array1 = [1, 2, 3, 4];
const reducer = (previousValue, currentValue) => previousValue + currentValue;
// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10
// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15
1行目のimport文でjqueryを使用しているのでパッケージを追加しておきます。
yarn add -D jquery
child/child-index.js
は階層を維持してビルドされるか確認するためだけなので中身は何でもOKです。
console.log('child-index');
webpack.config.jsの作成
webpack.config.jsを以下の内容で作成します。
const webpack = require('webpack');
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
mode: 'production',
//entry: '', // gulpで設定
output: {
filename: '[name].min.js' // [name]はgulpで設定
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
'presets': [
["@babel/preset-env"]
],
'compact': false
}
},
}
]
},
plugins: [
// ファイルを分割しない
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1,
}),
],
optimization: {
minimize: true, // ファイル圧縮機能を有効にする
minimizer: [
new TerserPlugin({
extractComments: false, // コメントを外部ファイルにしない
terserOptions: {
compress: {
drop_console: false, // console.logを残す
}
},
}),
],
},
performance: {
hints: false // パフォーマンス警告を表示しない
},
resolve: {
extensions: ['.js']
}
}
ところどころコメントを書いていますが、4行目のentry
はgulpで設定するのでコメントアウトしています。
同様に5,6行目のoutput
でfilename: '[name].min.js'
となっている部分もgulpで処理されます。
※ファイル圧縮にTerserPluginを使用していますが、もしwebpack4を使っている場合はパッケージを追加する必要があります。
gulpfile.jsの作成と実行
gulpfile.jsにwebpackのタスクを記述します。
const gulp = require('gulp');
const notify = require('gulp-notify'); // エラー通知
const plumber = require('gulp-plumber'); // エラー時のタスク停止防止
const debug = require('gulp-debug'); // ログ表示
const path = require('path');
const named = require('vinyl-named');
const filter = require('gulp-filter'); // ファイルフィルター
const webpack = require('webpack');
const webpackStream = require('webpack-stream');
const webpackConfig = require('./webpack.config.js');
const paths = {
js: {
src: 'src/assets/js/**/*.js', // コンパイル対象
dest: 'public/assets/js' // 出力先
}
}
/**
* jsタスクを実行する関数
*/
function js() {
return gulp.src(paths.js.src)
.pipe(plumber({
errorHandler: notify.onError('Error: <%= error.message %>')
}))
.pipe(filter(function (file) { // _から始まるファイルを除外
return !/\/_/.test(file.path) && !/^_/.test(file.relative);
}))
.pipe(named((file) => {
const p = path.parse(file.relative);
return ((p.dir) ? p.dir + path.sep : '') + p.name;
})
)
.pipe(webpackStream(webpackConfig, webpack))
.pipe(gulp.dest(paths.js.dest))
.pipe(debug({title: 'js dest:'}));
}
/**
* watchタスクを実行する関数
*/
function watch() {
return gulp.watch(paths.js.src, gulp.series(js))
}
exports.js = js; // jsタスク
exports.watch = watch; // watchタスク
exports.default = gulp.series(js); // defaultタスク
このタスクで大事なのは32~36行目のnamed
(vinyl-named)です。
答えはWebpackStreamのMultiple Entry Pointsに書いてあり、このnamed
を使用してgulp.src
に指定されたファイル(複数)をエントリーポイントにします。
ただnamed()
のままで使用すると階層を無視した出力になるため少し手を加えています。
作成したタスクが正常に動作するか確認するため、ターミナルからyarn gulp
かyarn gulp js
、環境によってはgulp
かgulp js
でコンパイルできるか試してみます。
# defaultタスクの実行
yarn gulp
# jsタスクの実行
yarn gulp js
正常に動作した場合は以下のファイルが出力されます。import文がバンドルされてトランスパイルされているでしょうか?
- public/assets/js/index.min.js
- public/assets/js/child/child-index.min.js
ざっくりとした説明ですがこれでgulpとwebpackを使用したコンパイル環境の完成です。
webpack.config.jsでentryを自動登録することも可能ですが、gulpでもこのようにできるので活用してみてはどうでしょうか。
今回作成した環境は以下からダウンロードできます。
コメント