できない.dev

webpack で CSS を import すると「You may need an appropriate loader」で失敗する

webpack が既定で解釈できるのは JavaScript と JSON だけで、CSS はローダーを通さないと構文エラーになる。css-loaderstyle-loadermodule.rules に登録し、適用順が右から左であることを踏まえて並べれば解決する。

公開:

要約

Module parse failed: Unexpected tokenYou may need an appropriate loader to handle this file type は、webpack が CSS ファイルを JavaScript として読もうとして失敗したという意味です。

webpack が追加設定なしで解釈できるのは JavaScript と JSON だけです。
それ以外の形式は、ローダーを経由して JavaScript が扱える形へ変換する必要があります。
CSS の場合は css-loader がその役目を担います。

エラーメッセージに出ているファイル名が CSS なら、原因はほぼ設定漏れです。

よくある原因

  1. ローダー自体を設定していない。
    パッケージをインストールしただけでは何も起きません。module.rules に書いて初めて適用されます。
  2. use の並びが逆になっている。
    webpack はローダーを配列の後ろから前へ適用するため、["css-loader", "style-loader"] と書くと style-loader が生の CSS を受け取って失敗します。
  3. test の正規表現が実ファイルに一致していない。/\.css$/ だけを書いて .scss を import している場合などです。
  4. 設定ファイルが読まれていない。webpack.prod.js のような別名にしているのに --config を付け忘れると、webpack は既定の設定で動きます。

解決策

1. ローダーを入れて rules に登録する

npm install --save-dev style-loader css-loader
// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ["style-loader", "css-loader"],
      },
    ],
  },
};

css-loader@importurl() を解決して JavaScript のモジュールに変換し、style-loader がそれを実行時に <style> として DOM へ挿入します。
役割が分かれているので、両方が要ります。

2. 適用順を間違えない

use の配列は 後ろから前へ 適用されます。
読む順ではなく、通す順が逆になる点が混乱の元です。

// 正しい: css-loader → style-loader の順に通る
use: ["style-loader", "css-loader"]
 
// 誤り: style-loader が CSS 原文を受け取り、同じエラーが続く
use: ["css-loader", "style-loader"]

Sass を使う場合も同じ考え方で、変換の起点になるローダーを配列の末尾に置きます。

use: ["style-loader", "css-loader", "sass-loader"]

3. 本番ビルドは別ファイルに切り出す

style-loader は CSS を JavaScript バンドルに埋め込むため、本番では初回描画までスタイルが当たりません。
ファイルとして出したい場合は mini-css-extract-plugin に差し替えます。

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
 
module.exports = {
  module: {
    rules: [
      { test: /\.css$/i, use: [MiniCssExtractPlugin.loader, "css-loader"] },
    ],
  },
  plugins: [new MiniCssExtractPlugin()],
};

4. どのファイルで落ちたかを読む

エラー本文には対象ファイルのパスが必ず出ます。
それが CSS ではなく画像やフォントなら、必要なのは css-loader ではなく Asset Modules の設定です。
同じメッセージでも足りていないローダーは違うので、まずパスを確認してください。

この記事は役立ちましたか?