🌐

React 19以下でもReact Compilerを有効化する

2024/05/27に公開1

はじめに

一応React Compilerは、React 19を必須としていますが、なくても動きます

https://x.com/potetotes/status/1793248011239170156

Reactチームの方によりますと、React 19のキャッシュ機構が過去のバージョンより効率が良いとされていますね。
しかしReactチームは、React 19じゃないプロジェクトでもReact Compilerが動くようにpolyfillを用意してくれてます。

the gist isn’t unsafe, it’s not efficient and not maintained basically. so yes, it is viable as a stop gap solution for the short term.

このpolyfillは安全ではないということではなく、一時的な解決策としてとされてますね。非効率かつメンテされないので本番適用は自己責任でお願いします😗

入れてみる

React v17.0.2 + Viteのプロジェクトに導入しました。
最初は以下に従って、ViteのプロジェクトにReact Compilerを入れます。
https://react.dev/learn/react-compiler#usage-with-vite

  1. React Compilerインストール
pnpm add babel-plugin-react-compiler

vite.config.jsを以下のように設定します。

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

const ReactCompilerConfig = {};

// https://vitejs.dev/config/
export default defineConfig({
	plugins: [
		react({
			babel: {
				plugins: [["babel-plugin-react-compiler", ReactCompilerConfig]],
			},
		}),
	],
});
  1. polyfillを導入する

rootにてpolyfillの置く場所を作成します。自分はlibのフォルダーを作成し、中にreact-compiler-runtimeのフォルダーを置きました。

lib/react-compiler-runtime配下にて以下のファイルとその内容を作成します。

lib/react-compiler-runtime/package.json
{
	"name": "react-compiler-runtime",
	"version": "0.0.1",
	"license": "MIT",
	"main": "index.js",
	"dependencies": {
		"react": "^18.2.0"
	}
}

lib/react-compiler-runtime/index.js
const React = require("react");
const $empty = Symbol.for("react.memo_cache_sentinel");
/**
 * DANGER: this hook is NEVER meant to be called directly!
 *
 * Note that this is a temporary userspace implementation of this function
 * from React 19. It is not as efficient and may invalidate more frequently
 * than the official API. Please upgrade to React 19 as soon as you can.
 **/
export function c(size) {
	return React.useState(() => {
		const $ = new Array(size);
		for (let ii = 0; ii < size; ii++) {
			$[ii] = $empty;
		}
		// @ts-ignore
		$[$empty] = true;
		return $;
	})[0];
}

作成後、lib/react-compiler-runtime配下に遷移し、依存パッケージをインストールします

  1. polyfillを依存パッケージとして設定する

rootpackage.jsonにて以下のように設定しました

package.json
"dependencies":{
    "react-compiler-runtime": "file:./lib/react-compiler-runtime"
    ....

file:と設定し./lib/react-compiler-runtime作成したpolyfillのパスを設定します。

4.React Compilerのbabel設定をpolyfillに向かせる

Vite使っていますので、vite.config.jsの設定変更します。

vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

const ReactCompilerConfig = { runtimeModule: "react-compiler-runtime" }; // 👈react-compiler-runtimeを設定

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [
      react({
        babel: {
          plugins: [
            [
              "babel-plugin-react-compiler",
                ReactCompilerConfig
              ],
            ],
          },
        }),
    ],
 });

これで設定完了です。
開発環境を立ち上げ挙動確認をしましょう。

Reactの開発ツールにてHighlight updates when components render.をオンしましょう。

開発ツールにてMemo✨とタッグ付されているコンポーネントはReact Compilerによってメモ化されています!

参考レポジトリを以下にて確認できますので、ぜひ確認してください
https://github.com/undesicimo/r17-with-compiler

Discussion

joshjosh

React 18で試しても

Error: Missing "./compiler-runtime" specifier in "react" package
    at e

とエラー出力される方は、
@vitejs/plugin-react4.2.1にダウングレードしてみてください