@@ -637,15 +637,46 @@ const posts = import.meta.glob("./posts/*.mdx", {
637637#### Strict route exports
638638
639639With Vite, Remix gets stricter about which exports are allowed from your route modules.
640- Previously, the Remix compiler would allow any export from routes.
641- While this was convenient, it was also a common source of bugs that were hard to track down because they only surfaced at runtime.
642640
643- 👉 ** Move any non-route exports to a separate file**
641+ Previously, Remix allowed user-defined exports from routes.
642+ The Remix compiler would then rely on treeshaking to remove any code only intended for use on the server from the client bundle.
644643
645- For example, with take this route:
644+ In contrast, Vite processes each module in isolation during development, so cross-module treeshaking is not possible.
645+ You should already be separating server-only code into ` .server ` files or directories, so treeshaking isn't needed for those modules.
646+ But routes are a special case since they intentionally blend client and server code.
647+ Remix knows that exports like ` loader ` , ` action ` , ` headers ` , etc. are server-only, so it can safely remove them from the client bundle.
648+ But there's no way to know when looking at a single route module in isolation whether user-defined exports are server-only.
649+ That's why Remix's Vite plugin is stricter about which exports are allowed from your route modules.
650+
651+ In fact, we'd rather not rely on treeshaking for correctness at all.
652+ If tomorrow you or your coworker accidentally imports something you _ thought_ was client safe,
653+ treeshaking will no longer exclude that from your client bundle and you might end up with server code in your app!
654+ Treeshaking is designed as a pure optimization, so relying on it for correctness is brittle.
655+ In short, Vite made us eat our veggies, but turns out they were delicious all along!
656+
657+ So instead of treeshaking, its better to be explicit about what code is server-only.
658+ For route modules, that means only exporting Remix route exports.
659+ For anything else, put it in a separate module and use a ` .server ` file or directory when needed.
660+
661+ Ultimately, Route exports are Remix API.
662+ Think of a Remix route module like a function and the exports like named arguments to the function.
663+
664+ ``` ts
665+ // Not real API, just a mental model
666+ let route = createRoute ({ loader , mySuperCoolThing });
667+ // ^^^^^^^^^^^^^^^^
668+ // Object literal may only specify known properties, and 'mySuperCoolThing' does not exist in type 'RemixRoute'
669+ ```
670+
671+ Just like how you shouldn't pass unexpected named arguments to a function, you shouldn't create unexpected exports from a route module.
672+ The result is that Remix is simpler and more predictable.
673+
674+ 👉 ** Move any user-defined route exports to a separate module**
675+
676+ For example, here's a route with a user-defined export called ` mySuperCoolThing ` :
646677
647678``` ts filename=app/routes/super-cool.tsx
648- // ❌ This is the problematic export
679+ // ❌ This isn't a Remix-specific route export, just something I made up
649680export const mySuperCoolThing =
650681 " Some value I wanted to colocate with my route!" ;
651682
@@ -656,7 +687,8 @@ export const loader = () => {};
656687export default function SuperCool() {}
657688```
658689
659- Using the default route convention in v2, you can refactor to:
690+ One option is to colocate your route and related utilities in the same directory if your routing convention allows it.
691+ For example, with the default route convention in v2:
660692
661693``` ts filename=app/routes/super-cool/route.tsx
662694export const loader = () => {};
@@ -665,12 +697,11 @@ export default function SuperCool() {}
665697```
666698
667699``` ts filename=app/routes/super-cool/utils.ts
700+ // If this was server-only code, I'd rename this file to "utils.server.ts"
668701export const mySuperCoolThing =
669702 " Some value I wanted to colocate with my route!" ;
670703```
671704
672- That way your utilities are still colocated with your route, but in a separate module.
673-
674705## Troubleshooting
675706
676707Check out the [ known issues with the Remix Vite plugin on GitHub] [ issues-vite ] before filing a new bug report!
0 commit comments