非圧縮CSSを書き出す、通常のコーディング案件でwebpack 5を利用する

HTMLとCSSのみのコーディング案件にwebpack 5を使用したところ、いい感じだったので忘れないうちにまとめます。

## webpackを使用するメリット

npm scriptsとPostCSSで良いのでは？と思うところですが、webpackはwatchモードを利用している間はキャッシュを使用するので、CSSの自動ビルドが体感でわかるほど早いです。CSSコーディングは細かい調整が多かったりするので、とても助かります。

## パッケージをインストールする

package.jsonがまだない場合は、プロジェクトの初期化をします。

```
npm init
```

以下のパッケージをインストールします。npm-run-allは必須ではありません。複数のnpm scriptをわかりやすく行を分けて書くために使用しています。node-sassは非推薦になったのでsass(Dart Sass)を使用してください。

- autoprefixer
- css-loader
- mini-css-extract-plugin
- npm-run-all
- postcss
- postcss-cli
- postcss-loader
- sass
- sass-loader
- watch
- webpack
- webpack-cli
- webpack-remove-empty-scripts


まとめてインストールする場合は、長いですがこうなるかと思います。

```
npm i -D autoprefixer css-loader mini-css-extract-plugin npm-run-all postcss postcss-cli postcss-loader sass sass-loader watch webpack webpack-cli webpack-remove-empty-scripts
```

### postcss関係いらなくない？

**CSSを非圧縮で納品するため**に使用しています。少なくとも私が関わる案件については、まだまだ非圧縮を求められます。改修のしやすさや新人への作業ベースとするなど、事情はいろいろでしょう。

一方、webpack 5は、productionモードでのCSSは圧縮する前提となりました。いろいろ調べたのですが、非圧縮にする方法が見つかりませんでした。

常にdevelopmentモードでビルドして、冒頭のコメントを手作業で削除…というのも考えましたが、スマートじゃないので納品時だけPostCSSでビルドすることにしました。

## ディレクトリ構成

以下の通り、ルート外にあるsrcから、distへ書き出す前提です。JavaScriptを作成しないため、srcディレクトリ内にjsディレクトリはありません。

```
package.json
postcss.config.js
webpack.config.js
src
└ scss
   └ style.scss
dist
├ index.html
└ css
   └ style.css
```

## webpack.config.js

以下のとおりです。
Dart Sass、PostCSSのautoprefixerを経由しています。
さらにMiniCssExtractPluginで、JSにバンドルせずCSSの実体を書き出し、RemoveEmptyScriptsPluginで使用しなかった＝空の状態で生成されたbundle.jsを削除しています。

```
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const RemoveEmptyScriptsPlugin = require('webpack-remove-empty-scripts');

module.exports = {
    entry: {
        'style': `${__dirname}/src/scss/style.scss`
    },
    output: {
        path: `${__dirname}/dist`,
        filename: 'bundle.js',
    },
    module: {
        rules: [{
            test: /\.(sa|sc|c)ss$/,
            use: [
                MiniCssExtractPlugin.loader,
                {
                    loader: 'css-loader',
                    options: {
                        url: false
                    },
                },
                {
                    loader: 'postcss-loader',
                    options: {
                        postcssOptions: {
                            plugins: [
                                require('autoprefixer')
                            ]
                        }
                    },
                },
                'sass-loader',
            ],
        }]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'css/[name].css'
        }),
        new RemoveEmptyScriptsPlugin()
    ],
};
```

## postcss.config.js

納品時のビルドのために、PostCSSの設定ファイルも必要となります。

```
module.exports = {
  plugins: [
    require('autoprefixer')({
      grid: 'autoplace',
    })
  ]
};
```

## package.json

npm scriptsは以下のとおり、作業時はwebpack、納品時はDart SassとPostCSSを生で呼び出します。autoprefixerのbrowserslistと、private宣言も忘れず書きます。

```
...略

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "prod": "run-s prod:scss prod:postcss",
    "prod:scss": "sass src/scss:dist/css --style expanded --no-source-map",
    "prod:postcss": "postcss ./dist/css -c=postcss.config.js --no-map --dir ./dist/css",
    "dev": "webpack --watch --mode development"
  },

...略

  "browserslist": [
    "> .2%",
    "not ie <= 11",
    "not op_mini all"
  ],
  "private": true
}
```

## 使用する

### 作業時

```
npm run dev
```

### 納品時

```
npm run prod
```

----

webpackは本来、旧来のコーディング案件に使うものではないのでしょうが、明らかに作業効率化になりましたし、案件ごとにpackage.jsonを変えるのは手間なのでこうなりました。

もしwebpack 5で非圧縮CSSを書き出す方法があればコメントなどで教えてもらえるとありがたいです。