Skip to content

Generate types for virtual:react-router/server-build #13152

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

Merged
merged 1 commit into from
Mar 4, 2025
Merged
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
5 changes: 5 additions & 0 deletions .changeset/silver-peas-shop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@react-router/dev": minor
---

Generate types for `virtual:react-router/server-build` module
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ declare module "react-router" {
}

const requestHandler = createRequestHandler(
// @ts-expect-error
() => import("virtual:react-router/server-build"),
import.meta.env.MODE
);
Expand Down
43 changes: 43 additions & 0 deletions integration/typegen-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,4 +444,47 @@ test.describe("typegen", () => {
expect(proc.stderr.toString()).toBe("");
expect(proc.status).toBe(0);
});

test.describe("virtual:react-router/server-build", async () => {
test("static import matches 'createRequestHandler' argument type", async () => {
const cwd = await createProject({
"vite.config.ts": viteConfig,
"app/routes.ts": tsx`
import { type RouteConfig } from "@react-router/dev/routes";
export default [] satisfies RouteConfig;
`,
"app/handler.ts": tsx`
import { createRequestHandler } from "react-router";
import * as serverBuild from "virtual:react-router/server-build";
export default createRequestHandler(serverBuild);
`,
});

const proc = typecheck(cwd);
expect(proc.stdout.toString()).toBe("");
expect(proc.stderr.toString()).toBe("");
expect(proc.status).toBe(0);
});

test("dynamic import matches 'createRequestHandler' function argument type", async () => {
const cwd = await createProject({
"vite.config.ts": viteConfig,
"app/routes.ts": tsx`
import { type RouteConfig } from "@react-router/dev/routes";
export default [] satisfies RouteConfig;
`,
"app/handler.ts": tsx`
import { createRequestHandler } from "react-router";
export default createRequestHandler(
() => import("virtual:react-router/server-build")
);
`,
});

const proc = typecheck(cwd);
expect(proc.stdout.toString()).toBe("");
expect(proc.stderr.toString()).toBe("");
expect(proc.status).toBe(0);
});
});
});
20 changes: 20 additions & 0 deletions packages/react-router-dev/typegen/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ async function writeAll(ctx: Context): Promise<void> {

const registerPath = Path.join(typegenDir, "+register.ts");
fs.writeFileSync(registerPath, register(ctx));

const virtualPath = Path.join(typegenDir, "+virtual.ts");
fs.writeFileSync(virtualPath, virtual);
}

function register(ctx: Context) {
Expand Down Expand Up @@ -146,3 +149,20 @@ function register(ctx: Context) {

return [register, Babel.generate(typeParams).code].join("\n\n");
}

const virtual = ts`
declare module "virtual:react-router/server-build" {
import { ServerBuild } from "react-router";
export const assets: ServerBuild["assets"];
export const assetsBuildDirectory: ServerBuild["assetsBuildDirectory"];
export const basename: ServerBuild["basename"];
export const entry: ServerBuild["entry"];
export const future: ServerBuild["future"];
export const isSpaMode: ServerBuild["isSpaMode"];
export const prerender: ServerBuild["prerender"];
export const publicPath: ServerBuild["publicPath"];
export const routes: ServerBuild["routes"];
export const ssr: ServerBuild["ssr"];
export const unstable_getCriticalCss: ServerBuild["unstable_getCriticalCss"];
}
`;
2 changes: 1 addition & 1 deletion packages/react-router-dev/vite/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -756,7 +756,7 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => {
ctx.reactRouterConfig.future.unstable_viteEnvironmentApi &&
viteCommand === "serve"
? `
export const getCriticalCss = ({ pathname }) => {
export const unstable_getCriticalCss = ({ pathname }) => {
Copy link
Member Author

@markdalgleish markdalgleish Mar 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seeing this API in a new light as part of this PR made me realise this should be marked as unstable. It was only ever defined when setting the future.unstable_viteEnvironmentApi flag.

return {
rel: "stylesheet",
href: "${
Expand Down
2 changes: 1 addition & 1 deletion packages/react-router/lib/server-runtime/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export interface ServerBuild {
assetsBuildDirectory: string;
future: FutureConfig;
ssr: boolean;
getCriticalCss?: (args: {
unstable_getCriticalCss?: (args: {
pathname: string;
}) => OptionalCriticalCss | Promise<OptionalCriticalCss>;
/**
Expand Down
4 changes: 2 additions & 2 deletions packages/react-router/lib/server-runtime/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,8 @@ export const createRequestHandler: CreateRequestHandlerFunction = (
let { pathname } = url;

let criticalCss: CriticalCss | undefined = undefined;
if (_build.getCriticalCss) {
criticalCss = await _build.getCriticalCss({ pathname });
if (_build.unstable_getCriticalCss) {
criticalCss = await _build.unstable_getCriticalCss({ pathname });
} else if (
mode === ServerMode.Development &&
getDevServerHooks()?.getCriticalCss
Expand Down
1 change: 0 additions & 1 deletion playground/vite-plugin-cloudflare/workers/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ declare module "react-router" {
}

const requestHandler = createRequestHandler(
// @ts-expect-error
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing this line is what this PR is all about 😄

() => import("virtual:react-router/server-build"),
import.meta.env.MODE
);
Expand Down