Skip to content

[Feature?]: Built-in server-only & client-only virtual module #2162

Description

@YanAnghelp

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the 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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions