Repository navigation
feat: add react plugin for client components #267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| import type { Plugin, UserConfig, ViteDevServer } from "vite"; | ||
| import type { Plugin, PluginOption, UserConfig, ViteDevServer } from "vite"; | ||
| import { loadEnv, parseAst } from "vite"; | ||
| import { pagesRouter, apiRouter, invalidateRouteCache, matchRoute, patternToNextFormat as pagesPatternToNextFormat, type Route } from "./routing/pages-router.js"; | ||
| import { appRouter, invalidateAppRouteCache } from "./routing/app-router.js"; | ||
|
|
@@ -37,6 +37,7 @@ import { scanMetadataFiles } from "./server/metadata-routes.js"; | |
| import { staticExportPages } from "./build/static-export.js"; | ||
| import { detectPackageManager } from "./utils/project.js"; | ||
| import tsconfigPaths from "vite-tsconfig-paths"; | ||
| import react, { Options as VitePluginReactOptions } from "@vitejs/plugin-react"; | ||
| import MagicString from "magic-string"; | ||
| import path from "node:path"; | ||
| import { fileURLToPath, pathToFileURL } from "node:url"; | ||
|
|
@@ -572,9 +573,17 @@ export interface VinextOptions { | |
| * @default true | ||
| */ | ||
| rsc?: boolean; | ||
| /** | ||
| * Options passed to @vitejs/plugin-react (React Fast Refresh + JSX transform). | ||
| * Enabled by default. Set to `false` to disable (e.g. if you already have | ||
| * @vitejs/plugin-react in your vite.config.ts), or pass an options object | ||
| * to customize the Babel transform. | ||
| * @default true | ||
| */ | ||
| react?: VitePluginReactOptions | boolean; | ||
| } | ||
|
|
||
| export default function vinext(options: VinextOptions = {}): Plugin[] { | ||
| export default function vinext(options: VinextOptions = {}): PluginOption[] { | ||
| let root: string; | ||
| let pagesDir: string; | ||
| let appDir: string; | ||
|
|
@@ -1680,10 +1689,16 @@ hydrate(); | |
| // files are detected and @mdx-js/rollup is installed. | ||
| let mdxDelegate: Plugin | null = null; | ||
|
|
||
| const plugins: (Plugin | Promise<Plugin[]>)[] = [ | ||
| const reactPlugin = options.react === false | ||
| ? false | ||
| : react(options.react === true ? undefined : options.react); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Worth considering: if a user already has The
Not blocking since no current examples or fixtures do this, but it will come up. |
||
|
|
||
| const plugins: PluginOption[] = [ | ||
| // Resolve tsconfig paths/baseUrl aliases so real-world Next.js repos | ||
| // that use @/*, #/*, or baseUrl imports work out of the box. | ||
| tsconfigPaths(), | ||
| // React Fast Refresh + JSX transform for client components. | ||
| reactPlugin, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: when |
||
| // Transform CJS require()/module.exports to ESM before other plugins | ||
| // analyze imports (RSC directive scanning, shim resolution, etc.) | ||
| commonjs(), | ||
|
|
@@ -2333,12 +2348,11 @@ hydrate(); | |
| name: "vinext:pages-router", | ||
|
|
||
| // HMR: trigger full-reload for Pages Router page changes. | ||
| // Without @vitejs/plugin-react (React Fast Refresh), component edits | ||
| // can't be hot-updated. In theory Vite's default propagation should | ||
| // reach the root and trigger a full-reload, but the Pages Router | ||
| // injects hydration via inline <script type="module"> which may not | ||
| // be tracked in the module graph. Explicitly sending full-reload | ||
| // ensures changes are always reflected in the browser. | ||
| // Even with @vitejs/plugin-react providing React Fast Refresh, | ||
| // the Pages Router injects hydration via inline <script type="module"> | ||
| // which may not be tracked in Vite's module graph. Explicitly | ||
| // sending full-reload ensures changes are always reflected in | ||
| // the browser. | ||
| hotUpdate(options: { file: string; server: ViteDevServer; modules: any[] }) { | ||
| if (!hasPagesDir || hasAppDir) return; | ||
| const ext = /\.(tsx?|jsx?|mdx)$/; | ||
|
|
@@ -3425,7 +3439,7 @@ hydrate(); | |
| plugins.push(rscPluginPromise); | ||
| } | ||
|
|
||
| return plugins as Plugin[]; | ||
| return plugins; | ||
| } | ||
|
|
||
| /** | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
@default undefinedis misleading — whenoptions.reactisundefined(the default), the plugin IS enabled with default options (line 1692 falls through toreact(undefined)). The effective default behavior is "enabled with defaults", not "undefined".Consider
@default trueor rewording the description to say "Enabled by default. Set tofalseto disable."