tohokuaikiのチラシの裏

技術的ネタとか。

webpackでSASSとJavaScriptをそれぞれ別々のファイルにコンパイルしたかっただけの人生だった

今まで、SASSを使うときは1つの.scssファイルにまとめて

$ ./node_modules/node-sass/bin/node-sass ./scss/foo.scss ./htdocs/css/foo.css --output-style compressed --source-map true &

とかやってたんだけど、JavaScriptも一緒にコンパイルしたいなと。TypeScriptじゃなくてJavaScriptなんだけど、npm installとかしたやつを一緒にコンパイルしたくなったんです。今までは、Laravel mix使ってたんで素で使うっというのが無くて…

とりあえず、package.json

{
  "name": "myproject-sass",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "prod": "NODE_ENV=production webpack --mode=production",
    "dev": "NODE_ENV=development webpack --mode=development --watch"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "css-loader": "^5.1.2",
    "mini-css-extract-plugin": "^1.3.9",
    "node-sass": "^5.0.0",
    "sass-loader": "^11.0.1",
    "webpack": "^5.25.1",
    "webpack-cli": "^4.5.0",
    "webpack-fix-style-only-entries": "^0.6.1"
  },
  "dependencies": {
    "bs-custom-file-input": "^1.3.4"
  }
}

node-sass使ってるのは、いにしえのSCSSライブラリcompassを使ってるからである。

当初、sass-loaderさえあればcss-loaderいらんやろ、CSSなんて書いて無いしって思ったんだけど、いるのね。

webpack.config.js

const path = require('path');
const MiniCSSExtractPlugin = require("mini-css-extract-plugin");
const FixStyleOnlyEntries = require("webpack-fix-style-only-entries");
const enabledSourceMap =  process.env.NODE_ENV !== 'production';

module.exports = ( env, argv ) => ({
  entry: {
      "foo_script": './src/js/foo.js',
      "foo_style": './src/scss/foo.scss'
  },
  output: {
    filename: 'js/[name].js',
    path: path.resolve(__dirname, 'htdocs')
  },
  module: {
    rules: [
        {
          test: /\.(sa|sc|c)ss$/,
          use: [
              {
                loader: MiniCSSExtractPlugin.loader,
              },
              {
                loader: "css-loader",
                options: {
                  url: false,
                  sourceMap: enabledSourceMap
                }
              },
              {
                loader: "sass-loader",
                options: {
                  sourceMap: enabledSourceMap
                }
              }
              ]
        }]
  },
  plugins: [
    new FixStyleOnlyEntries(),
    new MiniCSSExtractPlugin({
      filename: "./css/[name].css"
    })
  ],
  devtool: "inline-source-map",
});

ハマりポイント

  • devtoolを付けないと、sourceMapが有効にならなかった。
  • 本当は、foo.js foo.cssってしたかったんだけど、するとentryに同じキーになるのでできなかった。
  • じゃあ、outputのfilenameでfoo.css/foo.jsってそれぞれ指定すればいいじゃんって思ったんだけど、そうするとエラーが出てうまくいかなかった。多分、CSSにする際に一旦JavaScriptを経由してて、そのJavaScriptのファイル名が被ってしまうせいだと思う。
  • 環境変数NODE_ENVは、NODE_ENV=development ってpackage.jsonで指定しないといけなかったのを知らんかった。

これで、npm run prod/devで快適にSCSSとJavaScriptが書ける。・