-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Vite: build errors when non-server-only exports contain server-only code #7924
Comments
A workaround might be to use Vite's import.meta.env.SSR: import { doServerStuff } from "~/do-server-stuff.server.ts"
export const handle = () => {
value: 1,
onlyCallThisFromServer: import.meta.env.SSR ? () => doServerStuff("wow") : null,
} But haven't tested if the SSR part of the ternary gets DCE'd by Vite or not at compile time. export const handle = () => {
value: 1,
onlyCallThisFromServer: () => {
if (!import.meta.env.SSR) throw Error("tried calling server-only function from client")
let {doServerStuff} = await import(/* vite-ignore */ "~/do-server-stuff.server.ts")
return doServerStuff("wow")
}
} |
I tested both of these and they did not work for me. I'm still getting:
|
I commented something similar previously in #7864 (comment). import {doServerStuff} from "/app/server-only.server.ts"
// Uncaught SyntaxError: The requested module '/app/server-only.server.ts' does not provide an export named 'doServerStuff' (at test1.tsx:2:10) So, in order to "cheat" this static error, I suggested this as a workaround: import * as serverLib from '../server-only.server';
export const handle = {
value: 1,
// runtime error if it called on client since `serverLib = { default: {} }`
onlyCallThisFromServer: () => serverLib.doServerStuff('wow'),
};
// during `vite build`, it shows warning, but application seems to be functional
// app/routes/test2.tsx (6:42) "doServerStuff" is not exported by "app/server-only.server.ts", imported by "app/routes/test2.tsx". I made this reproduction on stackblitz: I think I'm not sure if it's possible to expand remix's "remix-remove-server-exports" plugin to achieve this somehow, but I think another direction of the fix would be to improve "remix-empty-server-modules" plugin to do be aware of named exports. I had this idea before and I made a simple vite plugin with es-module-lexer here, but I haven't tested with remix plugin. It might not work with remix plugin directly since it has some intricate |
I think this is the same issue: #7931 |
handle
contains server-only code
Similar tree-shaking related issue happens for client-only code as well: #7972 |
@kentcdodds I think the issue you're having is that |
Addressed by #8198 For onlookers, there are two separate cases that cause server-only code issues like this:
Vite forced our hand to be stricter about what exports can be allowed for Remix routes, so user-defined exports from Remix routes are now considered invalid at build time, addressing (1). See #7864 for more details on that. For (2), you can use dynamic exports as an escape hatch. For example, with |
What version of Remix are you using?
2.2.0
Are all your remix dependencies & dev-dependencies using the same version?
Steps to Reproduce
Create a route with a
handle
that includes a function that relies on server-only code:In the client build,
do-server-stuff.server.ts
will be an empty module, buthandle
won't get treeshaken nor DCE'd. And it shouldn't be!value
may still be used/needed for the client build.Expected Behavior
There's some way to include server-only functions within
handle
without client build failing.Actual Behavior
In the client build,
do-server-stuff.server.ts
will be an empty module, buthandle
won't get treeshaken nor DCE'd. And it shouldn't be!value
may still be used/needed for the client build.But this causes client build to fail with an error that
do-server-stuff.server
doesn't exportdoServerStuff
.The text was updated successfully, but these errors were encountered: