Skip to content

Commit d07cefe

Browse files
Add lazy route property API, use for loading middleware (#13294)
1 parent beb43fc commit d07cefe

File tree

8 files changed

+2377
-532
lines changed

8 files changed

+2377
-532
lines changed

.changeset/spicy-lamps-look.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
"react-router": minor
3+
---
4+
5+
Add granular object-based API for `route.lazy` to support lazy loading of individual route properties, for example:
6+
7+
```ts
8+
createBrowserRouter([
9+
{
10+
path: "/show/:showId",
11+
lazy: {
12+
loader: async () => (await import("./show.loader.js")).loader,
13+
action: async () => (await import("./show.action.js")).action,
14+
Component: async () => (await import("./show.component.js")).Component,
15+
},
16+
},
17+
]);
18+
```
19+
20+
**Breaking change for `route.unstable_lazyMiddleware` consumers**
21+
22+
The `route.unstable_lazyMiddleware` property is no longer supported. If you want to lazily load middleware, you must use the new object-based `route.lazy` API with `route.lazy.unstable_middleware`, for example:
23+
24+
```ts
25+
createBrowserRouter([
26+
{
27+
path: "/show/:showId",
28+
lazy: {
29+
unstable_middleware: async () =>
30+
(await import("./show.middleware.js")).middleware,
31+
// etc.
32+
},
33+
},
34+
]);
35+
```

docs/start/data/custom.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,13 @@ Routes can take most of their definition lazily with the `lazy` property.
6464
createBrowserRouter([
6565
{
6666
path: "/show/:showId",
67-
lazy: () => {
68-
let [loader, action, Component] = await Promise.all([
69-
import("./show.action.js"),
70-
import("./show.loader.js"),
71-
import("./show.component.js"),
72-
]);
73-
return { loader, action, Component };
67+
lazy: {
68+
loader: async () =>
69+
(await import("./show.loader.js")).loader,
70+
action: async () =>
71+
(await import("./show.action.js")).action,
72+
Component: async () =>
73+
(await import("./show.component.js")).Component,
7474
},
7575
},
7676
]);

packages/react-router/__tests__/router/context-middleware-test.ts

Lines changed: 91 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -562,26 +562,30 @@ describe("context/middleware", () => {
562562
{
563563
id: "parent",
564564
path: "/parent",
565-
unstable_lazyMiddleware: async () => [
566-
async ({ context }, next) => {
567-
await next();
568-
// Grab a snapshot at the end of the upwards middleware chain
569-
snapshot = context.get(orderContext);
570-
},
571-
getOrderMiddleware(orderContext, "a"),
572-
getOrderMiddleware(orderContext, "b"),
573-
],
565+
lazy: {
566+
unstable_middleware: async () => [
567+
async ({ context }, next) => {
568+
await next();
569+
// Grab a snapshot at the end of the upwards middleware chain
570+
snapshot = context.get(orderContext);
571+
},
572+
getOrderMiddleware(orderContext, "a"),
573+
getOrderMiddleware(orderContext, "b"),
574+
],
575+
},
574576
loader({ context }) {
575577
context.get(orderContext).push("parent loader");
576578
},
577579
children: [
578580
{
579581
id: "child",
580582
path: "child",
581-
unstable_lazyMiddleware: async () => [
582-
getOrderMiddleware(orderContext, "c"),
583-
getOrderMiddleware(orderContext, "d"),
584-
],
583+
lazy: {
584+
unstable_middleware: async () => [
585+
getOrderMiddleware(orderContext, "c"),
586+
getOrderMiddleware(orderContext, "d"),
587+
],
588+
},
585589
loader({ context }) {
586590
context.get(orderContext).push("child loader");
587591
},
@@ -634,10 +638,12 @@ describe("context/middleware", () => {
634638
{
635639
id: "child",
636640
path: "child",
637-
unstable_lazyMiddleware: async () => [
638-
getOrderMiddleware(orderContext, "c"),
639-
getOrderMiddleware(orderContext, "d"),
640-
],
641+
lazy: {
642+
unstable_middleware: async () => [
643+
getOrderMiddleware(orderContext, "c"),
644+
getOrderMiddleware(orderContext, "d"),
645+
],
646+
},
641647
loader({ context }) {
642648
context.get(orderContext).push("child loader");
643649
},
@@ -663,7 +669,7 @@ describe("context/middleware", () => {
663669
]);
664670
});
665671

666-
it("ignores middleware returned from route.lazy", async () => {
672+
it("ignores middleware returned from route.lazy function", async () => {
667673
let snapshot;
668674

669675
let consoleWarn = jest
@@ -679,15 +685,17 @@ describe("context/middleware", () => {
679685
{
680686
id: "parent",
681687
path: "/parent",
682-
unstable_lazyMiddleware: async () => [
683-
async ({ context }, next) => {
684-
await next();
685-
// Grab a snapshot at the end of the upwards middleware chain
686-
snapshot = context.get(orderContext);
687-
},
688-
getOrderMiddleware(orderContext, "a"),
689-
getOrderMiddleware(orderContext, "b"),
690-
],
688+
lazy: {
689+
unstable_middleware: async () => [
690+
async ({ context }, next) => {
691+
await next();
692+
// Grab a snapshot at the end of the upwards middleware chain
693+
snapshot = context.get(orderContext);
694+
},
695+
getOrderMiddleware(orderContext, "a"),
696+
getOrderMiddleware(orderContext, "b"),
697+
],
698+
},
691699
loader({ context }) {
692700
context.get(orderContext).push("parent loader");
693701
},
@@ -726,70 +734,6 @@ describe("context/middleware", () => {
726734
"Route property unstable_middleware is not a supported property to be returned from a lazy route function. This property will be ignored."
727735
);
728736
});
729-
730-
it("ignores lazy middleware returned from route.lazy", async () => {
731-
let snapshot;
732-
733-
let consoleWarn = jest
734-
.spyOn(console, "warn")
735-
.mockImplementation(() => {});
736-
737-
router = createRouter({
738-
history: createMemoryHistory(),
739-
routes: [
740-
{
741-
path: "/",
742-
},
743-
{
744-
id: "parent",
745-
path: "/parent",
746-
unstable_lazyMiddleware: async () => [
747-
async ({ context }, next) => {
748-
await next();
749-
// Grab a snapshot at the end of the upwards middleware chain
750-
snapshot = context.get(orderContext);
751-
},
752-
getOrderMiddleware(orderContext, "a"),
753-
getOrderMiddleware(orderContext, "b"),
754-
],
755-
loader({ context }) {
756-
context.get(orderContext).push("parent loader");
757-
},
758-
children: [
759-
{
760-
id: "child",
761-
path: "child",
762-
// @ts-expect-error
763-
lazy: async () => ({
764-
unstable_lazyMiddleware: async () => [
765-
getOrderMiddleware(orderContext, "c"),
766-
getOrderMiddleware(orderContext, "d"),
767-
],
768-
}),
769-
loader({ context }) {
770-
context.get(orderContext).push("child loader");
771-
},
772-
},
773-
],
774-
},
775-
],
776-
});
777-
778-
await router.navigate("/parent/child");
779-
780-
expect(snapshot).toEqual([
781-
"a middleware - before next()",
782-
"b middleware - before next()",
783-
"parent loader",
784-
"child loader",
785-
"b middleware - after next()",
786-
"a middleware - after next()",
787-
]);
788-
789-
expect(consoleWarn).toHaveBeenCalledWith(
790-
"Route property unstable_lazyMiddleware is not a supported property to be returned from a lazy route function. This property will be ignored."
791-
);
792-
});
793737
});
794738

795739
describe("throwing", () => {
@@ -1581,37 +1525,41 @@ describe("context/middleware", () => {
15811525
{
15821526
id: "parent",
15831527
path: "/parent",
1584-
unstable_lazyMiddleware: async () => [
1585-
async (_, next) => {
1586-
let res = (await next()) as Response;
1587-
res.headers.set("parent1", "yes");
1588-
return res;
1589-
},
1590-
async (_, next) => {
1591-
let res = (await next()) as Response;
1592-
res.headers.set("parent2", "yes");
1593-
return res;
1594-
},
1595-
],
1528+
lazy: {
1529+
unstable_middleware: async () => [
1530+
async (_, next) => {
1531+
let res = (await next()) as Response;
1532+
res.headers.set("parent1", "yes");
1533+
return res;
1534+
},
1535+
async (_, next) => {
1536+
let res = (await next()) as Response;
1537+
res.headers.set("parent2", "yes");
1538+
return res;
1539+
},
1540+
],
1541+
},
15961542
loader() {
15971543
return "PARENT";
15981544
},
15991545
children: [
16001546
{
16011547
id: "child",
16021548
path: "child",
1603-
unstable_lazyMiddleware: async () => [
1604-
async (_, next) => {
1605-
let res = (await next()) as Response;
1606-
res.headers.set("child1", "yes");
1607-
return res;
1608-
},
1609-
async (_, next) => {
1610-
let res = (await next()) as Response;
1611-
res.headers.set("child2", "yes");
1612-
return res;
1613-
},
1614-
],
1549+
lazy: {
1550+
unstable_middleware: async () => [
1551+
async (_, next) => {
1552+
let res = (await next()) as Response;
1553+
res.headers.set("child1", "yes");
1554+
return res;
1555+
},
1556+
async (_, next) => {
1557+
let res = (await next()) as Response;
1558+
res.headers.set("child2", "yes");
1559+
return res;
1560+
},
1561+
],
1562+
},
16151563
loader() {
16161564
return "CHILD";
16171565
},
@@ -2507,37 +2455,41 @@ describe("context/middleware", () => {
25072455
{
25082456
id: "parent",
25092457
path: "/parent",
2510-
unstable_lazyMiddleware: async () => [
2511-
async ({ context }, next) => {
2512-
let res = (await next()) as Response;
2513-
res.headers.set("parent1", "yes");
2514-
return res;
2515-
},
2516-
async ({ context }, next) => {
2517-
let res = (await next()) as Response;
2518-
res.headers.set("parent2", "yes");
2519-
return res;
2520-
},
2521-
],
2458+
lazy: {
2459+
unstable_middleware: async () => [
2460+
async ({ context }, next) => {
2461+
let res = (await next()) as Response;
2462+
res.headers.set("parent1", "yes");
2463+
return res;
2464+
},
2465+
async ({ context }, next) => {
2466+
let res = (await next()) as Response;
2467+
res.headers.set("parent2", "yes");
2468+
return res;
2469+
},
2470+
],
2471+
},
25222472
loader() {
25232473
return new Response("PARENT");
25242474
},
25252475
children: [
25262476
{
25272477
id: "child",
25282478
path: "child",
2529-
unstable_lazyMiddleware: async () => [
2530-
async ({ context }, next) => {
2531-
let res = (await next()) as Response;
2532-
res.headers.set("child1", "yes");
2533-
return res;
2534-
},
2535-
async ({ context }, next) => {
2536-
let res = (await next()) as Response;
2537-
res.headers.set("child2", "yes");
2538-
return res;
2539-
},
2540-
],
2479+
lazy: {
2480+
unstable_middleware: async () => [
2481+
async ({ context }, next) => {
2482+
let res = (await next()) as Response;
2483+
res.headers.set("child1", "yes");
2484+
return res;
2485+
},
2486+
async ({ context }, next) => {
2487+
let res = (await next()) as Response;
2488+
res.headers.set("child2", "yes");
2489+
return res;
2490+
},
2491+
],
2492+
},
25412493
loader({ context }) {
25422494
return new Response("CHILD");
25432495
},

0 commit comments

Comments
 (0)