できない.dev

postcss.config.js が ESM プロジェクトで読み込めずビルドが落ちる

package.json に type: module があると postcss.config.js は ES モジュールとして評価されるため、module.exports や require が使えず落ちる。
export default に書き換えるか拡張子を .cjs にする。

公開:

要約

module is not defined in ES module scoperequire is not defined で PostCSS の設定読み込みが落ちるのは、package.json"type": "module" があるためです。
この指定があると .js ファイルは ES モジュールとして評価され、module.exportsrequire も使えません。

設定を ES モジュールの書き方に直します。

// postcss.config.js
import autoprefixer from "autoprefixer";
 
export default {
  plugins: [autoprefixer],
};

よくある原因

  1. "type": "module"module.exports の組み合わせ: Node.js は package.jsontype.js の扱いを決める。module なら ES モジュールとして読むので、CommonJS の書き方は構文エラーになる。
  2. 設定ファイル内の require: プラグインを require("autoprefixer") で読み込んでいると、同じ理由で落ちる。
  3. 拡張子で明示していない: .jspackage.json の設定に左右される。
    チームで type を切り替えたときに、設定ファイルだけ取り残されることがある。
  4. TypeScript 版を置いた: postcss-load-config は postcss.config.ts も探すが、その場合は tsxjiti を peer dependency として自分で入れる必要がある。

解決策

1. export default 形式に書き換える

プラグインをオブジェクト記法で書く場合は、そのまま export default を付けます。

// postcss.config.js
export default {
  plugins: {
    autoprefixer: {},
  },
};

配列記法にすると、プラグイン関数を直接渡せてオプションも書けます。

// postcss.config.js
import autoprefixer from "autoprefixer";
 
export default {
  plugins: [autoprefixer({ grid: "autoplace" })],
};

2. 拡張子を .cjs にして CommonJS のまま使う

既存の設定を触りたくないときは、ファイル名を変えるだけで通ります。
postcss-load-config は postcss.config.cjs も探索対象にしています。

mv postcss.config.js postcss.config.cjs

.cjstype の値にかかわらず CommonJS として読まれるので、module.exportsrequire がそのまま使えます。

3. .mjs で ES モジュールを明示する

逆に、type を指定していないプロジェクトで ES モジュールとして書きたい場合は .mjs にします。

mv postcss.config.js postcss.config.mjs

4. TypeScript の設定ファイルにはローダーを入れる

postcss.config.ts を使うなら、TypeScript を読める実行環境が要ります。

npm i -D tsx

jiti でも同じ役割を果たします。
どちらも入れずに .ts の設定だけ置くと、設定が見つからないまま処理が進み、プラグインが一切適用されない状態になります。

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