Motomichi Works Blog

モトミチワークスブログです。その日学習したことについて書いている日記みたいなものです。

webpack4.xでscssファイルをコンパイルする

参考にさせて頂いたページ

設定全般

ExtractTextPluginをwebpack 4 で使用する方法について

今日の環境

  • Windows10
  • node 8.11.1
  • npm 5.8.0
  • webpack 4.8.1

プロジェクトディレクトリを作成

webpack_4_scss_introduction

npm init する

npm init

全てそのままenterを押してデフォルト値が設定されたpackage.jsonが生成されました。

グローバルにインストール

npm install -g webpack webpack-cli

プロジェクトにインストール

コマンド

npm install --save-dev webpack webpack-cli style-loader css-loader sass-loader node-sass postcss-loader autoprefixer extract-text-webpack-plugin@next

ここでのポイント

2018年05月09日現在ですが、webpack 4 を使用している場合はextract-text-webpack-plugin@nextをインストールします。

extract-text-webpack-pluginはwebpack 3で使用するプラグインなので以下のようなエラーが出ました。

(node:20569) DeprecationWarning: Tapable.plugin is deprecated. Use new API on `.hooks` instead
/Users/xxxxx/Desktop/webpack_4_scss_introduction/node_modules/webpack/lib/Chunk.js:712
        throw new Error(
        ^

Error: Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead
    at Chunk.get (/Users/xxxxx/Desktop/webpack_4_scss_introduction/node_modules/webpack/lib/Chunk.js:712:9)
    at /Users/xxxxx/Desktop/webpack_4_scss_introduction/node_modules/extract-text-webpack-plugin/dist/index.js:176:47
    at Array.forEach (<anonymous>)
    at /Users/xxxxx/Desktop/webpack_4_scss_introduction/node_modules/extract-text-webpack-plugin/dist/index.js:171:18
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/xxxxx/Desktop/webpack_4_scss_introduction/node_modules/tapable/lib/HookCodeFactory.js:24:12), <anonymous>:7:1)
    at AsyncSeriesHook.lazyCompileHook [as _callAsync] (/Users/xxxxx/Desktop/webpack_4_scss_introduction/node_modules/tapable/lib/Hook.js:35:21)
    at Compilation.seal (/Users/xxxxx/Desktop/webpack_4_scss_introduction/node_modules/webpack/lib/Compilation.js:890:27)
    at hooks.make.callAsync.err (/Users/xxxxx/Desktop/webpack_4_scss_introduction/node_modules/webpack/lib/Compiler.js:481:17)
    at _err0 (eval at create (/Users/xxxxx/Desktop/webpack_4_scss_introduction/node_modules/tapable/lib/HookCodeFactory.js:24:12), <anonymous>:11:1)
    at _addModuleChain (/Users/xxxxx/Desktop/webpack_4_scss_introduction/node_modules/webpack/lib/Compilation.js:758:12)
    at processModuleDependencies.err (/Users/xxxxx/Desktop/webpack_4_scss_introduction/node_modules/webpack/lib/Compilation.js:697:9)
    at _combinedTickCallback (internal/process/next_tick.js:131:7)
    at process._tickCallback (internal/process/next_tick.js:180:9)

以下のページを参照して解決できました。

今回webpack_4_scss_introductionディレクトリ内に作成するディレクトリ構造とファイル

  • package.json
  • package-lock.json
  • webpack.config.js
  • node-modules/*
  • src/index.js
  • src/style.scss
  • dist/style.css

webpack.config.jsの作成とその記述内容

const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    path: `${__dirname}/dist`,
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: [
            // CSSをバンドルするための機能
            {
              loader: 'css-loader',
              options: {
                // CSS内のurl()メソッドの取り込みを禁止する
                url: false,
                // ソースマップの利用有無
                sourceMap: true,
                // 空白文字やコメントを削除する
                minimize: true,
                // Sass+PostCSSの場合は2を指定
                importLoaders: 2
              },
            },
            // PostCSSのための設定
            {
              loader: 'postcss-loader',
              options: {
                // PostCSS側でもソースマップを有効にする
                sourceMap: true,
                plugins: [
                  // Autoprefixerを有効化
                  // ベンダープレフィックスを自動付与する
                  require('autoprefixer')({grid: true})
                ]
              },
            },
            // Sassをバンドルするための機能
            {
              loader: 'sass-loader',
              options: {
                // ソースマップの利用有無
                sourceMap: true,
              }
            }
          ],
        })
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin('style.css')
  ]
}

./src/index.jsの作成とその記述内容

import './style.scss';

./src/style.scssの作成とその記述内容

background-imageや、ベンダープレフィックスが意図通り出力されるのが確認できるように以下のように記述してみました。

.hoge {
  .foo {
    background-image: url(./hoge.png);
  }
  ::placeholder {
    color: gray;
  }
}

コンパイルする

以下のコマンドを実行します。

webpack

dist/style.cssが書き出されます。

ExtractTextPluginを使うとmodeをdevelopmentにしても、cssのsourceMapは出力されないけどなんでかわからない。 まぁcssはsourceMap無くてもいいか。