diff --git a/packages/plugin-react/README.md b/packages/plugin-react/README.md index 5e5fbc497..4c66419dd 100644 --- a/packages/plugin-react/README.md +++ b/packages/plugin-react/README.md @@ -46,6 +46,14 @@ Control where the JSX factory is imported from. Default to `'react'` react({ jsxImportSource: '@emotion/react' }) ``` +## jsxRuntime + +By default, the plugin uses the [automatic JSX runtime](https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html). However, if you encounter any issues, you may opt out using the `jsxRuntime` option. + +```js +react({ jsxRuntime: 'classic' }) +``` + ### babel The `babel` option lets you add plugins, presets, and [other configuration](https://babeljs.io/docs/en/options) to the Babel transformation performed on each included file. diff --git a/packages/plugin-react/package.json b/packages/plugin-react/package.json index 19f0f7175..919f42a46 100644 --- a/packages/plugin-react/package.json +++ b/packages/plugin-react/package.json @@ -42,7 +42,6 @@ "@babel/core": "^7.21.4", "@babel/plugin-transform-react-jsx-self": "^7.21.0", "@babel/plugin-transform-react-jsx-source": "^7.19.6", - "magic-string": "^0.30.0", "react-refresh": "^0.14.0" }, "peerDependencies": { diff --git a/packages/plugin-react/src/index.ts b/packages/plugin-react/src/index.ts index 1643d3ea7..9022dfd02 100644 --- a/packages/plugin-react/src/index.ts +++ b/packages/plugin-react/src/index.ts @@ -8,8 +8,6 @@ import type { ResolvedConfig, UserConfig, } from 'vite' -import MagicString from 'magic-string' -import type { SourceMap } from 'magic-string' import { addRefreshWrapper, preambleCode, @@ -20,18 +18,17 @@ import { export interface Options { include?: string | RegExp | Array exclude?: string | RegExp | Array - /** - * @deprecated All tools now support the automatic runtime, and it has been backported - * up to React 16. This allows to skip the React import and can produce smaller bundlers. - * @default "automatic" - */ - jsxRuntime?: 'classic' | 'automatic' /** * Control where the JSX factory is imported from. * https://esbuild.github.io/api/#jsx-import-source * @default 'react' */ jsxImportSource?: string + /** + * Note: Skipping React import with classic runtime is not supported from v4 + * @default "automatic" + */ + jsxRuntime?: 'classic' | 'automatic' /** * Babel configuration applied in both dev and prod. */ @@ -82,7 +79,6 @@ declare module 'vite' { } } -const prependReactImportCode = "import React from 'react'; " const refreshContentRE = /\$Refresh(?:Reg|Sig)\$\(/ const defaultIncludeRE = /\.[tj]sx?$/ const tsRE = /\.tsx?$/ @@ -92,7 +88,6 @@ export default function viteReact(opts: Options = {}): PluginOption[] { let devBase = '/' const filter = createFilter(opts.include ?? defaultIncludeRE, opts.exclude) const devRuntime = `${opts.jsxImportSource ?? 'react'}/jsx-dev-runtime` - let needHiresSourcemap = false let isProduction = true let projectRoot = process.cwd() let skipFastRefresh = false @@ -105,7 +100,7 @@ export default function viteReact(opts: Options = {}): PluginOption[] { // - import * as React from 'react'; // - import React from 'react'; // - import React, {useEffect} from 'react'; - const importReactRE = /(?:^|\n)import\s+(?:\*\s+as\s+)?React(?:,|\s+)/ + const importReactRE = /(?:^|\s)import\s+(?:\*\s+as\s+)?React(?:,|\s+)/ const viteBabel: Plugin = { name: 'vite:react-babel', @@ -129,16 +124,9 @@ export default function viteReact(opts: Options = {}): PluginOption[] { configResolved(config) { devBase = config.base projectRoot = config.root - needHiresSourcemap = - config.command === 'build' && !!config.build.sourcemap isProduction = config.isProduction skipFastRefresh = isProduction || config.command === 'build' - if (opts.jsxRuntime === 'classic') { - config.logger.warnOnce( - '[@vitejs/plugin-react] Support for classic runtime is deprecated.', - ) - } if ('jsxPure' in opts) { config.logger.warnOnce( '[@vitejs/plugin-react] jsxPure was removed. You can configure esbuild.jsxSideEffects directly.', @@ -191,7 +179,6 @@ export default function viteReact(opts: Options = {}): PluginOption[] { ]) } - let prependReactImport = false if (opts.jsxRuntime === 'classic' && isJSX) { if (!isProduction) { // These development plugins are only needed for the classic runtime. @@ -200,24 +187,6 @@ export default function viteReact(opts: Options = {}): PluginOption[] { await loadPlugin('@babel/plugin-transform-react-jsx-source'), ) } - - // Even if the automatic JSX runtime is not used, we can still - // inject the React import for .jsx and .tsx modules. - if (!importReactRE.test(code)) { - prependReactImport = true - } - } - - let inputMap: SourceMap | undefined - if (prependReactImport) { - if (needHiresSourcemap) { - const s = new MagicString(code) - s.prepend(prependReactImportCode) - code = s.toString() - inputMap = s.generateMap({ hires: true, source: id }) - } else { - code = prependReactImportCode + code - } } // Avoid parsing if no special transformation is needed @@ -226,7 +195,7 @@ export default function viteReact(opts: Options = {}): PluginOption[] { !babelOptions.configFile && !babelOptions.babelrc ) { - return { code, map: inputMap ?? null } + return } const parserPlugins = [...babelOptions.parserOpts.plugins] @@ -256,8 +225,6 @@ export default function viteReact(opts: Options = {}): PluginOption[] { }, plugins, sourceMaps: true, - // Vite handles sourcemap flattening - inputSourceMap: inputMap ?? (false as any), }) if (result) { diff --git a/playground/react-classic/App.jsx b/playground/react-classic/App.jsx index 1de7461b1..94326dc5f 100644 --- a/playground/react-classic/App.jsx +++ b/playground/react-classic/App.jsx @@ -1,4 +1,4 @@ -import { useState } from 'react' +import React, { useState } from 'react' function App() { const [count, setCount] = useState(0) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1fe22b34b..93cdc422d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -63,13 +63,11 @@ importers: '@babel/core': ^7.21.4 '@babel/plugin-transform-react-jsx-self': ^7.21.0 '@babel/plugin-transform-react-jsx-source': ^7.19.6 - magic-string: ^0.30.0 react-refresh: ^0.14.0 dependencies: '@babel/core': 7.21.4 '@babel/plugin-transform-react-jsx-self': 7.21.0_@babel+core@7.21.4 '@babel/plugin-transform-react-jsx-source': 7.19.6_@babel+core@7.21.4 - magic-string: 0.30.0 react-refresh: 0.14.0 playground: @@ -4120,6 +4118,7 @@ packages: engines: {node: '>=12'} dependencies: '@jridgewell/sourcemap-codec': 1.4.14 + dev: true /map-obj/1.0.1: resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==}