Skip to content
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

wip: vite environments API support #12742

Draft
wants to merge 1 commit into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
219 changes: 105 additions & 114 deletions packages/react-router-dev/vite/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,17 +141,10 @@ export type ServerBundleBuildConfig = {
serverBundleId: string;
};

type ReactRouterPluginSsrBuildContext =
| {
isSsrBuild: false;
getReactRouterServerManifest?: never;
serverBundleBuildConfig?: never;
}
| {
isSsrBuild: true;
getReactRouterServerManifest: () => Promise<ReactRouterManifest>;
serverBundleBuildConfig: ServerBundleBuildConfig | null;
};
type ReactRouterPluginSsrBuildContext = {
getReactRouterServerManifest: () => Promise<ReactRouterManifest>;
serverBundleBuildConfig: ServerBundleBuildConfig | null;
};

export type ReactRouterPluginContext = ReactRouterPluginSsrBuildContext & {
rootDirectory: string;
Expand Down Expand Up @@ -457,16 +450,12 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {

let viteManifestEnabled = viteUserConfig.build?.manifest === true;

let ssrBuildCtx: ReactRouterPluginSsrBuildContext =
viteConfigEnv.isSsrBuild && viteCommand === "build"
? {
isSsrBuild: true,
getReactRouterServerManifest: async () =>
(await generateReactRouterManifestsForBuild())
.reactRouterServerManifest,
serverBundleBuildConfig: getServerBundleBuildConfig(viteUserConfig),
}
: { isSsrBuild: false };
let ssrBuildCtx: ReactRouterPluginSsrBuildContext = {
getReactRouterServerManifest: async () =>
(await generateReactRouterManifestsForBuild())
.reactRouterServerManifest,
serverBundleBuildConfig: getServerBundleBuildConfig(viteUserConfig),
};

firstLoad = false;

Expand Down Expand Up @@ -824,19 +813,98 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
? "spa"
: "custom",

ssr: {
external: ssrExternals,
resolve: {
conditions:
viteCommand === "build"
? viteServerConditions
: ["development", ...viteServerConditions],
externalConditions:
viteCommand === "build"
? viteServerConditions
: ["development", ...viteServerConditions],
builder: {
sharedConfigBuild: true,
sharedPlugins: true,
async buildApp(builder) {
await builder.build(builder.environments.client);
await builder.build(builder.environments.ssr);
// TODO: Add `serverBuilds` support
},
},

environments: {
client: {
build: {
manifest: true,
outDir: getClientBuildDirectory(ctx.reactRouterConfig),
rollupOptions: {
...baseRollupOptions,
preserveEntrySignatures: "exports-only",
input: [
ctx.entryClientFilePath,
...Object.values(ctx.reactRouterConfig.routes).map(
(route) =>
`${path.resolve(
ctx.reactRouterConfig.appDirectory,
route.file
)}${BUILD_CLIENT_ROUTE_QUERY_STRING}`
),
],
},
cssMinify:
viteCommand === "build"
? viteUserConfig.build?.cssMinify ?? true
: false,
},
resolve: {
dedupe: [
// https://react.dev/warnings/invalid-hook-call-warning#duplicate-react
"react",
"react-dom",

// see description for `optimizeDeps.include`
"react-router",
"react-router/dom",
"react-router-dom",
],
conditions:
viteCommand === "build"
? viteClientConditions
: ["development", ...viteClientConditions],
},
},
ssr: {
build: {
// We move SSR-only assets to client assets. Note that the
// SSR build can also emit code-split JS files (e.g. by
// dynamic import) under the same assets directory
// regardless of "ssrEmitAssets" option, so we also need to
// keep these JS files have to be kept as-is.
ssrEmitAssets: true,
copyPublicDir: false, // Assets in the public directory are only used by the client
manifest: true, // We need the manifest to detect SSR-only assets
outDir: getServerBuildDirectory(ctx),
rollupOptions: {
...baseRollupOptions,
preserveEntrySignatures: "exports-only",
input:
viteUserConfig.build?.rollupOptions?.input ??
virtual.serverBuild.id,
output: {
entryFileNames: ctx.reactRouterConfig.serverBuildFile,
format: ctx.reactRouterConfig.serverModuleFormat,
},
},
cssMinify:
viteCommand === "build"
? viteUserConfig.build?.cssMinify ?? true
: false,
},
resolve: {
external: ssrExternals,
conditions:
viteCommand === "build"
? viteServerConditions
: ["development", ...viteServerConditions],
externalConditions:
viteCommand === "build"
? viteServerConditions
: ["development", ...viteServerConditions],
},
},
},

optimizeDeps: {
entries: ctx.reactRouterConfig.future.unstable_optimizeDeps
? [
Expand Down Expand Up @@ -870,22 +938,6 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
jsx: "automatic",
jsxDev: viteCommand !== "build",
},
resolve: {
dedupe: [
// https://react.dev/warnings/invalid-hook-call-warning#duplicate-react
"react",
"react-dom",

// see description for `optimizeDeps.include`
"react-router",
"react-router/dom",
"react-router-dom",
],
conditions:
viteCommand === "build"
? viteClientConditions
: ["development", ...viteClientConditions],
},
base: viteUserConfig.base,

// When consumer provides an allow list for files that can be read by
Expand All @@ -896,67 +948,6 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
server: viteUserConfig.server?.fs?.allow
? { fs: { allow: defaultEntries } }
: undefined,

// Vite config options for building
...(viteCommand === "build"
? {
build: {
cssMinify: viteUserConfig.build?.cssMinify ?? true,
...(!viteConfigEnv.isSsrBuild
? {
manifest: true,
outDir: getClientBuildDirectory(ctx.reactRouterConfig),
rollupOptions: {
...baseRollupOptions,
preserveEntrySignatures: "exports-only",
input: [
ctx.entryClientFilePath,
...Object.values(ctx.reactRouterConfig.routes).map(
(route) =>
`${path.resolve(
ctx.reactRouterConfig.appDirectory,
route.file
)}${BUILD_CLIENT_ROUTE_QUERY_STRING}`
),
],
},
}
: {
// We move SSR-only assets to client assets. Note that the
// SSR build can also emit code-split JS files (e.g. by
// dynamic import) under the same assets directory
// regardless of "ssrEmitAssets" option, so we also need to
// keep these JS files have to be kept as-is.
ssrEmitAssets: true,
copyPublicDir: false, // Assets in the public directory are only used by the client
manifest: true, // We need the manifest to detect SSR-only assets
outDir: getServerBuildDirectory(ctx),
rollupOptions: {
...baseRollupOptions,
preserveEntrySignatures: "exports-only",
input:
viteUserConfig.build?.rollupOptions?.input ??
virtual.serverBuild.id,
output: {
entryFileNames:
ctx.reactRouterConfig.serverBuildFile,
format: ctx.reactRouterConfig.serverModuleFormat,
},
},
}),
},
}
: undefined),

// Vite config options for SPA preview mode
...(viteCommand === "serve" && ctx.reactRouterConfig.ssr === false
? {
build: {
manifest: true,
outDir: getClientBuildDirectory(ctx.reactRouterConfig),
},
}
: undefined),
};
},
async configResolved(resolvedViteConfig) {
Expand Down Expand Up @@ -985,7 +976,6 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
{
command: viteConfig.command,
mode: viteConfig.mode,
isSsrBuild: ctx.isSsrBuild,
},
viteConfig.configFile
);
Expand Down Expand Up @@ -1174,7 +1164,7 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
// After the SSR build is finished, we inspect the Vite manifest for
// the SSR build and move server-only assets to client assets directory
async handler() {
if (!ctx.isSsrBuild) {
if (this.environment.name !== "ssr") {
return;
}

Expand Down Expand Up @@ -1319,9 +1309,10 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
return await getServerEntry();
}
case virtual.serverManifest.resolvedId: {
let reactRouterManifest = ctx.isSsrBuild
? await ctx.getReactRouterServerManifest()
: await getReactRouterManifestForDev();
let reactRouterManifest =
this.environment.name === "ssr"
? await ctx.getReactRouterServerManifest()
: await getReactRouterManifestForDev();

return `export default ${jsesc(reactRouterManifest, {
es6: true,
Expand Down
2 changes: 1 addition & 1 deletion playground/framework/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"sideEffects": false,
"type": "module",
"scripts": {
"build": "react-router build",
"build": "vite build --app",
"dev": "react-router dev",
"start": "react-router-serve ./build/server/index.js",
"typecheck": "react-router typegen && tsc"
Expand Down
Loading