かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

webpack 5 CSS だけコンパイルしたい

npm script で SCSS をコンパイルしてたのだけれど、環境変数や変数展開などを多用していたら Windows 環境でエラーになりビルド出来ない問題続出してメンテコストが高くなってしまいそうだったので、ざっくり webpack で CSS だけビルドする設定を作成下のメモ

環境

  • webpack v5.60.0

install packages

# webpack
$ npm i -D webpack webpack-cli css-loader
# Sass
$ npm i -D sass sass-loader
# postCSS
$ npm i -D postcss postcss-loader autoprefixer cssnano
# plugin
$ npm i -D mini-css-extract-plugin webpack-remove-empty-scripts

Plugins

ターゲットブラウザを browserslist で指定する

ターゲットブラウザは browserslist.dev で確認するのが便利。
package.jsonbrowserslist プロパティで指定する

{
  …
  "browserslist": [
    "last 2 versions",
    "> 1%",
    "not dead"
  ]
}

webpack.config.js

// webpack.config.js
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const RemoveEmptyScriptsPlugin = require("webpack-remove-empty-scripts");
const sass = require("sass");
const cssnano = require("cssnano");
const autoprefixer = require("autoprefixer");

const MODE = process.env.MODE || process.env.NODE_ENV || "development";
const ENABLED_SOURCEMAP = MODE === "development";

const TARGET_DIR = path.resolve(__dirname, '/path/to/src');
const DIST_DIR = path.resolove(__dirname, 'path/to/build');

module.exports = {
  mode: MODE,
  target: ["web", "es5"],
  // development の時だけ差分をビルドする
  cache: MODE === "development",
  entry: {
    // scss をエントリーポイントに指定できる
    css: `${TARGET_DIR}/scss/styles.scss`,
  },
  output: {
    path: DIST_DIR,
    filename: "js/[name].js",
  },
  module: {
    rules: [
      {
        test: /\.s(c|a)ss$/i,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: "css-loader",
            options: {
              // url() を require() に変換しない
              url: false,
              // development の時だけ source map を出力する
              sourceMap: MODE === "development",
              // css-loader の前に loader を 2つ (postcss, sass) 実行する
              importLoaders: 2,
            },
          },
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [
                  [
                    cssnano,
                    {
                      // コメントを削除する
                      preset: [
                        "default",
                        { discardComments: { removeAll: true } },
                      ],
                    },
                  ],
                  [autoprefixer, { grid: true }],
                ],
              },
            },
          },
          {
            loader: "sass-loader",
            options: {
              // dart-sass を使用する
              implementation: sass,
            },
          },
        ],
      },
    ],
  },
  plugins: [
    // /js/css.js を出力しない
    new RemoveEmptyScriptsPlugin(),
    new MiniCssExtractPlugin({
      // `${DIST_DIR}/css/styles.css` として出力される
      filename: "css/styles.css",
    }),
  ],
}

※ 今回はエントリーポイントの JS が無いので HTML をホットリロード (HMR) 関連の設定はしていません。

ビルドコマンドの作成

npm script から環境変数を渡す際の OS 間の差異を吸収するパッケージをインストール

$ npm i -D cross-env

package.json

{
  "scripts": {
    "build:prod": "cross-env MODE=production  webpack",
    "build:dev": "webpack",
    "dev": "webpack --watch --progress"
  }
}

👇 ビルド

# production mode でビルド
$ npm run build:prod
# 変更を監視して自動ビルド
$ npm run dev
所管

環境ってそう何度も作るものじゃないから毎回なんだったっけ?ってなる。webpack のドキュメントが充実しているのは本当に助かりました。

実は当初は esbuild で環境を作っていたのですが、まだ Sass をエントリーポイントに出来ないっぽかったので、 JS 以外もエントリーポイントに出来たので今回は webpack で作成しました。 esbuild 周りもまたちゃんとやって書きたいデス。(環境づくりばかりしてるな…)


[参考]

esbuild

CSS はエントリーポイントできるようになったけど、Sass (SCSS) はまだできないっぽい。