かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

Vite + React のプロジェクトでは require が使えない? Uncaught ReferenceError: require is not defined

Vite で作った React のアプリMSW を使おうとしてドキュメントにあるコード (下記)をコピペしたらエラーになった

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
if (process.env.NODE_ENV === 'development') {
  const { worker } = require('./mocks/browser');
  worker.start();
}
ReactDOM.render(<App />, document.getElementById('root'));

=> Uncaught (in promise) ReferenceError: require is not defined

require は node の方法 (CommonJS) なので ESM なクライアントサイドでは使えない

create-react-appcreate-next-app で作られたプロジェクトは webpack が使われていたので CommonJS の require もよしなに変換してくれていたので問題になってなかったが、Vite では DEV モードの時には ネイティブESM を使用するので require が使えないとなっていたっぽい

Vite は、ネイティブ ESM を行使してソースコードを提供します。ブラウザは、実質的にバンドラの仕事の一部を引き受けます
cf. なぜ Vite なのか | Vite

Dynamic Import を使う

require が使えないので ESModule の import を使えばOKということになります
今回は条件式の中で import したいので Dynamic import を使えば良さそうです

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
if (process.env.NODE_ENV === 'development') {
- const { worker } = require('./mocks/browser');
- worker.start();
+ (async () => {
+   const { worker } = await import('./mocks/browser');
+   worker.start();
+ })();
}
ReactDOM.render(<App />, document.getElementById('root'));

Dynamic import は非同期なので async の即時関数を作成してその中で import するようにすればOK
これで Vite のプロジェクトでも MSW の worker がどうさするようになりました。

おわり。


[参考]

そうだね…