diff --git a/.changeset/keep-client-conditions.md b/.changeset/keep-client-conditions.md new file mode 100644 index 000000000..0d8808ace --- /dev/null +++ b/.changeset/keep-client-conditions.md @@ -0,0 +1,5 @@ +--- +"@solidjs/start": patch +--- + +Keep Vite's default resolve conditions ("module", "browser") in the client environment: since 2.1.0, packages exposing a "browser" export condition (e.g. `@sentry/solidstart`) resolved to their Node build in the browser. The dev overlay's `@jridgewell/trace-mapping` is now pre-bundled, as the "browser" condition makes it import a UMD build. diff --git a/packages/start/src/config/index.spec.ts b/packages/start/src/config/index.spec.ts index 4eec36f04..7f6650e43 100644 --- a/packages/start/src/config/index.spec.ts +++ b/packages/start/src/config/index.spec.ts @@ -81,3 +81,39 @@ describe("SERVER_BASE_URL", () => { await expect(serverBaseUrl({ base: "/app" }, command)).resolves.toBe("/app/"); }); }); + +describe("resolve conditions", () => { + async function resolveEnvironments(command: ConfigEnv["command"] = "serve") { + const { resolveConfig } = await import("vite"); + const config = await resolveConfig( + { root, logLevel: "silent", plugins: [solidStart()] }, + command, + command === "build" ? "production" : "development", + ); + return config.environments; + } + + it("keeps Vite's client conditions", async () => { + const { client } = await resolveEnvironments(); + + expect(client.resolve.conditions).toEqual(expect.arrayContaining(["module", "browser"])); + expect(client.resolve.conditions).not.toContain("generic"); + }); + + it("resolves the server to runtime-agnostic builds", async () => { + const { ssr } = await resolveEnvironments(); + + expect(ssr.resolve.conditions).toContain("generic"); + expect(ssr.resolve.conditions).not.toContain("node"); + }); + + it("pre-bundles the dev overlay's dependencies in dev only", async () => { + const dev = await resolveEnvironments("serve"); + const build = await resolveEnvironments("build"); + + expect(dev.client.optimizeDeps.include).toContain("@solidjs/start > @jridgewell/trace-mapping"); + expect(build.client.optimizeDeps.include ?? []).not.toContain( + "@solidjs/start > @jridgewell/trace-mapping", + ); + }); +}); diff --git a/packages/start/src/config/index.ts b/packages/start/src/config/index.ts index 3d5aa28e9..e8d09dde7 100644 --- a/packages/start/src/config/index.ts +++ b/packages/start/src/config/index.ts @@ -224,6 +224,11 @@ export interface SolidStartOptions { }; } +// The dev overlay is served unbundled (solid packages are excluded from +// pre-bundling), and with the "browser" condition @jridgewell/trace-mapping +// imports the UMD build of @jridgewell/resolve-uri, which has no ESM exports. +const DEV_OVERLAY_DEPENDENCIES = ["@solidjs/start > @jridgewell/trace-mapping"]; + const absolute = (path: string, root: string) => path ? (isAbsolute(path) ? path : join(root, path)) : path; @@ -293,10 +298,16 @@ export function solidStart(options?: SolidStartOptions): Array { { name: "solid-start:config", enforce: "pre", - configEnvironment(name) { + configEnvironment(name, config) { + // Setting resolve.conditions replaces Vite's defaults instead of extending + // them. Server environments drop "node" on purpose, so that h3 resolves to + // its runtime-agnostic build, but the client must keep "browser" and + // "module": without them, packages exposing a "browser" export condition + // resolve to their Node build in the browser. + const isClient = name === VITE_ENVIRONMENTS.client || config.consumer === "client"; return { resolve: { - conditions: ["generic"], + ...(isClient ? {} : { conditions: ["generic"] }), // remove when https://github.com/solidjs/vite-plugin-solid/pull/228 is released externalConditions: ["solid", "node"], }, @@ -343,6 +354,9 @@ export function solidStart(options?: SolidStartOptions): Array { environments: { [VITE_ENVIRONMENTS.client]: { consumer: "client", + ...(env.command === "serve" && start.devOverlay + ? { optimizeDeps: { include: DEV_OVERLAY_DEPENDENCIES } } + : {}), build: { write: true, manifest: true,