remix: Dev server HMR and *.server.ts naming convention doesn't work with monorepos using shared routes
What version of Remix are you using?
v1.18
Are all your remix dependencies & dev-dependencies using the same version?
- Yes
Steps to Reproduce
Minimal Reproduction: https://github.com/jrestall/remix-nx-monorepo/
- Create a monorepo using Nx or Turborepo such as Logan’s example at https://github.com/mcansh/remix-shared-routes/ that has shared route packages outside the app directory.
- Setup the new dev server.
- Modify files outside the main app directory and note HMR doesn’t work.
- Add files outside the main app directory that are used by shared routes that follow the *.server.ts pattern and note they don’t get replaced with an empty module.
Expected Behavior
HMR and *.server.ts naming convention works with code outside the app dir that uses shared routes.
Actual Behavior
Following are the areas of code that limit HMR and *.server conventions to only work with routes in the app dir. I’m happy to submit a PR to fix this if a better approach can be agreed.
HMR
https://github.com/remix-run/remix/blob/40a4d7d5e25eb5edc9a622278ab111d881c7c155/packages/remix-dev/compiler/js/plugins/hmr.ts#L134-L136 If the goal here is to not add react refresh to node_modules code, could we perhaps explicitly check whether the file is in node_modules instead?
Naming Convention
https://github.com/remix-run/remix/blob/40a4d7d5e25eb5edc9a622278ab111d881c7c155/packages/remix-dev/compiler/plugins/emptyModules.ts#L24-L28 Instead of limiting this convention to the app dir, if the goal is to exclude node_modules, could we change it to something like the following?
!args.path.includes("node_modules")
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 2
- Comments: 16 (9 by maintainers)
Thanks, this is the key. If the route files are shared outside the app dir then HMR and naming conventions don’t work.
I’ve created a minimal reproduction repo at https://github.com/jrestall/remix-nx-monorepo/ which shows the issue is with sharing routes that exist outside the app dir. Editing a shared route file or any file referenced by the shared route will not work with HMR or *.server.ts conventions.
I’m using mostly the same approach to share routes between many apps as Logan does here except using the flat routes package as configured here. Moving routes to each of our apps isn’t an option as it would duplicate 100’s of file-based routing configs that would get out of sync, even if the route module’s implementation was shared.
Closing as completed by #8795 🎉
The Vite plugin now has very good monorepo support, can load routes from anywhere in the workspace and doesn’t require any patches, the presets functionality is especially useful for configuring multiple apps without duplicating config. The *.server.ts naming convention also works well in the monorepo.
Talked with @pcattori about this. There are two concepts here that we need to be able to tell the compiler:
a. what to watch for changes for HMR b. to apply some of our file conventions (
*.{server|client}.ts) to sources outside ofappDirectoryFor (a) we already have
watchPaths.For (b) we have
appDirectorybut it is limited to a single directory and applies other file conventions likeroot,entry.server, etc.I’m thinking we rename
watchPathstosourcePathsand then do both (a) and (b) with those directories.We also discussed that this is something we can add after v2 ships.
Thoughts?
We are using presets to avoid duplicating the way shared library routes are defined. Each monorepo app can reference shared functionality which can contain remix routes, so we use Nx (createGlobPatternsForDependencies) to get the route folders for each of the app’s workspace dependencies and then remix-flat-routes to define them since it supports multiple route folders. Not all libraries are shared but we also structure the repo in this way to enforce separation between features as the banking domain is very large, so this enables us to scale the Remix site to very many teams and features whilst enforcing modularity.
The preset is written in JS rather than TypeScript due to https://github.com/vitejs/vite/issues/5370.
This issue seems to be almost fixed if using the vite plugin, there’s just one bit of code that incorrectly assumes routes are always under the app directory.
https://github.com/remix-run/remix/blob/c82125332a63eeb374798814e0096013c0ea3eb8/packages/remix-dev/vite/plugin.ts#L1300
@markdalgleish @pcattori
I can already see me running into this, so yeah, fixing this would make future me very happy 😃
Thanks so much @kiliman! Your work on remix-flat-routes made the modular monorepo architecture possible with how flexible your package is. Your support for basePath was also really useful.
Appreciate the tips, we definitely plan to move to
basenamebut it’ll take a while as there’s a lot of custom code to rollback that handled redirects and links under a base path. Nice catch on the ignoredRouteFiles thanks, the comment should just mention dot files rather than all files so I’ll remove that config now that https://github.com/remix-run/remix/pull/8801 is in.😍 I knew that feature would come in handy
Also, since Remix now supports
basenamedirectly, you probably want to use that instead of thebasePathoption since this only adds the prefix to all top-level routes.One more thing. Your
ignoredRouteFilesconfig should be[**/*]. You’re currently only ignoring dot files.@jrestall Oh, that’s cool you’re using the presets feature too! Out of interest, do you mind sharing your preset? I’d love to see it!
Same problem preventing code move to mono repro packages. Seems common isecase can we please have a fix for this asap?🙏
HMR is working fine for me with NX monorepo
I had the same problem