webpack4がリリースされていて、ちょっと調べて行く中で、webpack.configの構成方法を工夫した方がいいんだと言うことを知りました。
公式でも解説されている事なのですが、webpack.configを以下のように構成するのが、今時なんだそうです。
- 共通のwebpack.config = webpack.common.js
- 開発用のwebpack.config = webpack.dev.js
- リリース用のwebpack.config = webpack.prod.js
この方が、シンプルに考えられるよねってことです。
webpack-mergeのインストール
この構成で、webpack.configを構成するには、webpack-mergeが必要になります。
開発用とリリース用のwebpack.configに、共通のwebpack.configを取り込むために、webpack-mergeを使います。
npm install webpack-merge --save-dev
共通のwebpack.configを作成
開発用とリリース用で共通となる部分のwebpack.configを、webpack.common.jsとして作成します。
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const glob = require('glob');
module.exports = {
entry: {
server: './src/server/main.ts',
assets: glob.sync('./src/server/assets/**/*')
},
target: 'node',
node: {
__dirname: false,
__filename: false
},
externals: [
nodeExternals()
],
module: {
rules: [
{
test: /\.ts$/,
use: [
// 下から順に処理される
{
loader: 'ts-loader',
options: {
configFile: 'src/server/tsconfig.server.json'
}
},
{
loader: 'tslint-loader',
options: {
typeCheck: true,
// tslint時に自動的に修正しない
fix: false,
// warningをエラーにすることでその後のビルドを止める
emitErrors: true
},
},
],
exclude: /(node_modules|client)/
},
{
test: /\.txt$/,
use: {
loader: 'file-loader'
},
exclude: /(node_modules|client)/
}
]
},
resolve: {
extensions: [ '.ts', '.txt' ]
},
plugins: [
new BundleAnalyzerPlugin({
openAnalyzer: false,
generateStatsFile: true,
analyzerMode: 'static',
reportFilename: '../../report.html',
statsFilename: '../../stats.json'
})
],
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist/server'),
publicPath: path.resolve(__dirname, 'dist/server')
}
};
開発用のwebpack.configを作成
開発用として必要になる構成、例えばmodeをdevelopmentにするとか、devtoolでソースマップを作成するとかを指定します。
共通として作成したwebpack.common.jsを取り込む必要があるので、webpack-mergeを使います。
const merge = require('webpack-merge');
const common = require('./webpack.common');
module.exports = merge(common, {
mode: 'development',
devtool: 'source-map'
})
リリース用のwebpack.configを作成
今度はリリース用として必要になる構成、例えばmodeをproductionにするとかを指定します。
こっちでも、共通として作成したwebpack.common.jsを取り込む必要があるので、webpack-mergeを使います。
const merge = require('webpack-merge');
const common = require('./webpack.common');
const TerserPlugin = require('terser-webpack-plugin');
module.exports = merge(common, {
mode: 'production',
optimization: {
minimizer: [
new TerserPlugin({
terserOptions: {
keep_classnames: true,
drop_console: true
}
})
]
}
})
使い分け
以下のビルドするときのパラメータを変えると使い分けるとできます。
- 開発するとき・・・webpack --config webpack.dev.js
- リリースするとき・・・webpack --config webpack.prod.js
ただ、これだとPCで開発しているとき、Herokuにリリースするときを考えると、めんどくさいので、gulpを使う事にしました。
gulpfile.jsを以下のようにすると、NODE_ENVを見て、構成を変えることができます。
const gulp = require('gulp');
const webpack = require('webpack');
const webpackStream = require('webpack-stream');
const webpackConfigDev = require('./webpack.dev');
const webpackConfigProd = require('./webpack.prod');
// Node.jsのビルド(webpack)
gulp.task('build-server', () => {
const webpackConfig = (process.env.NODE_ENV || 'development') === 'development' ? webpackConfigDev : webpackConfigProd;
return webpackStream(webpackConfig, webpack)
.pipe(gulp.dest('dist/server'));
});
すっきり!