できない.dev

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

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

公開: 更新:

症状できない · exit 1
npx webpack --stats errors-warnings
…
ERROR in ./src/style.css
Module build failed (from ./node_modules/css-loader/dist/cjs.js):
SyntaxError
解決後できた · exit 0
npx webpack --stats errors-warnings
webpack compiled successfully

2026-10-03 に node:20(Node.js 20.20.2 / npm 10.8.2) で実際に打って取った出力。検証環境の詳細

要約

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

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

ただし webpack 5.109(新しいタブで開く) で experiments.css などの既定値が "auto" に変わり、CSS に一致するローダーが登録されていなければ組み込みの CSS サポートが有効になるようになりました。
つまり 5.109 以降でローダーを 1 つも設定していない場合は、このエラーではなく CSS がそのままバンドルされることがあります。
逆に css-loader を登録している構成では従来どおりローダー側が優先されるため、以下の原因と解決策はそのまま当てはまります。

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

実行例

ローダーを 1 つも登録しない状態では webpack compiled successfully と出て、dist に main.css が書き出された。use を ["css-loader", "style-loader"] の順に書くと css-loader の Unknown word import で失敗して終了コード 1 になり、["style-loader", "css-loader"] に直すと成功している。.scss を import すると You may need an appropriate loader で終了コード 1 になり、test を /\.s?css$/i に広げて sass-loader を末尾に足したあとはビルドが通った。

$ npx webpack --mode development --stats errors-warnings
webpack compiled successfully
$ echo $?
0
$ ls dist
main.css
main.css.map
main.js
$ cat webpack.config.js
module.exports = {
  mode: "development",
  module: {
    rules: [{ test: /\.css$/i, use: ["css-loader", "style-loader"] }],
  },
};
$ npx webpack --stats errors-warnings
ERROR in ./src/style.css
Module build failed (from ./node_modules/css-loader/dist/cjs.js):
 
SyntaxError
 
(2:7) /tmp/tmp.RlFZ6bkVOU/src/style.css Unknown word import
 
  1 | 
> 2 |       import API from "!../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js";
    |       ^
  3 |       import domAPI from "!../node_modules/style-loader/dist/runtime/styleDomAPI.js";
  4 |       import insertFn from "!../node_modules/style-loader/dist/runtime/insertBySelector.js";
 
webpack compiled with 1 error
$ echo $?
1
$ cat webpack.config.js
module.exports = {
  mode: "development",
  module: {
    rules: [{ test: /\.css$/i, use: ["style-loader", "css-loader"] }],
  },
};
$ npx webpack --stats errors-warnings
webpack compiled successfully
$ echo $?
0
$ npx webpack --stats errors-warnings
ERROR in ./src/theme.scss 2:0
Module parse failed: Unexpected token (2:0)
File was parsed as module type 'javascript/auto'.
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
  1 | $main: red;
> 2 | .title {
    | ^
  3 |   color: $main;
 
webpack compiled with 1 error
$ echo $?
1
$ cat webpack.config.js
module.exports = {
  mode: "development",
  module: {
    rules: [{ test: /\.s?css$/i, use: ["style-loader", "css-loader", "sass-loader"] }],
  },
};
$ npx webpack --stats errors-warnings
webpack compiled successfully
$ echo $?
0

— 2026-10-03 時点の出力

検証環境Node.js 20.20.2 / npm 10.8.2 / Python 3.11.2 / 2026-10-03 検証(ほか 1 件)
検証日
実行環境
node:20 Debian GNU/Linux 12 (bookworm)
バージョン
  • Node.js 20.20.2
  • npm 10.8.2
  • Python 3.11.2
  • Git 2.39.5

この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。

解決策

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

2. 適用順を間違えない

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

// 正しい: css-loader → style-loader の順に通る
use: ["style-loader", "css-loader"]
 
// 誤り: style-loader の出力を css-loader が CSS として読み、Unknown word で失敗する
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 の設定です。
同じメッセージでも足りていないローダーは違うので、まずパスを確認してください。

よくある原因

  1. ローダー自体を設定していない。
    パッケージをインストールしただけでは何も起きません。module.rules に書いて初めて適用されます(webpack 5.108 以前。
    5.109 以降は組み込み CSS が代わりに働きます)。
  2. use の並びが逆になっている。
    webpack はローダーを配列の後ろから前へ適用するため、["css-loader", "style-loader"] と書くと style-loader が出力した JavaScript(import API from …)を css-loader が CSS として読もうとし、Module build failed (from …css-loader…) の SyntaxError(Unknown word import)で失敗します。
  3. test の正規表現が実ファイルに一致していない。/\.css$/ だけを書いて .scss を import している場合などです。
  4. 設定ファイルが読まれていない。webpack.prod.js のような別名にしているのに --config を付け忘れると、webpack は既定の設定で動きます。

この手順で直った?