Skip to content

Commit

Permalink
refactor vite plugin (#12539)
Browse files Browse the repository at this point in the history
* namespace vite plugins with `react-router:`

* refactor: pre-compute virtual module resolvedId and url
  • Loading branch information
pcattori authored Dec 13, 2024
1 parent a897f99 commit 151c25c
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 54 deletions.
93 changes: 47 additions & 46 deletions packages/react-router-dev/vite/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { generate, parse } from "./babel";
import type { NodeRequestHandler } from "./node-adapter";
import { fromNodeRequest, toNodeRequest } from "./node-adapter";
import { getStylesForUrl, isCssModulesFile } from "./styles";
import * as VirtualModule from "./vmod";
import * as VirtualModule from "./virtual-module";
import { resolveFileUrl } from "./resolve-file-url";
import { combineURLs } from "./combine-urls";
import { removeExports } from "./remove-exports";
Expand Down Expand Up @@ -163,11 +163,8 @@ export type ReactRouterPluginContext = ReactRouterPluginSsrBuildContext & {
viteManifestEnabled: boolean;
};

let serverBuildId = VirtualModule.id("server-build");
let serverManifestId = VirtualModule.id("server-manifest");
let browserManifestId = VirtualModule.id("browser-manifest");
let hmrRuntimeId = VirtualModule.id("hmr-runtime");
let injectHmrRuntimeId = VirtualModule.id("inject-hmr-runtime");
let virtualHmrRuntime = VirtualModule.create("hmr-runtime");
let virtualInjectHmrRuntime = VirtualModule.create("inject-hmr-runtime");

const resolveRelativeRouteFilePath = (
route: RouteManifestEntry,
Expand All @@ -180,13 +177,15 @@ const resolveRelativeRouteFilePath = (
return vite.normalizePath(fullPath);
};

let vmods = [serverBuildId, serverManifestId, browserManifestId];
let virtual = {
serverBuild: VirtualModule.create("server-build"),
serverManifest: VirtualModule.create("server-manifest"),
browserManifest: VirtualModule.create("browser-manifest"),
};

const invalidateVirtualModules = (viteDevServer: Vite.ViteDevServer) => {
vmods.forEach((vmod) => {
let mod = viteDevServer.moduleGraph.getModuleById(
VirtualModule.resolve(vmod)
);
let invalidateVirtualModules = (viteDevServer: Vite.ViteDevServer) => {
Object.values(virtual).forEach((vmod) => {
let mod = viteDevServer.moduleGraph.getModuleById(vmod.resolvedId);
if (mod) {
viteDevServer.moduleGraph.invalidateModule(mod);
}
Expand Down Expand Up @@ -513,7 +512,9 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
)};`;
})
.join("\n")}
export { default as assets } from ${JSON.stringify(serverManifestId)};
export { default as assets } from ${JSON.stringify(
virtual.serverManifest.id
)};
export const assetsBuildDirectory = ${JSON.stringify(
path.relative(
ctx.rootDirectory,
Expand Down Expand Up @@ -709,12 +710,9 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {

return {
version: String(Math.random()),
url: combineURLs(ctx.publicPath, VirtualModule.url(browserManifestId)),
url: combineURLs(ctx.publicPath, virtual.browserManifest.url),
hmr: {
runtime: combineURLs(
ctx.publicPath,
VirtualModule.url(injectHmrRuntimeId)
),
runtime: combineURLs(ctx.publicPath, virtualInjectHmrRuntime.url),
},
entry: {
module: combineURLs(
Expand Down Expand Up @@ -908,7 +906,7 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
preserveEntrySignatures: "exports-only",
input:
viteUserConfig.build?.rollupOptions?.input ??
serverBuildId,
virtual.serverBuild.id,
output: {
entryFileNames:
ctx.reactRouterConfig.serverBuildFile,
Expand Down Expand Up @@ -1012,8 +1010,8 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
plugin !== null &&
"name" in plugin &&
plugin.name !== "react-router" &&
plugin.name !== "react-router-route-exports" &&
plugin.name !== "react-router-hmr-updates"
plugin.name !== "react-router:route-exports" &&
plugin.name !== "react-router:hmr-updates"
),
],
});
Expand Down Expand Up @@ -1119,7 +1117,7 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
viteDevServer.middlewares.use(async (req, res, next) => {
try {
let build = (await viteDevServer.ssrLoadModule(
serverBuildId
virtual.serverBuild.id
)) as ServerBuild;

let handler = createRequestHandler(build, "development");
Expand Down Expand Up @@ -1253,7 +1251,7 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
},
},
{
name: "react-router-route-entry",
name: "react-router:route-entry",
enforce: "pre",
async transform(_code, id, options) {
if (!isRouteEntry(id)) return;
Expand All @@ -1279,17 +1277,18 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
},
},
{
name: "react-router-virtual-modules",
name: "react-router:virtual-modules",
enforce: "pre",
resolveId(id) {
if (vmods.includes(id)) return VirtualModule.resolve(id);
const vmod = Object.values(virtual).find((vmod) => vmod.id === id);
if (vmod) return vmod.resolvedId;
},
async load(id) {
switch (id) {
case VirtualModule.resolve(serverBuildId): {
case virtual.serverBuild.resolvedId: {
return await getServerEntry();
}
case VirtualModule.resolve(serverManifestId): {
case virtual.serverManifest.resolvedId: {
let reactRouterManifest = ctx.isSsrBuild
? await ctx.getReactRouterServerManifest()
: await getReactRouterManifestForDev();
Expand All @@ -1298,7 +1297,7 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
es6: true,
})};`;
}
case VirtualModule.resolve(browserManifestId): {
case virtual.browserManifest.resolvedId: {
if (viteCommand === "build") {
throw new Error("This module only exists in development");
}
Expand All @@ -1314,7 +1313,7 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
},
},
{
name: "react-router-dot-server",
name: "react-router:dot-server",
enforce: "pre",
async resolveId(id, importer, options) {
// https://vitejs.dev/config/dep-optimization-options
Expand All @@ -1324,9 +1323,9 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {

if (isOptimizeDeps || options?.ssr) return;

let isResolving = options?.custom?.["react-router-dot-server"] ?? false;
let isResolving = options?.custom?.["react-router:dot-server"] ?? false;
if (isResolving) return;
options.custom = { ...options.custom, "react-router-dot-server": true };
options.custom = { ...options.custom, "react-router:dot-server": true };
let resolved = await this.resolve(id, importer, options);
if (!resolved) return;

Expand Down Expand Up @@ -1384,7 +1383,7 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
},
},
{
name: "react-router-dot-client",
name: "react-router:dot-client",
async transform(code, id, options) {
if (!options?.ssr) return;
let clientFileRE = /\.client(\.[cm]?[jt]sx?)?$/;
Expand All @@ -1406,7 +1405,7 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
},
WithProps.plugin,
{
name: "react-router-route-exports",
name: "react-router:route-exports",
async transform(code, id, options) {
let route = getRoute(ctx.reactRouterConfig, id);
if (!route) return;
Expand Down Expand Up @@ -1454,17 +1453,18 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
},
},
{
name: "react-router-inject-hmr-runtime",
name: "react-router:inject-hmr-runtime",
enforce: "pre",
resolveId(id) {
if (id === injectHmrRuntimeId)
return VirtualModule.resolve(injectHmrRuntimeId);
if (id === virtualInjectHmrRuntime.id) {
return virtualInjectHmrRuntime.resolvedId;
}
},
async load(id) {
if (id !== VirtualModule.resolve(injectHmrRuntimeId)) return;
if (id !== virtualInjectHmrRuntime.resolvedId) return;

return [
`import RefreshRuntime from "${hmrRuntimeId}"`,
`import RefreshRuntime from "${virtualHmrRuntime.id}"`,
"RefreshRuntime.injectIntoGlobalHook(window)",
"window.$RefreshReg$ = () => {}",
"window.$RefreshSig$ = () => (type) => type",
Expand All @@ -1473,13 +1473,13 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
},
},
{
name: "react-router-hmr-runtime",
name: "react-router:hmr-runtime",
enforce: "pre",
resolveId(id) {
if (id === hmrRuntimeId) return VirtualModule.resolve(hmrRuntimeId);
if (id === virtualHmrRuntime.id) return virtualHmrRuntime.resolvedId;
},
async load(id) {
if (id !== VirtualModule.resolve(hmrRuntimeId)) return;
if (id !== virtualHmrRuntime.resolvedId) return;

let reactRefreshDir = path.dirname(
require.resolve("react-refresh/package.json")
Expand All @@ -1501,7 +1501,7 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
},
},
{
name: "react-router-react-refresh-babel",
name: "react-router:react-refresh-babel",
async transform(code, id, options) {
if (viteCommand !== "serve") return;
if (id.includes("/node_modules/")) return;
Expand Down Expand Up @@ -1543,7 +1543,7 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
},
},
{
name: "react-router-hmr-updates",
name: "react-router:hmr-updates",
async handleHotUpdate({ server, file, modules, read }) {
let route = getRoute(ctx.reactRouterConfig, file);

Expand All @@ -1553,8 +1553,9 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {

if (route) {
// invalidate manifest on route exports change
let serverManifest = (await server.ssrLoadModule(serverManifestId))
.default as ReactRouterManifest;
let serverManifest = (
await server.ssrLoadModule(virtual.serverManifest.id)
).default as ReactRouterManifest;

let oldRouteMetadata = serverManifest.routes[route.id];
let newRouteMetadata = await getRouteMetadata(
Expand Down Expand Up @@ -1653,7 +1654,7 @@ function withCommentBoundaries(label: string, text: string) {
}

const REACT_REFRESH_HEADER = `
import RefreshRuntime from "${hmrRuntimeId}";
import RefreshRuntime from "${virtualHmrRuntime.id}";
const inWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope;
let prevRefreshReg;
Expand Down
8 changes: 8 additions & 0 deletions packages/react-router-dev/vite/virtual-module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export function create(name: string) {
let id = `virtual:react-router/${name}`;
return {
id,
resolvedId: `\0${id}`,
url: `/@id/__x00__${id}`,
};
}
3 changes: 0 additions & 3 deletions packages/react-router-dev/vite/vmod.ts

This file was deleted.

10 changes: 5 additions & 5 deletions packages/react-router-dev/vite/with-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@ import dedent from "dedent";

import type { Babel, NodePath, ParseResult } from "./babel";
import { traverse, t } from "./babel";
import * as VirtualModule from "./vmod";
import * as VirtualModule from "./virtual-module";

const vmodId = VirtualModule.id("with-props");
const vmod = VirtualModule.create("with-props");

const NAMED_COMPONENT_EXPORTS = ["HydrateFallback", "ErrorBoundary"];

export const plugin: Plugin = {
name: "react-router-with-props",
enforce: "pre",
resolveId(id) {
if (id === vmodId) return VirtualModule.resolve(vmodId);
if (id === vmod.id) return vmod.resolvedId;
},
async load(id) {
if (id !== VirtualModule.resolve(vmodId)) return;
if (id !== vmod.resolvedId) return;
return dedent`
import { createElement as h } from "react";
import { useActionData, useLoaderData, useMatches, useParams, useRouteError } from "react-router";
Expand Down Expand Up @@ -126,7 +126,7 @@ export const transform = (ast: ParseResult<Babel.File>) => {
hocs.map(([name, identifier]) =>
t.importSpecifier(identifier, t.identifier(name))
),
t.stringLiteral(vmodId)
t.stringLiteral(vmod.id)
)
);
}
Expand Down

0 comments on commit 151c25c

Please sign in to comment.