この記事を読んでいて知ったのだが、CSSを抽出する目的でextract-text-webpack-plugin
を使うのは非推奨になったらしい。
qiita.com
webpack@4
では mini-css-extract-plugin というプラグインを使うことが推奨されている。
というわけで、その使い方を書いていく。
webpack でのCSSの扱いの基礎については、以前書いたこの記事を参照。
numb86-tech.hatenablog.com
本記事は以下のバージョンで動作確認している。
- webpack@4.20.2
- webpack-cli@3.1.2
- css-loader@1.0.0
- mini-css-extract-plugin@0.4.4
- optimize-css-assets-webpack-plugin@5.0.1
- terser-webpack-plugin@1.1.0
まずはCSSを webpack の対象にする
復習を兼ねて、動作確認用の環境を一から作っていく。
まずはwebpack
とwebpack-cli
をインストールする。
$ npm i -D webpack webpack-cli
webpack でCSSを扱えるようにするためにcss-loader
もインストールする。
$ npm i -D css-loader
今回はsrc/index.js
というファイルでsrc/style.css
を読み込んで使う。
// src/index.js import './style.css'; const body = document.querySelector('body'); body.innerHTML += 'Hello World!';
/* src/style.css */ body { color: red; }
最後にwebpack.config.jp
を作成する。
// webpack.config.jp const path = require('path'); module.exports = { entry: { main: './src/index.js', }, output: { filename: '[name].js', path: path.resolve(__dirname, 'dest'), }, module: { rules: [ {test: /\.css$/, use: ['css-loader']} ], }, }
この状態で$ npx webpack --mode development
を実行すると、dest/main.js
が生成される。
dest/main.js
には、src/index.js
とsrc/style.css
の内容が含まれている。
だがこのままでは、CSSの内容がアプリに反映されることはない。
CSSを実際に使えるようにするための方法の一つとして、extract-text-webpack-plugin
があった。
これは、webpack で出力した結果をテキストとしてファイルに抽出するプラグインで、これを使うことでCSSファイルを出力することが出来た。
webpack@4
では、extract-text-webpack-plugin
の代わりにmini-css-extract-plugin
を使用する。
mini-css-extract-plugin の基本的な使い方
まずはインストールする。
$ npm i -D mini-css-extract-plugin
webpack.config.jp
を以下のように書き換える。
// webpack.config.jp const path = require('path'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = { entry: { main: './src/index.js', }, output: { filename: '[name].js', path: path.resolve(__dirname, 'dest'), }, module: { rules: [ { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', ], }, ], }, plugins: [ new MiniCssExtractPlugin({filename: 'style/[name].css'}), ], }
これで$ npx webpack --mode development
すると、以下の内容のdest/style/main.css
が出力される。
body { color: red; }
また、dest/main.js
も更新され、src/style.css
の内容が省かれている。
あとはHTMLファイルでdest/main.js
とdest/style/main.css
を読み込めば正しく動作し、赤文字の「Hello World!」が表示される。
CSSファイルの圧縮
$ npx webpack --mode production
のようにprodcution
モードでビルドすると、JSファイルを圧縮してくれる。
先程の例だと、dest/main.js
がワンライナーに圧縮される。
だがdest/style/main.css
は何も変わらない。
mini-css-extract-plugin
で抽出したCSSファイルを圧縮したい場合は、プラグインを使って明示的に設定する必要がある。
まずはプラグインをインストールする。
$ npm i -D optimize-css-assets-webpack-plugin
webpack.config.js
を以下の内容にする。OptimizeCSSAssetsPlugin
をrequire
し、optimization
の記述を追加している。
const path = require('path'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); module.exports = { entry: { main: './src/index.js', }, output: { filename: '[name].js', path: path.resolve(__dirname, 'dest'), }, module: { rules: [ { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', ], }, ], }, plugins: [ new MiniCssExtractPlugin({filename: 'style/[name].css'}), ], optimization: { minimizer: [new OptimizeCSSAssetsPlugin({})], }, }
これで$ npx webpack --mode production
すると、dest/style/main.css
がワンライナーに圧縮される。
だが今度は、dest/main.js
が圧縮されていない。
実はoptimization.minimizer
を記述すると圧縮の設定が上書きされてしまうので、JSについても明示的に設定しなければならない。
これまではJSの圧縮にはuglifyjs-webpack-plugin
というプラグインを使っていたが、v2
でES2015の対応が外れてしまった。今後ES2015+のコードを使う場合は、terser-webpack-plugin
というプラグインを使う必要がある。
というわけで、terser-webpack-plugin
をインストール。
$ npm i -D terser-webpack-plugin
そしてwebpack.config.js
を更新。
@@ -1,6 +1,7 @@ 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 = { entry: { @@ -25,6 +26,6 @@ module.exports = { new MiniCssExtractPlugin({filename: 'style/[name].css'}), ], optimization: { - minimizer: [new OptimizeCSSAssetsPlugin({})], + minimizer: [new TerserPlugin({}), new OptimizeCSSAssetsPlugin({})], }, }
これでビルドすると、dest/main.js
もdest/style/main.css
も圧縮される。