diff --git a/docs/future/vite.md b/docs/future/vite.md index ad0651553d8..79d468bd5b4 100644 --- a/docs/future/vite.md +++ b/docs/future/vite.md @@ -637,15 +637,46 @@ const posts = import.meta.glob("./posts/*.mdx", { #### Strict route exports With Vite, Remix gets stricter about which exports are allowed from your route modules. -Previously, the Remix compiler would allow any export from routes. -While this was convenient, it was also a common source of bugs that were hard to track down because they only surfaced at runtime. -👉 **Move any non-route exports to a separate file** +Previously, Remix allowed user-defined exports from routes. +The Remix compiler would then rely on treeshaking to remove any code only intended for use on the server from the client bundle. -For example, with take this route: +In contrast, Vite processes each module in isolation during development, so cross-module treeshaking is not possible. +You should already be separating server-only code into `.server` files or directories, so treeshaking isn't needed for those modules. +But routes are a special case since they intentionally blend client and server code. +Remix knows that exports like `loader`, `action`, `headers`, etc. are server-only, so it can safely remove them from the client bundle. +But there's no way to know when looking at a single route module in isolation whether user-defined exports are server-only. +That's why Remix's Vite plugin is stricter about which exports are allowed from your route modules. + +In fact, we'd rather not rely on treeshaking for correctness at all. +If tomorrow you or your coworker accidentally imports something you _thought_ was client safe, +treeshaking will no longer exclude that from your client bundle and you might end up with server code in your app! +Treeshaking is designed as a pure optimization, so relying on it for correctness is brittle. +In short, Vite made us eat our veggies, but turns out they were delicious all along! + +So instead of treeshaking, its better to be explicit about what code is server-only. +For route modules, that means only exporting Remix route exports. +For anything else, put it in a separate module and use a `.server` file or directory when needed. + +Ultimately, Route exports are Remix API. +Think of a Remix route module like a function and the exports like named arguments to the function. + +```ts +// Not real API, just a mental model +let route = createRoute({ loader, mySuperCoolThing }); +// ^^^^^^^^^^^^^^^^ +// Object literal may only specify known properties, and 'mySuperCoolThing' does not exist in type 'RemixRoute' +``` + +Just like how you shouldn't pass unexpected named arguments to a function, you shouldn't create unexpected exports from a route module. +The result is that Remix is simpler and more predictable. + +👉 **Move any user-defined route exports to a separate module** + +For example, here's a route with a user-defined export called `mySuperCoolThing`: ```ts filename=app/routes/super-cool.tsx -// ❌ This is the problematic export +// ❌ This isn't a Remix-specific route export, just something I made up export const mySuperCoolThing = "Some value I wanted to colocate with my route!"; @@ -656,7 +687,8 @@ export const loader = () => {}; export default function SuperCool() {} ``` -Using the default route convention in v2, you can refactor to: +One option is to colocate your route and related utilities in the same directory if your routing convention allows it. +For example, with the default route convention in v2: ```ts filename=app/routes/super-cool/route.tsx export const loader = () => {}; @@ -665,12 +697,11 @@ export default function SuperCool() {} ``` ```ts filename=app/routes/super-cool/utils.ts +// If this was server-only code, I'd rename this file to "utils.server.ts" export const mySuperCoolThing = "Some value I wanted to colocate with my route!"; ``` -That way your utilities are still colocated with your route, but in a separate module. - ## Troubleshooting Check out the [known issues with the Remix Vite plugin on GitHub][issues-vite] before filing a new bug report!