shigeki.takeguchi.log

アラフィフおじさんの技術日記

ひさびさにwebpackの設定を書いたらバージョンが4になっていて色々と変わっていた

ひさびさにwebpackの設定を書いたらバージョンが4になっていて色々と変わっていた

ここのところNuxt.jsを使って制作することが多かったのでwebpackを使ってどのパッケージを使ってTypeScriptやScssをトランスパイルして圧縮するかとか考えて設定する機会がなかった。

webpackでCSSをCSSのまま使うためにはこれまで extract-text-webpack-plugin をインストールしてたんだけどこれがwebpack@4になって非推奨なったんですね。 extract-text-webpack-plugin@beta でもうまく動きません。。。

terser-webpack-pluginを使って圧縮(Minify)をする

GitHub: terser-webpack-plugin

GitHubの説明ではJavaScriptのみの言及になっていますが、後で説明する optimize-css-assets-webpack-pluginの引数に terser-webpack-plugin を渡してCSSの圧縮でも利用します。 おそらく以前はUglifyJSを使うことが一般的で過去の自分のwebpackの記述をみても以下のように書いてあったのですがES2015(ES6)の構文があるとエラーになります。

1
2
3
plugins: [
new webpack.optimize.UglifyJsPlugin()
]

mini-css-extract-pluginを使ってJavaScriptから別ファイルとしてCSSを切り出す

GitHub: mini-css-extract-plugin

webpackを使って素直にCSSを扱うとJavaScriptとして同じファイルとして扱ったりするんだけど、まあそれだといろいろと不都合があったりするので切り出してCSSファイルとして別にしたくなる。 そういう場合は今まで extract-text-webpack-pluginを使ってたんだけどこれからは mini-css-extract-plugin を使ってねということと理解。

optimize-css-assets-webpack-pluginはCSSを最適化して圧縮(minimize)する

古いwebpackの記述を探すと extract-text-webpack-plugin 使ってて以下な感じでminimizeしてたんですが今はうまく動きません。

1
2
3
4
5
6
7
8
module: {
loaders: [
{
test: /\.css|scss$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader?minimize!sass-loader')
}
]
},

こんな記述にしていました

entryとなるディレクトリとoutputするディレクトリは環境にあわせて書き換える必要がありますがこんな感じで書いておくと汎用的に使えるんじゃないかと思います。
オプションがいろいろ設定できて進化を感じます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');

module.exports = (env, argv) => {
return [
{
entry: {
bundle: "./src/ts/application.ts",
},
output: {
path: path.resolve(__dirname, './static/js'),
publicPath: '/js/',
filename: '[name].js',
},
optimization: {
minimize: true,
minimizer: [new TerserPlugin({
extractComments: false,
terserOptions: {
ecma: 6,
compress: true,
output: {
comments: false,
beautify: false
}
}
})]
},
module: {
rules: [
{
test: /\.ts$/,
use: "ts-loader"
}
]
},
resolve: {
extensions: [".ts"]
},
cache: true
},
{
entry: {
bundle: "./src/scss/application.scss",
},
output: {
path: path.resolve(__dirname, './static/css'),
publicPath: '/css/',
filename: '[name].css'
},
optimization: {
minimizer: [new TerserPlugin({}), new OptimizeCSSAssetsPlugin({
assetNameRegExp: /\.optimize\.css$/g,
cssProcessor: require('cssnano'),
cssProcessorPluginOptions: {
preset: ['advanced',
{
autoprefixer: {
add: true,
browsers: ["last 2 versions", "ie >= 11", "Android >= 5", "iOS >= 9"]
},
discardComments: { removeAll: true },
cssDeclarationSorter: { order: 'smacss' }
}],
},
canPrint: true
})],
},
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
'css-loader',
'postcss-loader',
'sass-loader',
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: './[name].css'
})
],
cache: true
}
]
};

ちなみにpackage.jsonは以下な感じです。
autoprefixerはwebpack.config.jsにもこちらにも記述があって二重管理なのであれな感じになってますね。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{
"name": "project",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"postcss": {
"plugins": {
"autoprefixer": {}
}
},
"scripts": {
"build": "webpack --mode production",
"watch": "webpack -w --mode development"
},
"devDependencies": {
"autoprefixer": "^9.7.3",
"css-loader": "^3.2.1",
"mini-css-extract-plugin": "^0.8.0",
"node-sass": "^4.13.0",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"postcss-loader": "^3.0.0",
"sass-loader": "^8.0.0",
"terser-webpack-plugin": "^2.2.1",
"ts-loader": "^6.2.1",
"typescript": "^3.7.3",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10"
},
"browserslist": [
"> 1%",
"last 2 versions",
"Android >= 5",
"iOS >= 9"
],
"dependencies": {}
}

shigeki.takeguchi

渋谷の某ソーシャルゲームの会社でフロントエンドエンジニアとして働いてます。20世紀よりウェブ業界。気づいたらアラフィフ業界人です。
まだまだ現場で粘り強く作る側でいたいと思います。