Duplicates
Latest version
Summary 💡
Add a built-in server-only virtual module that throws a build-time error when imported in client-side code. When imported inside a "use server" file or any server-side module, it is a no-op.
This can be implemented as a first-class Vite plugin inside @solidjs/start/config:
{
name: 'server-only',
resolveId(id, importer, { ssr }) {
if (id !== 'server-only') return null;
if (!ssr) {
this.error(
`[server-only] "${importer}" cannot import a server-only module on the client`,
);
}
return '\0server-only';
},
load(id) {
if (id === '\0server-only') return 'export {}';
},
},
'client-only' is similar to this.
Examples 🌈
import 'server-only';
// anything below is guaranteed never to reach the client bundle
export const db = createDatabaseClient();
Motivation 🔦
SolidStart has no way to enforce that a module never reaches the client bundle. "use server" marks functions as server RPCs, but it does not prevent accidental client-side imports of modules containing secrets, DB credentials, or Node.js-only APIs.
The workaround today is a runtime check using import.meta.env.SSR, but that only throws in the browser at runtime — it won't catch the leak in CI or during pnpm build. A build-time error via a Vite resolveId hook is both trivial to implement and already proven in Next.js. Shipping it as part of @solidjs/start would give the same safety guarantee without requiring users to wire up the plugin themselves.
Duplicates
Latest version
Summary 💡
Add a built-in server-only virtual module that throws a build-time error when imported in client-side code. When imported inside a "use server" file or any server-side module, it is a no-op.
This can be implemented as a first-class Vite plugin inside
@solidjs/start/config:'client-only' is similar to this.
Examples 🌈
Motivation 🔦
SolidStart has no way to enforce that a module never reaches the client bundle. "use server" marks functions as server RPCs, but it does not prevent accidental client-side imports of modules containing secrets, DB credentials, or Node.js-only APIs.
The workaround today is a runtime check using import.meta.env.SSR, but that only throws in the browser at runtime — it won't catch the leak in CI or during pnpm build. A build-time error via a Vite resolveId hook is both trivial to implement and already proven in Next.js. Shipping it as part of @solidjs/start would give the same safety guarantee without requiring users to wire up the plugin themselves.