diff --git a/packages/plugin-react/CHANGELOG.md b/packages/plugin-react/CHANGELOG.md index c0b6f75f..1972cc9f 100644 --- a/packages/plugin-react/CHANGELOG.md +++ b/packages/plugin-react/CHANGELOG.md @@ -2,6 +2,33 @@ ## Unreleased +### React Compiler runtimeModule option removed + +React Compiler was updated to accept a `target` option and `runtimeModule` was removed. vite-plugin-react will still detect `runtimeModule` for backwards compatibility. + +When using a custom `runtimeModule` or `target !== '19'`, the plugin will not try to pre-optimize `react/compiler-runtime` dependency. + +The [react-compiler-runtime](https://www.npmjs.com/package/react-compiler-runtime) is now available on npm can be used instead of the local shim for people using the compiler with React < 19. + +Here is the configuration to use the compiler with React 18 and correct source maps in development: + +```bash +npm install react-compiler-runtime +``` + +```ts +export default defineConfig(({ command }) => { + const babelPlugins = [['babel-plugin-react-compiler', { target: '18' }]] + if (command === 'serve') { + babelPlugins.push(['@babel/plugin-transform-react-jsx-development', {}]) + } + + return { + plugins: [react({ babel: { plugins: babelPlugins } })], + } +}) +```` + ## 4.3.2 (2024-09-29) Ignore directive sourcemap error [#369](https://github.com/vitejs/vite-plugin-react/issues/369) diff --git a/packages/plugin-react/src/index.ts b/packages/plugin-react/src/index.ts index cff959b0..f5c1e3c6 100644 --- a/packages/plugin-react/src/index.ts +++ b/packages/plugin-react/src/index.ts @@ -237,9 +237,10 @@ export default function viteReact(opts: Options = {}): PluginOption[] { // Required for esbuild.jsxDev to provide correct line numbers // This crates issues the react compiler because the re-order is too important // People should use @babel/plugin-transform-react-jsx-development to get back good line numbers - retainLines: hasCompiler(plugins) - ? false - : !isProduction && isJSX && opts.jsxRuntime !== 'classic', + retainLines: + getReactCompilerPlugin(plugins) != null + ? false + : !isProduction && isJSX && opts.jsxRuntime !== 'classic', parserOpts: { ...babelOptions.parserOpts, sourceType: 'module', @@ -274,8 +275,11 @@ export default function viteReact(opts: Options = {}): PluginOption[] { const dependencies = ['react', jsxImportDevRuntime, jsxImportRuntime] const staticBabelPlugins = typeof opts.babel === 'object' ? opts.babel?.plugins ?? [] : [] - if (hasCompilerWithDefaultRuntime(staticBabelPlugins)) { - dependencies.push('react/compiler-runtime') + const reactCompilerPlugin = getReactCompilerPlugin(staticBabelPlugins) + if (reactCompilerPlugin != null) { + const reactCompilerRuntimeModule = + getReactCompilerRuntimeModule(reactCompilerPlugin) + dependencies.push(reactCompilerRuntimeModule) } const viteReactRefresh: Plugin = { @@ -377,21 +381,28 @@ function defined(value: T | undefined): value is T { return value !== undefined } -function hasCompiler(plugins: ReactBabelOptions['plugins']) { - return plugins.some( +function getReactCompilerPlugin(plugins: ReactBabelOptions['plugins']) { + return plugins.find( (p) => p === 'babel-plugin-react-compiler' || (Array.isArray(p) && p[0] === 'babel-plugin-react-compiler'), ) } -// https://gist.github.com/poteto/37c076bf112a07ba39d0e5f0645fec43 -function hasCompilerWithDefaultRuntime(plugins: ReactBabelOptions['plugins']) { - return plugins.some( - (p) => - p === 'babel-plugin-react-compiler' || - (Array.isArray(p) && - p[0] === 'babel-plugin-react-compiler' && - p[1]?.runtimeModule === undefined), - ) +type ReactCompilerRuntimeModule = + | 'react/compiler-runtime' // from react namespace + | 'react-compiler-runtime' // npm package +function getReactCompilerRuntimeModule( + plugin: babelCore.PluginItem, +): ReactCompilerRuntimeModule { + let moduleName: ReactCompilerRuntimeModule = 'react/compiler-runtime' + if (Array.isArray(plugin)) { + if (plugin[1]?.target === '17' || plugin[1]?.target === '18') { + moduleName = 'react-compiler-runtime' + } else if (typeof plugin[1]?.runtimeModule === 'string') { + // backward compatibility from (#374), can be removed in next major + moduleName = plugin[1]?.runtimeModule + } + } + return moduleName } diff --git a/playground/compiler-react-18/lib/react-compiler-runtime/index.js b/playground/compiler-react-18/lib/react-compiler-runtime/index.js deleted file mode 100644 index 3d794bf7..00000000 --- a/playground/compiler-react-18/lib/react-compiler-runtime/index.js +++ /dev/null @@ -1,20 +0,0 @@ -import React from '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] -} diff --git a/playground/compiler-react-18/lib/react-compiler-runtime/package.json b/playground/compiler-react-18/lib/react-compiler-runtime/package.json deleted file mode 100644 index 372531f5..00000000 --- a/playground/compiler-react-18/lib/react-compiler-runtime/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "react-compiler-runtime", - "private": true, - "main": "index.js", - "dependencies": { - "react": "^18.3.1" - } -} diff --git a/playground/compiler-react-18/package.json b/playground/compiler-react-18/package.json index 969a668e..6fa2c55d 100644 --- a/playground/compiler-react-18/package.json +++ b/playground/compiler-react-18/package.json @@ -9,7 +9,7 @@ }, "dependencies": { "react": "^18.3.1", - "react-compiler-runtime": "file:./lib/react-compiler-runtime", + "react-compiler-runtime": "0.0.0-experimental-8d8e73f-20241009", "react-dom": "^18.3.1" }, "devDependencies": { @@ -17,7 +17,7 @@ "@types/react": "^18.3.10", "@types/react-dom": "^18.3.0", "@vitejs/plugin-react": "workspace:*", - "babel-plugin-react-compiler": "^0.0.0-experimental-b12479e-20240926", + "babel-plugin-react-compiler": "0.0.0-experimental-58c2b1c-20241009", "typescript": "^5.6.2", "vite": "^5.4.8" } diff --git a/playground/compiler-react-18/vite.config.ts b/playground/compiler-react-18/vite.config.ts index 36403615..8850c1ac 100644 --- a/playground/compiler-react-18/vite.config.ts +++ b/playground/compiler-react-18/vite.config.ts @@ -1,8 +1,6 @@ import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' -// https://gist.github.com/poteto/37c076bf112a07ba39d0e5f0645fec43 - // https://vitejs.dev/config/ export default defineConfig(({ command }) => { return { @@ -10,12 +8,7 @@ export default defineConfig(({ command }) => { plugins: [ react({ babel: { - plugins: [ - [ - 'babel-plugin-react-compiler', - { runtimeModule: 'react-compiler-runtime' }, - ], - ], + plugins: [['babel-plugin-react-compiler', { target: '18' }]], }, }), ], diff --git a/playground/compiler/package.json b/playground/compiler/package.json index dc5a11c0..1ce96ddf 100644 --- a/playground/compiler/package.json +++ b/playground/compiler/package.json @@ -16,7 +16,7 @@ "@types/react": "^18.3.10", "@types/react-dom": "^18.3.0", "@vitejs/plugin-react": "workspace:*", - "babel-plugin-react-compiler": "^0.0.0-experimental-b12479e-20240926", + "babel-plugin-react-compiler": "0.0.0-experimental-58c2b1c-20241009", "typescript": "^5.6.2", "vite": "^5.4.8" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 83cc240f..622f2d11 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -150,8 +150,8 @@ importers: specifier: workspace:* version: link:../../packages/plugin-react babel-plugin-react-compiler: - specifier: ^0.0.0-experimental-b12479e-20240926 - version: 0.0.0-experimental-b12479e-20240926 + specifier: 0.0.0-experimental-58c2b1c-20241009 + version: 0.0.0-experimental-58c2b1c-20241009 typescript: specifier: ^5.6.2 version: 5.6.2 @@ -165,8 +165,8 @@ importers: specifier: ^18.3.1 version: 18.3.1 react-compiler-runtime: - specifier: file:./lib/react-compiler-runtime - version: link:lib/react-compiler-runtime + specifier: 0.0.0-experimental-8d8e73f-20241009 + version: 0.0.0-experimental-8d8e73f-20241009(react@18.3.1) react-dom: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) @@ -184,8 +184,8 @@ importers: specifier: workspace:* version: link:../../packages/plugin-react babel-plugin-react-compiler: - specifier: ^0.0.0-experimental-b12479e-20240926 - version: 0.0.0-experimental-b12479e-20240926 + specifier: 0.0.0-experimental-58c2b1c-20241009 + version: 0.0.0-experimental-58c2b1c-20241009 typescript: specifier: ^5.6.2 version: 5.6.2 @@ -193,12 +193,6 @@ importers: specifier: ^5.4.8 version: 5.4.8(@types/node@20.16.10) - playground/compiler-react-18/lib/react-compiler-runtime: - dependencies: - react: - specifier: ^18.3.1 - version: 18.3.1 - playground/mdx: dependencies: react: @@ -1496,8 +1490,8 @@ packages: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} - babel-plugin-react-compiler@0.0.0-experimental-b12479e-20240926: - resolution: {integrity: sha512-QoiS1tZsE7gDdd3EFLpprvM4edUBhNrV98El2G073Onhg2vJ+wub+RpEtztoNTNGrAwogj+CcFU9j1VxxzhiPQ==} + babel-plugin-react-compiler@0.0.0-experimental-58c2b1c-20241009: + resolution: {integrity: sha512-/DSwpfz7c1hK5dpxxlLxQJtvXCF3RjN3ZCaJ43NM4BEvzTpaS0C0jasXVBEUIFumBcdaoirFbfZkyk9htY+6Xw==} bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} @@ -2040,6 +2034,7 @@ packages: eslint@8.57.1: resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true espree@9.6.1: @@ -3316,6 +3311,11 @@ packages: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} + react-compiler-runtime@0.0.0-experimental-8d8e73f-20241009: + resolution: {integrity: sha512-TEOS8csCfa/xSNt8ft9yRAimOJNetQIOuTgMFU2rv3dhDUOpM3e/Jrv+55uGUKMUYK6kCBV4QYsviLl2c8JfOg==} + peerDependencies: + react: ^18.2.0 || ^19.0.0 + react-dom@18.3.1: resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} peerDependencies: @@ -4040,7 +4040,7 @@ snapshots: '@babel/generator@7.2.0': dependencies: - '@babel/types': 7.24.5 + '@babel/types': 7.25.6 jsesc: 2.5.2 lodash: 4.17.21 source-map: 0.5.7 @@ -4130,7 +4130,7 @@ snapshots: '@babel/parser@7.24.5': dependencies: - '@babel/types': 7.24.5 + '@babel/types': 7.25.6 '@babel/parser@7.25.6': dependencies: @@ -5090,10 +5090,10 @@ snapshots: cosmiconfig: 7.1.0 resolve: 1.22.8 - babel-plugin-react-compiler@0.0.0-experimental-b12479e-20240926: + babel-plugin-react-compiler@0.0.0-experimental-58c2b1c-20241009: dependencies: '@babel/generator': 7.2.0 - '@babel/types': 7.24.5 + '@babel/types': 7.25.6 chalk: 4.1.2 invariant: 2.2.4 pretty-format: 24.9.0 @@ -7366,6 +7366,10 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 + react-compiler-runtime@0.0.0-experimental-8d8e73f-20241009(react@18.3.1): + dependencies: + react: 18.3.1 + react-dom@18.3.1(react@18.3.1): dependencies: loose-envify: 1.4.0