Skip to content

Commit 17bdd98

Browse files
authored
Ensure ancestor pathless/index routes are loaded via manifest requests (#10535)
1 parent 37cbdd1 commit 17bdd98

File tree

3 files changed

+106
-1
lines changed

3 files changed

+106
-1
lines changed

.changeset/eleven-oranges-lie.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@remix-run/server-runtime": patch
3+
---
4+
5+
Load ancestor pathless/index routes in lazy route discovery for upwards non-eager-discoery routing

integration/fog-of-war-test.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1510,4 +1510,83 @@ test.describe("Fog of War", () => {
15101510
)
15111511
).toEqual(["root", "routes/a", "routes/_index", "routes/a.b"]);
15121512
});
1513+
1514+
test("loads ancestor index routes on navigations", async ({ page }) => {
1515+
let fixture = await createFixture({
1516+
config: {
1517+
future: {
1518+
v3_lazyRouteDiscovery: true,
1519+
},
1520+
},
1521+
files: {
1522+
...getFiles(),
1523+
"app/root.tsx": js`
1524+
import * as React from "react";
1525+
import { Link, Links, Meta, Outlet, Scripts } from "@remix-run/react";
1526+
export default function Root() {
1527+
let [showLink, setShowLink] = React.useState(false);
1528+
return (
1529+
<html lang="en">
1530+
<head>
1531+
<Meta />
1532+
<Links />
1533+
</head>
1534+
<body>
1535+
<Link to="/" discover="none">Home</Link><br/>
1536+
<Link to="/a" discover="none">/a</Link><br/>
1537+
<Link to="/a/b" discover="none">/a/b</Link><br/>
1538+
<Link to="/a/b/c" discover="none">/a/b/c</Link><br/>
1539+
<Outlet />
1540+
<Scripts />
1541+
</body>
1542+
</html>
1543+
);
1544+
}
1545+
`,
1546+
"app/routes/a._index.tsx": js`
1547+
export default function Index() {
1548+
return <h3 id="a-index">A INDEX</h3>;
1549+
}
1550+
`,
1551+
"app/routes/a.b._index.tsx": js`
1552+
export default function Index() {
1553+
return <h3 id="b-index">B INDEX</h3>;
1554+
}
1555+
`,
1556+
},
1557+
});
1558+
let appFixture = await createAppFixture(fixture);
1559+
let app = new PlaywrightFixture(appFixture, page);
1560+
1561+
await app.goto("/", true);
1562+
expect(
1563+
await page.evaluate(() =>
1564+
Object.keys((window as any).__remixManifest.routes)
1565+
)
1566+
).toEqual(["root", "routes/_index"]);
1567+
1568+
await app.clickLink("/a/b/c");
1569+
await page.waitForSelector("#c");
1570+
1571+
// /a/b is not discovered yet even thought it's rendered
1572+
expect(
1573+
await page.evaluate(() =>
1574+
Object.keys((window as any).__remixManifest.routes)
1575+
)
1576+
).toEqual([
1577+
"root",
1578+
"routes/_index",
1579+
"routes/a",
1580+
"routes/a._index",
1581+
"routes/a.b",
1582+
"routes/a.b._index",
1583+
"routes/a.b.c",
1584+
]);
1585+
1586+
await app.clickLink("/a/b");
1587+
await page.waitForSelector("#b-index");
1588+
1589+
await app.clickLink("/a");
1590+
await page.waitForSelector("#a-index");
1591+
});
15131592
});

packages/remix-server-runtime/server.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,28 @@ async function handleManifestRequest(
310310
let patches: Record<string, EntryRoute> = {};
311311

312312
if (url.searchParams.has("p")) {
313-
for (let path of url.searchParams.getAll("p")) {
313+
let paths = new Set<string>();
314+
315+
// In addition to responding with the patches for the requested paths, we
316+
// need to include patches for each partial path so that we pick up any
317+
// pathless/index routes below ancestor segments. So if we
318+
// get a request for `/parent/child`, we need to look for a match on `/parent`
319+
// so that if a `parent._index` route exists we return it so it's available
320+
// for client side matching if the user routes back up to `/parent`.
321+
// This is the same thing we do on initial load in <Scripts> via
322+
// `getPartialManifest()`
323+
url.searchParams.getAll("p").forEach((path) => {
324+
if (!path.startsWith("/")) {
325+
path = `/${path}`;
326+
}
327+
let segments = path.split("/").slice(1);
328+
segments.forEach((_, i) => {
329+
let partialPath = segments.slice(0, i + 1).join("/");
330+
paths.add(`/${partialPath}`);
331+
});
332+
});
333+
334+
for (let path of paths) {
314335
let matches = matchServerRoutes(routes, path, build.basename);
315336
if (matches) {
316337
for (let match of matches) {

0 commit comments

Comments
 (0)