webpack 4でmini-css-extract-pluginを使う
webpack 4ではPlugin(プラグイン)を使用しない場合、CSSの情報はwebpackの実行後に作成されるJavaScriptファイルに埋め込まれ、htmlファイルを閲覧する時にstyleタグにCSSの情報が埋め込まれます。しかし別ファイルのほうがいいという場合もあるため、webpackでは別ファイルにわけることができます。
別ファイルとして出力させるためにmini-css-extract-pluginを使用します。
目次
環境の構築
mini-css-etract-pluginの動作確認を行うためにwebpackの環境を構築しておく必要があります。webpackはnpmを使ってインストールを行うのでnpmがわからない人は以下の記事を参考にしてください。
webpackのインストール
npmを使用してインストールを行うためにディレクトリを作成します。ここでは動作確認用なのでplugiin-testというディレクトリを作成しています。
mac $ mkdir plugiin-test
mac $ cd plugiin-test
npm initコマンドを使ってpackage.jsonファイルの作成を行います。
mac $ npm init -yes
webpackとwebpack-cliのインストールを行います。
mac $ npm install --save-dev webpack webpack-cli
css-loaderとstyle-loaderのインストールを行います。
mac $ npm install css-loader style-loader --save-dev
index.html, index.js , style.cssファイルの作成
index.htmlファイルの作成を行います。distディレクトリはwebpackの設定で指定するディレクトリでその下にwebpackで生成されるbundle.jsファイルを指定します。(現時点ではdistディレクトリは存在しません)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>webpack</title>
<script src="dist/bundle.js"></script>
</head>
<body>
<div class="first-header">
<h1>mini-css-extract-pluginの使い方</h1>
</div>
</body>
</html>
srcディレクトリの作成を行います。
$ mkdir src
srcディレクトリの下にindex.jsファイルの作成を行います。webpackを実行する際に起点になるファイルで通常はここにJavaScriptのコードを記述しますが、今回はCSSの動作確認なので、CSSファイルの読み込みとconsole.logのみ記述しています。
import './style.css'
console.log('Test');
style.cssファイルを作成します。
.first-header{
background-color: #FF0000;
color: #FFFFFF;
padding: 20px;
}
webpack.config.jsファイルの作成
webpack.config.jsファイルの作成を行います。
$ touch webpack.config.js
const path = require('path')
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module:{
rules:[
{
test:/\.css$/,
use:['style-loader','css-loader']
}
]
}
}
ここまでの設定で、以下のようなディレクトリ構成になっています。
webpackの実行
webpackを実行し、これまでの設定に問題がないか確認を行います。
$ npx webpack
実行後、distディレクトリが自動作成され、bundle.jsファイルが作成されます。ブラウザでindex.htmlを表示すると下記の画面が表示されていれば、問題なく設定が完了しています。
webpack 4では実行時にmodeの設定がないとWARNINGが表示されます。package.jsonのscriptsに以下を追加して、今後はnpm runコマンドでwebpackを実行させます。
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack --mode development",
"build": "webpack --mode production",
"watch": "webpack --mode development --watch"
},
mini-css-extract-pluginのインストール
npmコマンドで、mini-css-extract-pluginのインストールを行います。
$ npm install --save-dev mini-css-extract-plugin
インストール完了後、webpack.config.jsにmini-css-extract-loaderの設定に関する記述を追加します。htmlのstyleタグにCSSを埋め込むstyle-loaderは不必要になるため、代わりにmini-css-extract-loaderが追加されます。
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module:{
rules:[
{
test:/\.css$/,
use:[
{
loader: MiniCssExtractPlugin.loader,
},
'css-loader',]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'style.css',
}),
],
}
webpack.config.jsの更新後、npm run devでwebpackを実行します。実行後、distディレクトリの中にstyle.cssが保存されていることが確認できれば正常に動作しています。
今度は、npm run buildのproductionモードで実行してみましょう。bundle.jsファイルは最小化されていますが、style.cssには何も変化がありません。
下記がbundle.jsファイルの中身です。
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={
下記がstyle.cssファイルの中身です。
.first-header{
background-color: #FF0000;
color: #FFFFFF;
padding: 20px;
}
webpackでmini-css-extract-pluginを使うことでCSSファイルを別にすることはできましたがPRODUCTIONモードでは最小化されないということがわかりまました。
最小化の問題を解決するためにoptimize-css-assets-webpack-pluginが必要になります。
optimize-css-assets-webpack-pluginのインストール
npmコマンドでoptimize-css-assets-webpack-pluginのインストールを行います。
$ npm install --save-dev optimize-css-assets-webpack-plugin
インストール完了後、webpack.config.jsにoptimize-css-assets-webpack-pluginの設定に関する記述を追加します。pluginsの下のoptimaizationに追加を行っています。
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module:{
rules:[
{
test:/\.css$/,
use:[
MiniCssExtractPlugin.loader,
'css-loader',]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'style.css',
}),],
optimization: {
minimizer: [new OptimizeCSSAssetsPlugin({})],
},
}
npm run devを実行すると作成されるbundle.jsとstyle.cssに変化はありません。npm run buildのPRODUCTIONモードで実行するとstyle.cssが最小化されていることを確認することができます。
.first-header{background-color:red;color:#fff;padding:20px}
しかし、bundle.jsの最小化が行われなくなっています。
原因は、minimizerにOptimizeCSSAssetsPluginを記述したこでwebpackで初期設定されているJavaScriptの最小化のPluginのTerserの情報が上書きされてしまうためです。そのため、明示的にTerserJSPluginを追加する必要があります。
coconst path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const TerserJSPlugin = require('terser-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module:{
rules:[
{
test:/\.css$/,
use:[
MiniCssExtractPlugin.loader,
'css-loader',]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'style.css',
}),],
optimization: {
minimizer: [new TerserJSPlugin({}),new OptimizeCSSAssetsPlugin({})],
},
}
追加後、npm run buildを実行するとbundle.jsもstyle.cssも最小化されていることが確認できます。また、npm run devを実行するとbundle.js、style.cssは最小化されない状態で作成されます。
スタイルシートとをJavaScriptファイルと別々に作成し、PRODUCTIONモードではどちらも最小化できることを確認できました。