🐳

[React / Vite] ビルドしたら画面蒼白「React refresh preamble was not loaded」俺も顔面蒼白

2023/09/18に公開

人生初の React ビルドをしようとしたらしっかり躓いたのでメモ
すんげーーーggったけどあんまり解決方法が見つけられなかったので記事に残しておく

要約

  • 「React refresh preamble was not loaded」と怒られて悲しみに暮れた
  • プラグインを変えたら解消できた

環境

  • Vite 4.4.0
  • React 18.2.0
  • TypeScript 5.0.2

Vite を使って React のプロジェクトを作成しました

事象

  • npm run build してアクセスしたら画面が真っ白
  • npm run dev で動かしていた開発環境では問題なし
  • 開発者ツールを見てみたところ下記のようなエラー……
Uncaught Error: React refresh preamble was not loaded. Something is wrong.
    at index-4da826b8.js:23:1926

「何かが違うんだよ」・・・って言われても、そらそうですよねとしか😭オオンオンオンオン

先に結論

初めて技術記事を書くのでちょっと長くなってしまいました
そのため先に結論をば

vite.config.ts で設定しているプラグインを、

@vitejs/plugin-react-swc@vitejs/plugin-react

に変更して、npm でインストールしたら解消できました

npm i @vitejs/plugin-react
あざらしの vite.config.ts
import { defineConfig, splitVendorChunkPlugin } from "vite";
// import react from "@vitejs/plugin-react-swc";
import { visualizer } from "rollup-plugin-visualizer";
import react from '@vitejs/plugin-react';

// https://vitejs.dev/config/
export default defineConfig({
  build: {
    rollupOptions: {
      plugins: [react(), visualizer(), splitVendorChunkPlugin()],
      output: {
        manualChunks: {
          vendor: ["axios", "react", "react-router-dom", "react-dom"],
          material: ["@mui/material"],
        },
      },
    },
  },
});

格闘記録(分析)

エラーが出た行を示してくれているので、そのまま開発者ツールで確認すると、

if (!window.$RefreshReg$)
    throw new Error("React refresh preamble was not loaded. Something is wrong.");
const Wb = window.$RefreshReg$

この部分で、if 内に入ってしまってエラーが投げられているみたいだった

RefreshReg

こんなものを入れた記憶が全くなく、とりあえずggってみたところ、
とりあえず画面のリフレッシュに使う~~??ようなニアピンの記事がでてきました。
でも !window.$RefreshReg$ で悩んでいる記事に出会えなかったので、
心の友 ChatGPT に聞いてみました

以下回答

window.RefreshReg と window.RefreshSig は、React RefreshのためにViteやWebpackなどのビルドツールが生成するグローバル変数です。これらの変数はReactのコンポーネントをホットリロードするために使用されます。
具体的には、React Refreshはコンポーネントの変更時にコンポーネントを再レンダリングし、新しいコードを適用するためのメカニズムを提供します。これは開発中にコードを修正すると、ブラウザで即座に変更を確認できる便利な機能です。
エラーメッセージ "React refresh preamble was not loaded. Something is wrong." は、React RefreshのプリアンブルがビルドされたJavaScriptコードに含まれていないか、正しく読み込まれていない場合に表示されます。これはビルド設定やViteの設定に問題がある可能性があります。
解決策としては、Viteの設定やビルドツールの設定を確認し、React Refreshの正しい設定が行われていることを確認することが重要です。また、ReactとReact Refreshのバージョンも互換性があることを確認してください。問題が続く場合は、ビルドツールやReact Refreshのドキュメンテーションを確認し、設定に不足がないか確認することをお勧めします。

ほんほんほん
この部分の設定が足りてないのかな?と思いつつ、
でも公式でも色んな記事でも、ビルドにこんなものを別途インストールが必要だなんて言ってなかったなぁ…となったので、

「React Refreshというのは、別途入れないといけないもの?何も入れた記憶がないのだけど」

と聞いてみた結果、以下回答

Reactアプリケーションをビルドする際にReact Refreshを別途インストールする必要はありません。通常、Reactアプリケーションを作成し、ビルドツール(例: Vite、Webpack、Create React Appなど)を使用すると、React Refreshは自動的に含まれます。
React Refreshを有効にするために特別な手順を踏む必要はありません。しかし、React Refreshが正しく動作しない場合、ビルドツールの設定に問題がある可能性があるため、ビルドツールの設定を確認することが重要です。

ホォン!!!じゃあビルドツールの設定が何か教えてもらえれば解決できそうか!?

「>ビルドツールの設定を確認
どのファイルの、どの項目を確認したらいいか教えてもらってもいいですか?」

と聞いてみた結果、以下回答

Viteを使用している場合、設定ファイルは通常プロジェクトのルートにある vite.config.js または vite.config.ts です。React Refreshの設定はViteの設定内で行われます。設定ファイル内で以下のように確認できます:

import reactRefresh from '@vitejs/plugin-react-refresh';

export default {
  // ...
  plugins: [reactRefresh()],
};

@vitejs/plugin-react-refresh プラグインがプラグインリストに追加されていることを確認し、React Refreshが有効になっていることを確認してください。

つまり、RefreshReg のエラーは、plugin-react-refresh が関係してそう?

plugin-react-refresh 改め plugin-react

npm のページで検索してみたところ、現在は plugin-react-refresh ではなく plugin-react でまかなえそうであった(というか、plugin-react と競合してるぞ!と出た)

というわけで plugin-react のページを見てみる
https://www.npmjs.com/package/@vitejs/plugin-react

設定方法も npm ページに書いてあるし、これを追加すればエラーは解消されそうかな???と推測

plugin-react と plugin-react-swc

ここで、vite.config.ts を見てみると plugin-react-swc が入っており、この子が import react してた。誰…?

公式より抜粋すると…

◆plugin-react

esbuild と Babel を使用し、小さなパッケージフットプリントで高速な HMR や、Babel 変換パイプラインを使用できる柔軟性を実現します。Babel プラグインを追加しない場合、ビルド時には esbuild のみが使用されます。

◆plugin-react-swc

開発中は Babel を SWC に置き換えます。ビルド時には、プラグインを使用する場合は SWC+esbuild、それ以外は esbuild を使用します。非標準の React 拡張を必要としない大きなプロジェクトでは、コールドスタートやホットモジュールリプレースメント(HMR)が大幅に高速化されます。

とのこと

https://ja.vitejs.dev/plugins/

つまり、plugin-react-swc が上位互換な感じなのか…でもいつ入れたんだっけ???

実は最初に選択していた

いつ入れたか…それはいっちばーーーーん最初、プロジェクトを立ち上げた時に選んでいた

Vite は、

npm create vite

でプロジェクトを立ち上げるのだが、
フレームワーク React を選択した後に聞かれる4つの選択肢

Select a variant: 
	JavaScript
	TypeScript
	JavaScript + SWC
	TypeScript + SWC

ここで選択することになる
あざらしは今回、ここで TypeScript + SWC を選んだので、
plugin-react-swc がデフォルトでインストールされていたものと思われる

https://tech-broccoli.life/articles/engineer/create-react-with-vite

プラグインを差し替えで解決…?

ということだったので、(とはいえ SWC で問題ない部分では…?何が悪いんだ…?と思いつつ)
plugin-react-swc をコメントアウトして、新たに plugin-react をインポートしてビルドした

画面が表示できた…😭😭😭😭よかった…😭😭😭😭

……とはいえ、根本解決(なんで SWC ではできなかったのか、何かプラグインが不足していたのか、バグなのか、などなど…)できなかったので、ちょっともにょもにょしています

おわりに(感想)

React 開発を初めてしたので本件以外にも悩みがいろいろありましたが、面白く開発できています。新しい知識が増えるのって楽しいですね
とくにプロジェクトを立ち上げるのに、Vite を使うとあっという間だったのが感動しました。いつもC#は待ちがあるので……

今回の事象について、Web記事などではあまり出てこなかったので恐らくレアケースのように思います
とはいえ、特に私のようなポンコツは歴史を繰り返す可能性があるので今回記事にしてみました
次からは悩まないでくれ、未来の私

Discussion