Skip to content
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

fix(remix-dev): allow defining multiple routes for the same route module file #3970

Merged
merged 13 commits into from Dec 1, 2022
1 change: 1 addition & 0 deletions contributors.yml
Expand Up @@ -236,6 +236,7 @@
- lpsinger
- lswest
- lucasdibz
- lucasferreira
- luispagarcia
- luistak
- luistorres
Expand Down
10 changes: 10 additions & 0 deletions packages/remix-dev/__tests__/defineRoutes-test.ts
Expand Up @@ -87,4 +87,14 @@ describe("defineRoutes", () => {
}
`);
});

it("allows multiple routes with the same route module", () => {
let routes = defineRoutes((route) => {
route("/user/:id", "routes/index.tsx", { id: "user-by-id" });
route("/user", "routes/index.tsx", { id: "user" });
route("/other", "routes/other-route.tsx");
});

expect(Object.entries(routes)).toHaveLength(3);
});
});
44 changes: 26 additions & 18 deletions packages/remix-dev/compiler/assets.ts
Expand Up @@ -56,10 +56,13 @@ export async function createAssetsManifest(
config.appDirectory,
config.entryClientFile
);
let routesByFile: Map<string, Route> = Object.keys(config.routes).reduce(
let routesByFile: Map<string, Route[]> = Object.keys(config.routes).reduce(
(map, key) => {
let route = config.routes[key];
map.set(route.file, route);
map.set(
route.file,
map.has(route.file) ? [...map.get(route.file), route] : [route]
);
brophdawg11 marked this conversation as resolved.
Show resolved Hide resolved
return map;
},
new Map()
Expand All @@ -85,22 +88,27 @@ export async function createAssetsManifest(
/(^browser-route-module:|\?browser$)/g,
""
);
let route = routesByFile.get(entryPointFile);
invariant(route, `Cannot get route for entry point ${output.entryPoint}`);
let sourceExports = await getRouteModuleExportsCached(config, route.id);
routes[route.id] = {
id: route.id,
parentId: route.parentId,
path: route.path,
index: route.index,
caseSensitive: route.caseSensitive,
module: resolveUrl(key),
imports: resolveImports(output.imports),
hasAction: sourceExports.includes("action"),
hasLoader: sourceExports.includes("loader"),
hasCatchBoundary: sourceExports.includes("CatchBoundary"),
hasErrorBoundary: sourceExports.includes("ErrorBoundary"),
};
let groupedRoute = routesByFile.get(entryPointFile);
invariant(
groupedRoute,
`Cannot get route(s) for entry point ${output.entryPoint}`
);
for (let route of groupedRoute) {
let sourceExports = await getRouteModuleExportsCached(config, route.id);
routes[route.id] = {
brophdawg11 marked this conversation as resolved.
Show resolved Hide resolved
id: route.id,
parentId: route.parentId,
path: route.path,
index: route.index,
caseSensitive: route.caseSensitive,
module: resolveUrl(key),
imports: resolveImports(output.imports),
hasAction: sourceExports.includes("action"),
hasLoader: sourceExports.includes("loader"),
hasCatchBoundary: sourceExports.includes("CatchBoundary"),
hasErrorBoundary: sourceExports.includes("ErrorBoundary"),
};
}
}
}

Expand Down
11 changes: 10 additions & 1 deletion packages/remix-dev/config/routes.ts
Expand Up @@ -54,6 +54,13 @@ export interface DefineRouteOptions {
* Should be `true` if this is an index route that does not allow child routes.
*/
index?: boolean;

/**
* An optional unique id string for this route, that will be appended to the file
* name e.g: `<file-name>--<id>`. Use this if you need to aggregate two or more
* routes with the same route file.
*/
id?: string;
brophdawg11 marked this conversation as resolved.
Show resolved Hide resolved
brophdawg11 marked this conversation as resolved.
Show resolved Hide resolved
}

interface DefineRouteChildren {
Expand Down Expand Up @@ -137,11 +144,13 @@ export function defineRoutes(
options = optionsOrChildren || {};
}

let fileId = createRouteId(file);

let route: ConfigRoute = {
path: path ? path : undefined,
index: options.index ? true : undefined,
caseSensitive: options.caseSensitive ? true : undefined,
id: createRouteId(file),
id: options.id ? `${fileId}--${options.id}` : fileId,
Copy link
Contributor

Choose a reason for hiding this comment

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

what is the best way to "verbatim and error if they provide duplicates" just throws a new Error inside routes.ts file?

Maybe just change this to

Suggested change
id: options.id ? `${fileId}--${options.id}` : fileId,
id: options.id || createRouteId(file),

And delete line 147 above

parentId:
parentRoutes.length > 0
? parentRoutes[parentRoutes.length - 1].id
Expand Down