Skip to content

[pull] main from remix-run:main #114

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 28 commits into from
Apr 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6e98814
fix(react-router): Add better error messaging when `getLoadContext` i…
brophdawg11 Apr 4, 2025
bd50e07
Merge branch 'release-next' into dev
brophdawg11 Apr 4, 2025
c923ded
Properly handle redirects in prerendered pages (#13365)
brophdawg11 Apr 7, 2025
9f07f81
Revalidate prerendered paths when param values change (#13380)
brophdawg11 Apr 7, 2025
a87b796
Refactor lazy tests (#13383)
markdalgleish Apr 8, 2025
c63b509
Skip `route.lazy` hydration properties after hydration (#13376)
markdalgleish Apr 8, 2025
710626f
refactor(react-router): internal data strategy (#13253)
brophdawg11 Apr 8, 2025
c40f786
Update LoaderFunctionArgs and friends when middleware is enabled (#13…
brophdawg11 Apr 8, 2025
aae4b2c
Stop inserting null placeholders for non-executed loaders in staticHa…
brophdawg11 Apr 9, 2025
52358da
Refactor dataStrategy for easier RSC abstraction (#13344)
brophdawg11 Apr 9, 2025
9b3accc
fix lint issues
brophdawg11 Apr 9, 2025
8bf7177
Fix flaky split route modules test (#13394)
markdalgleish Apr 10, 2025
416d3e2
Remove missing react-router exports in tests (#13392)
markdalgleish Apr 10, 2025
90695fb
Add `unstable_runClientMiddleware` API for `dataStrategy` (#13395)
brophdawg11 Apr 10, 2025
18f1b70
Refactor dataStrategy for better use with RSC (#13396)
brophdawg11 Apr 10, 2025
65774ea
Support rolldown-vite in integration tests (#13388)
markdalgleish Apr 11, 2025
7bc2422
chore(react-router): remove `@types/cookie` dependency (#13400)
MichaelDeBoey Apr 11, 2025
cd5681b
Slight refactor of fetchAndDecode for RSC (#13409)
brophdawg11 Apr 14, 2025
726b524
Add script for starting a prerelease
brophdawg11 Apr 15, 2025
c97fd4c
Merge branch 'main' into release-next
brophdawg11 Apr 15, 2025
d04ce51
Enter prerelease mode
brophdawg11 Apr 15, 2025
6ce4a79
chore: Update version for release (pre) (#13412)
github-actions[bot] Apr 15, 2025
360726d
Draft release notes
brophdawg11 Apr 15, 2025
77f693c
Update release notes
brophdawg11 Apr 15, 2025
6734abc
Update release notes
brophdawg11 Apr 15, 2025
1c82938
Exit prerelease mode
brophdawg11 Apr 17, 2025
5dd7c15
chore: Update version for release (#13422)
github-actions[bot] Apr 17, 2025
b5ae784
Merge branch 'release-next'
brophdawg11 Apr 17, 2025
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
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ node_modules/
pnpm-lock.yaml
/docs/api
examples/**/dist/
/integration/helpers/vite-plugin-cloudflare-template/worker-configuration.d.ts
/playground/
/playground-local/
packages/**/dist/
Expand Down
207 changes: 127 additions & 80 deletions CHANGELOG.md

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions integration/action-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ test.describe("actions", () => {
`,

[`app/routes/${THROWS_REDIRECT}.jsx`]: js`
import { redirect } from "react-router";
import { Form } from "react-router";
import { redirect, Form } from "react-router";

export function action() {
throw redirect("/${REDIRECT_TARGET}")
Expand Down
2 changes: 1 addition & 1 deletion integration/blocking-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ test("handles synchronous proceeding correctly", async ({ page }) => {
`,
"app/routes/b.tsx": js`
import * as React from "react";
import { Form, useAction, useBlocker } from "react-router";
import { Form, useBlocker } from "react-router";
export default function Component() {
return (
<div>
Expand Down
6 changes: 1 addition & 5 deletions integration/client-data-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,6 @@ test.describe("Client Data", () => {
}),
"app/routes/parent.child.tsx": js`
import * as React from 'react';
import { json } from "react-router"
import { Await, useLoaderData } from "react-router"
export function loader() {
return {
Expand Down Expand Up @@ -685,7 +684,6 @@ test.describe("Client Data", () => {
}),
"app/routes/parent.child.tsx": js`
import * as React from 'react';
import { json } from "react-router";
import { useLoaderData, useRevalidator } from "react-router";
let isFirstCall = true;
export async function loader({ serverLoader }) {
Expand Down Expand Up @@ -763,7 +761,7 @@ test.describe("Client Data", () => {
childClientLoaderHydrate: false,
}),
"app/routes/parent.child.tsx": js`
import { ClientLoaderFunctionArgs, useRouteError } from "react-router";
import { useRouteError } from "react-router";

export function loader() {
throw new Error("Broken!")
Expand Down Expand Up @@ -1286,7 +1284,6 @@ test.describe("Client Data", () => {
}),
"app/routes/parent.child.tsx": js`
import * as React from 'react';
import { json } from "react-router";
import { Form, useRouteError } from "react-router";
export async function clientAction({ serverAction }) {
return await serverAction();
Expand Down Expand Up @@ -1508,7 +1505,6 @@ test.describe("Client Data", () => {
}),
"app/routes/parent.child.tsx": js`
import * as React from 'react';
import { json } from "react-router";
import { Form, useRouteError } from "react-router";
export async function clientAction({ serverAction }) {
return await serverAction();
Expand Down
1 change: 0 additions & 1 deletion integration/error-boundary-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -971,7 +971,6 @@ test("Allows back-button out of an error boundary after a hard reload", async ({
`,

"app/routes/boom.tsx": js`
import { json } from "react-router";
export function loader() { return boom(); }
export default function() { return <b>my page</b>; }
`,
Expand Down
1 change: 0 additions & 1 deletion integration/fetch-globals-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ test.beforeAll(async () => {
fixture = await createFixture({
files: {
"app/routes/_index.tsx": js`
import { json } from "react-router";
import { useLoaderData } from "react-router";
export async function loader() {
const resp = await fetch('https://reqres.in/api/users?page=2');
Expand Down
1 change: 0 additions & 1 deletion integration/fetcher-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ test.describe("useFetcher", () => {
fixture = await createFixture({
files: {
"app/routes/resource-route-action-only.ts": js`
import { json } from "react-router";
export function action() {
return new Response("${CHEESESTEAK}");
}
Expand Down
8 changes: 0 additions & 8 deletions integration/fs-routes-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,6 @@ test.describe("fs-routes", () => {
test.beforeAll(async () => {
fixture = await createFixture({
files: {
"vite.config.js": js`
import { defineConfig } from "vite";
import { reactRouter } from "@react-router/dev/vite";

export default defineConfig({
plugins: [reactRouter()],
});
`,
"app/routes.ts": js`
import { type RouteConfig } from "@react-router/dev/routes";
import { flatRoutes } from "@react-router/fs-routes";
Expand Down
8 changes: 6 additions & 2 deletions integration/helpers/create-fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
import { createRequestHandler as createExpressHandler } from "@react-router/express";
import { createReadableStreamFromReadable } from "@react-router/node";

import { viteConfig, reactRouterConfig } from "./vite.js";
import { type TemplateName, viteConfig, reactRouterConfig } from "./vite.js";

const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const root = path.join(__dirname, "../..");
Expand All @@ -31,6 +31,7 @@ export interface FixtureInit {
spaMode?: boolean;
prerender?: boolean;
port?: number;
templateName?: TemplateName;
}

export type Fixture = Awaited<ReturnType<typeof createFixture>>;
Expand Down Expand Up @@ -362,7 +363,7 @@ export async function createFixtureProject(
init: FixtureInit = {},
mode?: ServerMode
): Promise<string> {
let template = "vite-5-template";
let template = init.templateName ?? "vite-5-template";
let integrationTemplateDir = path.resolve(__dirname, template);
let projectName = `rr-${template}-${Math.random().toString(32).slice(2)}`;
let projectDir = path.join(TMP_DIR, projectName);
Expand Down Expand Up @@ -424,6 +425,9 @@ function build(projectDir: string, buildStdio?: Writable, mode?: ServerMode) {
env: {
...process.env,
NODE_ENV: mode || ServerMode.Production,
// Ensure build can pass in Rolldown. This can be removed once
// "preserveEntrySignatures" is supported in rolldown-vite.
ROLLDOWN_OPTIONS_VALIDATION: "loose",
},
});

Expand Down
6 changes: 6 additions & 0 deletions integration/helpers/vite-rolldown-template/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules

/.cache
/build
.env
.react-router
19 changes: 19 additions & 0 deletions integration/helpers/vite-rolldown-template/app/root.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "react-router";

export default function App() {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
</head>
<body>
<Outlet />
<ScrollRestoration />
<Scripts />
</body>
</html>
);
}
4 changes: 4 additions & 0 deletions integration/helpers/vite-rolldown-template/app/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { type RouteConfig } from "@react-router/dev/routes";
import { flatRoutes } from "@react-router/fs-routes";

export default flatRoutes() satisfies RouteConfig;
16 changes: 16 additions & 0 deletions integration/helpers/vite-rolldown-template/app/routes/_index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { MetaFunction } from "react-router";

export const meta: MetaFunction = () => {
return [
{ title: "New React Router App" },
{ name: "description", content: "Welcome to React Router!" },
];
};

export default function Index() {
return (
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.8" }}>
<h1>Welcome to React Router</h1>
</div>
);
}
2 changes: 2 additions & 0 deletions integration/helpers/vite-rolldown-template/env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/// <reference types="@react-router/node" />
/// <reference types="vite/client" />
45 changes: 45 additions & 0 deletions integration/helpers/vite-rolldown-template/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"name": "integration-vite-rolldown-template",
"version": "0.0.0",
"private": true,
"sideEffects": false,
"type": "module",
"scripts": {
"dev": "react-router dev",
"build": "cross-env ROLLDOWN_OPTIONS_VALIDATION=loose react-router build",
"start": "react-router-serve ./build/server/index.js",
"typecheck": "react-router typegen && tsc"
},
"dependencies": {
"@react-router/express": "workspace:*",
"@react-router/node": "workspace:*",
"@react-router/serve": "workspace:*",
"@vanilla-extract/css": "^1.10.0",
"@vanilla-extract/vite-plugin": "^3.9.2",
"express": "^4.19.2",
"isbot": "^5.1.11",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router": "workspace:*",
"serialize-javascript": "^6.0.1"
},
"devDependencies": {
"@react-router/dev": "workspace:*",
"@react-router/fs-routes": "workspace:*",
"@react-router/remix-routes-option-adapter": "workspace:*",
"@types/react": "^18.2.20",
"@types/react-dom": "^18.2.7",
"cross-env": "^7.0.3",
"eslint": "^8.38.0",
"typescript": "^5.1.6",
"vite": "npm:[email protected]",
"vite-env-only": "^3.0.1",
"vite-tsconfig-paths": "^4.2.1"
},
"overrides": {
"vite": "npm:[email protected]"
},
"engines": {
"node": ">=20.0.0"
}
}
Binary file not shown.
22 changes: 22 additions & 0 deletions integration/helpers/vite-rolldown-template/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"include": ["env.d.ts", "**/*.ts", "**/*.tsx", ".react-router/types/**/*"],
"compilerOptions": {
"lib": ["DOM", "DOM.Iterable", "ES2022"],
"verbatimModuleSyntax": true,
"esModuleInterop": true,
"jsx": "react-jsx",
"module": "ESNext",
"moduleResolution": "Bundler",
"resolveJsonModule": true,
"target": "ES2022",
"strict": true,
"allowJs": true,
"skipLibCheck": true,
"baseUrl": ".",
"paths": {
"~/*": ["./app/*"]
},
"noEmit": true,
"rootDirs": [".", ".react-router/types/"]
}
}
11 changes: 11 additions & 0 deletions integration/helpers/vite-rolldown-template/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { reactRouter } from "@react-router/dev/vite";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";

export default defineConfig({
plugins: [
// @ts-expect-error `dev` depends on Vite 6, Plugin type is mismatched.
reactRouter(),
tsconfigPaths(),
],
});
58 changes: 51 additions & 7 deletions integration/helpers/vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,29 @@ export const reactRouterConfig = ({
`;
};

type ViteConfigArgs = {
type ViteConfigServerArgs = {
port: number;
fsAllow?: string[];
};

type ViteConfigBuildArgs = {
assetsInlineLimit?: number;
assetsDir?: string;
};

type ViteConfigBaseArgs = {
envDir?: string;
};

type ViteConfigArgs = (
| ViteConfigServerArgs
| { [K in keyof ViteConfigServerArgs]?: never }
) &
ViteConfigBuildArgs &
ViteConfigBaseArgs;

export const viteConfig = {
server: async (args: ViteConfigArgs) => {
server: async (args: ViteConfigServerArgs) => {
let { port, fsAllow } = args;
let hmrPort = await getPort();
let text = dedent`
Expand All @@ -81,21 +96,42 @@ export const viteConfig = {
`;
return text;
},
build: ({ assetsInlineLimit, assetsDir }: ViteConfigBuildArgs = {}) => {
return dedent`
build: {
// Detect rolldown-vite. This should ideally use "rolldownVersion"
// but that's not exported. Once that's available, this
// check should be updated to use it.
rollupOptions: "transformWithOxc" in (await import("vite"))
? {
onwarn(warning, warn) {
// Ignore "The built-in minifier is still under development." warning
if (warning.code === "MINIFY_WARNING") return;
warn(warning);
},
}
: undefined,
assetsInlineLimit: ${assetsInlineLimit ?? "undefined"},
assetsDir: ${assetsDir ? `"${assetsDir}"` : "undefined"},
},
`;
},
basic: async (args: ViteConfigArgs) => {
return dedent`
import { reactRouter } from "@react-router/dev/vite";
import { envOnlyMacros } from "vite-env-only";
import tsconfigPaths from "vite-tsconfig-paths";

export default {
${await viteConfig.server(args)}
export default async () => ({
${args.port ? await viteConfig.server(args) : ""}
${viteConfig.build(args)}
envDir: ${args.envDir ? `"${args.envDir}"` : "undefined"},
plugins: [
reactRouter(),
envOnlyMacros(),
tsconfigPaths()
],
};
});
`;
},
};
Expand Down Expand Up @@ -145,14 +181,19 @@ export const EXPRESS_SERVER = (args: {
`;

export type TemplateName =
| "cloudflare-dev-proxy-template"
| "vite-5-template"
| "vite-6-template"
| "cloudflare-dev-proxy-template"
| "vite-plugin-cloudflare-template";
| "vite-plugin-cloudflare-template"
| "vite-rolldown-template";

export const viteMajorTemplates = [
{ templateName: "vite-5-template", templateDisplayName: "Vite 5" },
{ templateName: "vite-6-template", templateDisplayName: "Vite 6" },
{
templateName: "vite-rolldown-template",
templateDisplayName: "Vite Rolldown",
},
] as const satisfies Array<{
templateName: TemplateName;
templateDisplayName: string;
Expand Down Expand Up @@ -205,6 +246,9 @@ export const build = ({
...process.env,
...colorEnv,
...env,
// Ensure build can pass in Rolldown. This can be removed once
// "preserveEntrySignatures" is supported in rolldown-vite.
ROLLDOWN_OPTIONS_VALIDATION: "loose",
},
});
};
Expand Down
3 changes: 1 addition & 2 deletions integration/link-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,7 @@ test.describe("route module link export", () => {
`,

"app/routes/gists.$username.tsx": js`
import { data, redirect } from "react-router";
import { Link, useLoaderData, useParams } from "react-router";
import { data, redirect, Link, useLoaderData, useParams } from "react-router";
export async function loader({ params }) {
let { username } = params;
if (username === "mjijackson") {
Expand Down
Loading