Allow specifying arbitrary modules in routes.ts
#13747
Replies: 1 comment
-
I like the proposal btw, I have always wanted to have a way to load routes from a package so we could build something like Rails Engines where you can install a package and that can give you a full app to integrate into your app, imagine I'm not sure what should a package exports based on this proposal. export default [
index('routes/home.tsx'),
route('login', module('@mycompany/shared-routes/login')),
] satisfies RouteConfig;
I understand this point to a route module that's exported by a package.
But from this I understand that the package exports something similar to I think being able to import a Some other questions about this:
Should this happen at the app level or the package level I export something like
If it only supports referencing routes manually it would be possible like this: export default [
index('routes/home.tsx'),
route('login', module('@mycompany/shared-routes/login'), [
// more route from my package
]),
] satisfies RouteConfig; But a package exports a RouteConfig, should there be a way? Or should package allow both ways? I imagine something like this for pre-defined route configs: import adminRoutes from "react-router-admin";
export default [
index("routes/home.tsx"),
...adminRoutes
] satisfies RouteConfig; Or if you want to define them manually: export default [
index("routes/home.tsx"),
route("admin", module("react-router-admin/layout"), [
route("users", module("react-router-admin/entity"), { id: "admin/users" }),
route("articles", module("react-router-admin/entity"), { id: "admin/articles" }),
route("settings", "routes/admin/settings.tsx") // custom route inside package layout
])
] satisfies RouteConfig; |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Sharing common "base" framework configuration across multiple apps is hard.
Sharing common route configurations across multiple apps is also hard/tedious.
Let's make it better!
TL;DR: It's my belief that allowing for arbitrary module specifiers (ie: anything that can be passed to
import()
or be resolved via the bundler) inroutes.ts
, in addition to file-system paths, can open up a world of compositional and collaborative possibilities!Currently, React Router framework mode is focused on files, has the following contstraints:
{appDir}/root.tsx
- special file for theroot
route{appDir}/entry.server.tsx
- (optional1) special file for the server entry{appDir}/entry.client.tsx
- (optional1) special file for the client entryroutes.ts
must reference paths on the file systemThis works for most cases, but tends to breaks down in certain scenarios:
that must run on the same set of utilities/configuration, such as enterprise environments that have standardized
things like authentication / observability / caching / db access / etc.
These things are technically possible to do today with things like
unstable_middleware
, or more complex build-time solutionssuch as @jrestall's work here.
However, I feel they could be made much better. To explain how, first let's look at how you have to do this currently.
Sharing common framework configuration today
My current solution looks like this. These files are copy/pasted across multiple applications without changes:
(Shared config files)
app/routes.ts
react-router.config.ts
app/root.tsx
app/entry.client.ts
app/entry.server.ts
Also, I have a set of routes that are installed in
express
that handle things like OAuth/OIDC andsimilar cross cutting concerns.
IMO, copy/paste-ing this kind of config is
How to make it better
I think that changing one constraint of the routing system would allow for solving most of these pain points:
As a quick strawman, I'm proposing something like this:
Important
Why
module('...')
instead of something likeimport('...')
orimport * as login from '...'
?Because we don't want to actually import this thing when
routes.ts
is executed. We're providinga specifier to the framework compiler and it needs to know that this is going to be handled differently from
a file-system path when the app is built.
At the risk of Not Knowing What The Heck I'm Talking About™, I believe that enabling this pattern could solve most of the issues I outlined above: Collections of routes could be built and published on package registries (npmjs.com / jsr.io / Artifactory / GH Packages / etc) and simply export a set of
RouteConfigEntry[]
that reference module specifiers instead of file system paths.The plumbing for resolving a route entry to a module instead of a file system path could also be re-used to implement customizing where the
root
route and the client/server entry modules are located. They could be supplied by an installed package instead of having to live in the applications 'appFolder'.This could be implemented with named exports from
react-router.config.ts
:Unanswered questions:
react-router typegen
process. I don't think it would be too problematic, as (in my mind) we're merely adding an additional way to find a route module's contents. If thetypegen
step relies on typescript source code, there may be some modifications necessary to load those types from published*.d.ts
definitions instead of raw*.ts
source code.Beta Was this translation helpful? Give feedback.
All reactions