diff --git a/.changeset/dev-ssr-inline-core.md b/.changeset/dev-ssr-inline-core.md new file mode 100644 index 0000000..e399931 --- /dev/null +++ b/.changeset/dev-ssr-inline-core.md @@ -0,0 +1,5 @@ +--- +'@solidjs/vite-plugin': patch +--- + +Dev servers now inline `solid-js` and `@solidjs/web` into every server environment instead of externalizing them. `resolve.externalConditions` only governs the imports Vite's module runner resolves itself; an externalized package's own imports are resolved by Node with Node's conditions, never `development`. Since solid 2.0.0-rc.7 both core packages ship a `dist/server.dev.*` behind that condition, so under `vite dev` the framework split in two: the app's `solid-js` was the runner's dev copy while `@solidjs/web`'s `import "solid-js"` landed on Node's production copy. `renderToStream` installed the asset resolver on one `sharedConfig` and `lazy()` read the other — every dev SSR page with a `lazy()` component failed with `lazy() called with moduleUrl "…" but no asset manifest is set` — and every other module-level singleton (owner tracking, request events, hydration keys) was divided the same way. With the two packages in `resolve.noExternal` every resolution, theirs included, goes through the environment's conditions and a single dev build is loaded end to end. Applies whenever the plugin injects dev mode into a server environment; vitest projects (which manage their own inlining) and hosts that set `noExternal: true` are left as they are. diff --git a/.changeset/start-render-mode.md b/.changeset/start-render-mode.md index b4586c4..91f864e 100644 --- a/.changeset/start-render-mode.md +++ b/.changeset/start-render-mode.md @@ -2,4 +2,4 @@ '@solidjs/vite-plugin': minor --- -`start.renderMode: 'stream' | 'async'` (default `'stream'`), plus a per-request form and a runtime override — the fix for streaming SSR leaving `` fallbacks unresolved for clients that never run JavaScript (solidjs/solid#3280). `'async'` makes the generated handler adopt the `renderToStream` result's thenable, which resolves with the complete HTML once every boundary has settled: nothing has flushed, so each boundary's content is spliced in place of its placeholder — no fallback markup, no swap templates or scripts — while hydration data still serializes and JavaScript clients hydrate as before. The string then takes `createSSRResponse`'s string path: the response head commits, the document gets the doctype and client-entry injection, and a `Location` written mid-render becomes a real 3xx instead of the post-flush script redirect. The tradeoffs are inherent and documented: time-to-first-byte waits for the slowest boundary and the whole page buffers in memory; `deferStream` is moot (everything defers). The per-request form follows the `middleware`/`setup` convention — `renderMode: './src/render-mode.ts'`, a module default-exporting `(event) => 'stream' | 'async' | Promise<...>` run inside the request scope after the middleware chain — for policies like "complete documents for crawler user agents or `?nojs`, streaming for everyone else". Hosts driving the handler directly pass `handleRequest(request, { renderMode })`; precedence is that runtime option, then the module function, then the static config, and an invalid value from any source is rejected with an actionable error (unknown literals and missing module paths fail at config time). Works identically for authored entries. Generated entries also commit the response head at render completion (`onCompleteAll`) so `httpStatus`/`httpHeader` declarations survive the runtime's dispose-before-resolve in the awaited path; stream mode is unchanged. +`start.renderMode: 'stream' | 'async'` (default `'stream'`), plus a per-request form and a runtime override — the fix for streaming SSR leaving `` fallbacks unresolved for clients that never run JavaScript (solidjs/solid#3280). `'async'` makes the generated handler adopt the `renderToStream` result's thenable, which resolves with the complete HTML once every boundary has settled: nothing has flushed, so each boundary's content is spliced in place of its placeholder — no fallback markup, no swap templates or scripts — while hydration data still serializes and JavaScript clients hydrate as before. The string then takes `createSSRResponse`'s string path: the response head commits, the document gets the doctype and client-entry injection, and a `Location` written mid-render becomes a real 3xx instead of the post-flush script redirect. The tradeoffs are inherent and documented: time-to-first-byte waits for the slowest boundary and the whole page buffers in memory; `deferStream` is moot (everything defers). The per-request form follows the `middleware`/`setup` convention — `renderMode: './src/render-mode.ts'`, a module default-exporting `(event) => 'stream' | 'async' | Promise<...>` run inside the request scope after the middleware chain — for policies like "complete documents for crawler user agents or `?nojs`, streaming for everyone else". Hosts driving the handler directly pass `handleRequest(request, { renderMode })`; precedence is that runtime option, then the module function, then the static config, and an invalid value from any source is rejected with an actionable error (unknown literals and missing module paths fail at config time). Works identically for authored entries; stream mode is unchanged. Requires `solid-js` / `@solidjs/web` `^2.0.0-rc.7`, which freezes the response head when the awaited render completes so `httpStatus` / `httpHeader` declarations reach the response (solidjs/solid#3292). diff --git a/README.md b/README.md index c523f1b..30734d5 100644 --- a/README.md +++ b/README.md @@ -435,15 +435,10 @@ runtime option, then the module function's result, then the static config; an unknown value from any of the three is an error naming its source. The mode applies to generated and authored entries alike — an authored `render()` returning a `renderToStream` result is awaited the same way (and -in production its client-entry reference is still rewritten). One caveat for -authored entries: `httpStatus()` / `httpHeader()` declarations made during -the render are reverted when the runtime disposes it, which under `'async'` -happens before the response head is committed — the generated entry commits -the head at render completion (`renderToStream`'s `onCompleteAll`) to keep -them, so an authored entry that needs them under `'async'` should pass the -same hook (`onCompleteAll: () => commitResponseStub(getRequestEvent().response)`); -a `Location` written straight onto `event.response.headers` is unaffected. -Server mode only — in client mode the served shell has no boundaries to +in production its client-entry reference is still rewritten). `httpStatus()` / +`httpHeader()` declarations survive either mode: the runtime freezes the +response head when the awaited render completes (`@solidjs/web` 2.0.0-rc.7+), +just as streaming freezes it at shell flush. Server mode only — in client mode the served shell has no boundaries to settle, so the option is a documented no-op there. **`env`** — first-party typed environment variables. A schema file at the diff --git a/examples/css-matrix/vite.config.ts b/examples/css-matrix/vite.config.ts index 7a67ca3..8e28e1a 100644 --- a/examples/css-matrix/vite.config.ts +++ b/examples/css-matrix/vite.config.ts @@ -61,12 +61,6 @@ export default defineConfig({ solidPlugin({ compiler: 'native', ssr: true }), bundleChunksProbe(), ], - // TEMPORARY: the workspace links solid-js to a sibling worktree (see - // pnpm-workspace.yaml), which stops Vite from externalizing it in SSR and - // splits it into two instances (bundled app copy vs the one the external - // @solidjs/web loads). Force it external to match published-package - // behavior; remove together with the workspace link. - ssr: { external: ['solid-js'] }, build: { manifest: true, rollupOptions: { diff --git a/examples/ssr/vite.config.ts b/examples/ssr/vite.config.ts index 2f9202f..61fc53a 100644 --- a/examples/ssr/vite.config.ts +++ b/examples/ssr/vite.config.ts @@ -3,12 +3,6 @@ import solidPlugin from '@solidjs/vite-plugin'; export default defineConfig({ plugins: [solidPlugin({ compiler: 'native', ssr: true })], - // TEMPORARY: the workspace links solid-js to a sibling worktree (see - // pnpm-workspace.yaml), which stops Vite from externalizing it in SSR and - // splits it into two instances (bundled app copy vs the one the external - // @solidjs/web loads). Force it external to match published-package - // behavior; remove together with the workspace link. - ssr: { external: ['solid-js'] }, build: { manifest: true, rollupOptions: { diff --git a/package.json b/package.json index 464d6cd..322511e 100644 --- a/package.json +++ b/package.json @@ -91,9 +91,9 @@ }, "peerDependencies": { "@solidjs/start-devtools": "^1.0.0-next.2", - "@solidjs/web": "^2.0.0-rc.0", + "@solidjs/web": "^2.0.0-rc.7", "@testing-library/jest-dom": "^5.16.6 || ^5.17.0 || ^6.*", - "solid-js": "^2.0.0-rc.0", + "solid-js": "^2.0.0-rc.7", "vite": "^8.0.0 || ^9.0.0" }, "peerDependenciesMeta": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9de8af6..cee57be 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,11 +7,11 @@ settings: catalogs: default: '@solidjs/web': - specifier: ^2.0.0-rc.6 - version: 2.0.0-rc.6 + specifier: ^2.0.0-rc.7 + version: 2.0.0-rc.7 solid-js: - specifier: ^2.0.0-rc.6 - version: 2.0.0-rc.6 + specifier: ^2.0.0-rc.7 + version: 2.0.0-rc.7 importers: @@ -25,13 +25,13 @@ importers: version: 7.29.7 '@solidjs/babel-plugin': specifier: ^2.0.0-rc.6 - version: 2.0.0-rc.6(@babel/core@7.29.7)(@tsrx/core@0.1.63) + version: 2.0.0-rc.7(@babel/core@7.29.7)(@tsrx/core@0.1.63) '@solidjs/compiler': specifier: ^2.0.0-rc.6 - version: 2.0.0-rc.6 + version: 2.0.0-rc.7 '@solidjs/web': - specifier: ^2.0.0-rc.0 - version: 2.0.0-rc.6(solid-js@2.0.0-rc.6) + specifier: ^2.0.0-rc.7 + version: 2.0.0-rc.7(solid-js@2.0.0-rc.7) '@testing-library/jest-dom': specifier: ^5.16.6 || ^5.17.0 || ^6.* version: 6.10.0(@testing-library/dom@10.4.1) @@ -68,10 +68,10 @@ importers: version: 0.2.2 '@solidjs/diagnostics': specifier: ^2.0.0-rc.3 - version: 2.0.0-rc.6(vitest@4.1.11) + version: 2.0.0-rc.7(vitest@4.1.11) '@solidjs/start-devtools': specifier: ^1.0.0-next.3 - version: 1.0.0-next.4(@solidjs/web@2.0.0-rc.6(solid-js@2.0.0-rc.6))(solid-js@2.0.0-rc.6) + version: 1.0.0-next.4(@solidjs/web@2.0.0-rc.7(solid-js@2.0.0-rc.7))(solid-js@2.0.0-rc.7) '@types/node': specifier: ^24.0.0 version: 24.13.3 @@ -98,7 +98,7 @@ importers: version: 1.0.0(rollup@4.62.2) solid-js: specifier: ^2.0.0-rc.0 - version: 2.0.0-rc.6 + version: 2.0.0-rc.7 typescript: specifier: ^5.2.2 version: 5.9.3 @@ -110,10 +110,10 @@ importers: dependencies: '@solidjs/web': specifier: 'catalog:' - version: 2.0.0-rc.6(solid-js@2.0.0-rc.6) + version: 2.0.0-rc.7(solid-js@2.0.0-rc.7) solid-js: specifier: 'catalog:' - version: 2.0.0-rc.6 + version: 2.0.0-rc.7 devDependencies: '@solidjs/vite-plugin': specifier: workspace:* @@ -126,10 +126,10 @@ importers: dependencies: '@solidjs/web': specifier: 'catalog:' - version: 2.0.0-rc.6(solid-js@2.0.0-rc.6) + version: 2.0.0-rc.7(solid-js@2.0.0-rc.7) solid-js: specifier: 'catalog:' - version: 2.0.0-rc.6 + version: 2.0.0-rc.7 devDependencies: '@solidjs/vite-plugin': specifier: workspace:* @@ -142,10 +142,10 @@ importers: dependencies: '@solidjs/web': specifier: 'catalog:' - version: 2.0.0-rc.6(solid-js@2.0.0-rc.6) + version: 2.0.0-rc.7(solid-js@2.0.0-rc.7) solid-js: specifier: 'catalog:' - version: 2.0.0-rc.6 + version: 2.0.0-rc.7 devDependencies: '@solidjs/vite-plugin': specifier: workspace:* @@ -158,10 +158,10 @@ importers: dependencies: '@solidjs/web': specifier: 'catalog:' - version: 2.0.0-rc.6(solid-js@2.0.0-rc.6) + version: 2.0.0-rc.7(solid-js@2.0.0-rc.7) solid-js: specifier: 'catalog:' - version: 2.0.0-rc.6 + version: 2.0.0-rc.7 valibot: specifier: ^1.1.0 version: 1.4.2(typescript@5.9.3) @@ -183,10 +183,10 @@ importers: dependencies: '@solidjs/web': specifier: 'catalog:' - version: 2.0.0-rc.6(solid-js@2.0.0-rc.6) + version: 2.0.0-rc.7(solid-js@2.0.0-rc.7) solid-js: specifier: 'catalog:' - version: 2.0.0-rc.6 + version: 2.0.0-rc.7 devDependencies: '@solidjs/vite-plugin': specifier: workspace:* @@ -205,14 +205,14 @@ importers: dependencies: '@solidjs/web': specifier: 'catalog:' - version: 2.0.0-rc.6(solid-js@2.0.0-rc.6) + version: 2.0.0-rc.7(solid-js@2.0.0-rc.7) solid-js: specifier: 'catalog:' - version: 2.0.0-rc.6 + version: 2.0.0-rc.7 devDependencies: '@solidjs/testing-library': specifier: ^1.0.0-beta.2 - version: 1.0.0-beta.2(@solidjs/web@2.0.0-rc.6(solid-js@2.0.0-rc.6))(solid-js@2.0.0-rc.6) + version: 1.0.0-beta.2(@solidjs/web@2.0.0-rc.7(solid-js@2.0.0-rc.7))(solid-js@2.0.0-rc.7) '@solidjs/vite-plugin': specifier: workspace:* version: link:../.. @@ -1362,8 +1362,8 @@ packages: resolution: {integrity: sha512-T4Wyi9lUuz0a1C2OHuzqZ0aFOCI0AmaGTb2LP9sHgWdoHXlB3JU02gfBpa0Y081G/gFsJYpQ/R0iCJRzF/nknw==} hasBin: true - '@solidjs/babel-plugin@2.0.0-rc.6': - resolution: {integrity: sha512-bPw4UjS4OGgIHxetWwEj1OEBpU59RYt7t2jE1QPxqYlomJiS2fQFLiXFy62rkqme+zAFVWNV4SMyS+2THQI2Mw==} + '@solidjs/babel-plugin@2.0.0-rc.7': + resolution: {integrity: sha512-cKcyVbOh8WC7ywV3txxfNrFRtTa7t8O3tXDXRf3RE3DKyZr+hZmbEOq6q/T6smaJXS3ekzuUDVlQrG1+HErnhg==} peerDependencies: '@babel/core': ^7.20.12 '@tsrx/core': 0.1.63 @@ -1371,48 +1371,48 @@ packages: '@tsrx/core': optional: true - '@solidjs/compiler-darwin-arm64@2.0.0-rc.6': - resolution: {integrity: sha512-uTZeFIIqsoDEgp4YUDrmnrIt63Hgz5quEIDexTnzcL6sPUpSMFoDGtNR5db6+d/pCUXAAE8ZgimpG0EJ6gOOiw==} + '@solidjs/compiler-darwin-arm64@2.0.0-rc.7': + resolution: {integrity: sha512-xJ7FoPrFV94LMuEPNJ2nIGFlqhVGR+s5GAr0nzMRMdWAimriF0sZ8clxlIqPS3v2oaNE9JW7EDCdJysD3JezWg==} cpu: [arm64] os: [darwin] - '@solidjs/compiler-darwin-x64@2.0.0-rc.6': - resolution: {integrity: sha512-GmUujhjlOT9TBm10+8qS8Ft0sKc5that4CFmj4klbt40PywwPDfdhEzlw+awhlFgl+7FN75q+tRQdQJFNcrAgA==} + '@solidjs/compiler-darwin-x64@2.0.0-rc.7': + resolution: {integrity: sha512-rcu8wcxeO0QWXu69yFaSf3ZR1KlsPDCzmRmdA8fX/cte96Ox0r6GfMXE+5CH/gg9dSaXY3qwwmpSG9AEvLxZQg==} cpu: [x64] os: [darwin] - '@solidjs/compiler-linux-arm64-gnu@2.0.0-rc.6': - resolution: {integrity: sha512-/edSzc/fjl+QCYeaAxSEQwpOBiaB5DNrb8EUm4zKQHGWY1WwFeKSkSLoMKwnhmwCu+SIt1Z8fTEG6lZirUj1hw==} + '@solidjs/compiler-linux-arm64-gnu@2.0.0-rc.7': + resolution: {integrity: sha512-EhiLKgLcFkHWYOx3Pds3px0onhTbzpDfenhsuDy1R7ViZYALXXBlZ+EUSE85rKwyCM0sgcR/kVMswL2V8sJXng==} cpu: [arm64] os: [linux] - '@solidjs/compiler-linux-x64-gnu@2.0.0-rc.6': - resolution: {integrity: sha512-EWb0ypXtL7LbLn70M7O6FmK3pOKNDX9HaQETCiwZxjj/AXP7zYDsb7H5M1HsprbeXspij5+gft9Oeq7NfJJ+mQ==} + '@solidjs/compiler-linux-x64-gnu@2.0.0-rc.7': + resolution: {integrity: sha512-ymN3hIqzH3msWt3lcU3vqILnzRlB1rNbv1BlUqXkwVZByjFw/bJQ+BgncIq0WqNH6ciQ5nhZ1E7ECgGw/SNwEA==} cpu: [x64] os: [linux] - '@solidjs/compiler-wasm32-wasi@2.0.0-rc.6': - resolution: {integrity: sha512-aQCYH+d3TAx1i05vtdINSRnKxPFL8VnkSOoab2OkX3rmxwCGxpRRUvj+fOePiF28XO4ijDoY7Bty4QsP1jbUUw==} + '@solidjs/compiler-wasm32-wasi@2.0.0-rc.7': + resolution: {integrity: sha512-k4vN+EHRtoIxj0D8d2VYHPEnWIok6kokbZskpn1pXrOoXBkj0OmqzzyJVBvSRYx6cWDWEjCKSWGuufRRZtgmjA==} engines: {node: '>=14.0.0'} - '@solidjs/compiler-win32-x64-msvc@2.0.0-rc.6': - resolution: {integrity: sha512-8luAnqBxHJxEfw8SKqKGV1W2x+j1yk0G2rb242/z45pbVkQz+J5HNKMYSnvfKN3B2VpIvhZ447yph449wDKpEA==} + '@solidjs/compiler-win32-x64-msvc@2.0.0-rc.7': + resolution: {integrity: sha512-pZtrkWmiiZ/NRwyMASAitwAa4EO2jlt4z8Z5K9NoljnBreWrCsz4HmIKSIeZ+17++WwAyeZo2byon0AEv6FzRQ==} cpu: [x64] os: [win32] - '@solidjs/compiler@2.0.0-rc.6': - resolution: {integrity: sha512-3B6zdACJp+lImXJW/E0E5cXfsMlMXSIg9+s8me2sxz5Q4juGptiW+aUtluDb2e+lCUZt7kDVZdy5eHOmZ3T/mA==} + '@solidjs/compiler@2.0.0-rc.7': + resolution: {integrity: sha512-jhFq/QcoUM34760NuQiSvMDInZ+3AEHwA354VELRDpAJwuiMpPbEvkSH6qqfgneDzVwCiCtLbjScqUEymU7R1A==} - '@solidjs/diagnostics@2.0.0-rc.6': - resolution: {integrity: sha512-Q+4x6iwJCW+mV2jVMboaKubdjEUruirbgp+I4sa0XfNZFrbL1EQluiNqVpYL4Q0HszTzboRh2a2Rzob7OG7DTw==} + '@solidjs/diagnostics@2.0.0-rc.7': + resolution: {integrity: sha512-XppGGFRGc7dtX8i+eKn04A0+q2AGLdbTUbHqRhSRaN81aGHOAhMEeyXWzSoY9tABpPgy4jga1m9t4xz9FwAJzA==} peerDependencies: vitest: '>=2.0.0' peerDependenciesMeta: vitest: optional: true - '@solidjs/signals@2.0.0-rc.6': - resolution: {integrity: sha512-lPqwZNLPq1Z9CBvgXkMvi1ZFr5OHUiFNz1X40+yehszDWEbJkneZx7BGKIe9eMT/AN1NSL+PMjOiMyZaqVB2xw==} + '@solidjs/signals@2.0.0-rc.7': + resolution: {integrity: sha512-JY0OJ5nGeqxGKOAqCtuoHkFBkaWQYxmf+yBQE8vw/o9C7yUF+Kan9PwcrL0ZHR6+MgyixBUtTfBigwou5hwW5w==} '@solidjs/start-devtools@1.0.0-next.4': resolution: {integrity: sha512-RNjndz1PfUicxJi3XHwjoIsu9AHeOhpP8Y/bgRmumR5Z9ymdMsiRCL89Fq1YqxhBnHf+GL4kX/VvC+F8lgmTVA==} @@ -1427,10 +1427,10 @@ packages: '@solidjs/web': '>=2.0.0' solid-js: '>=2.0.0' - '@solidjs/web@2.0.0-rc.6': - resolution: {integrity: sha512-JgQ2NCjygQpZizZrVjcwPqH3dhIZQZoMRGoGSC6+Tr622cvbuXthDC3pKdNMsjCKCVp19UbT0kkPX15FOdT0pw==} + '@solidjs/web@2.0.0-rc.7': + resolution: {integrity: sha512-qsKKWR4PzzPw8ZGFR0Oc2776G1ONMMBKPJWO3Opf3cWHoczgfhknW6NED0WtdCuR6T8usFTWCZgMM5Cc0h14Dg==} peerDependencies: - solid-js: ^2.0.0-rc.6 + solid-js: ^2.0.0-rc.7 '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} @@ -2839,8 +2839,8 @@ packages: resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} engines: {node: '>=10'} - solid-js@2.0.0-rc.6: - resolution: {integrity: sha512-Z/M8s9ypLBf+6Bl3AAb5upgkYCl73HkpM+UxdUJ5uFGctTwpOQVCM9Gpj3Mjbiaki270HHUfA3Z0Lyn4w+fDtg==} + solid-js@2.0.0-rc.7: + resolution: {integrity: sha512-3APJcwGbJ3YzXzPXwl0R3cAiogXLacXdXSFasdE2uw1Gzj5xqDW/0bJu4fs75KK5WzXg+JfpkcsxBjTxkbnLQQ==} source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} @@ -4445,7 +4445,7 @@ snapshots: kleur: 4.1.5 yargs-parser: 20.2.9 - '@solidjs/babel-plugin@2.0.0-rc.6(@babel/core@7.29.7)(@tsrx/core@0.1.63)': + '@solidjs/babel-plugin@2.0.0-rc.7(@babel/core@7.29.7)(@tsrx/core@0.1.63)': dependencies: '@babel/core': 7.29.7 '@babel/helper-module-imports': 7.18.6 @@ -4457,61 +4457,61 @@ snapshots: optionalDependencies: '@tsrx/core': 0.1.63 - '@solidjs/compiler-darwin-arm64@2.0.0-rc.6': + '@solidjs/compiler-darwin-arm64@2.0.0-rc.7': optional: true - '@solidjs/compiler-darwin-x64@2.0.0-rc.6': + '@solidjs/compiler-darwin-x64@2.0.0-rc.7': optional: true - '@solidjs/compiler-linux-arm64-gnu@2.0.0-rc.6': + '@solidjs/compiler-linux-arm64-gnu@2.0.0-rc.7': optional: true - '@solidjs/compiler-linux-x64-gnu@2.0.0-rc.6': + '@solidjs/compiler-linux-x64-gnu@2.0.0-rc.7': optional: true - '@solidjs/compiler-wasm32-wasi@2.0.0-rc.6': + '@solidjs/compiler-wasm32-wasi@2.0.0-rc.7': dependencies: '@emnapi/core': 1.11.3 '@emnapi/runtime': 1.11.3 '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.11.3)(@emnapi/runtime@1.11.3) optional: true - '@solidjs/compiler-win32-x64-msvc@2.0.0-rc.6': + '@solidjs/compiler-win32-x64-msvc@2.0.0-rc.7': optional: true - '@solidjs/compiler@2.0.0-rc.6': + '@solidjs/compiler@2.0.0-rc.7': optionalDependencies: - '@solidjs/compiler-darwin-arm64': 2.0.0-rc.6 - '@solidjs/compiler-darwin-x64': 2.0.0-rc.6 - '@solidjs/compiler-linux-arm64-gnu': 2.0.0-rc.6 - '@solidjs/compiler-linux-x64-gnu': 2.0.0-rc.6 - '@solidjs/compiler-wasm32-wasi': 2.0.0-rc.6 - '@solidjs/compiler-win32-x64-msvc': 2.0.0-rc.6 + '@solidjs/compiler-darwin-arm64': 2.0.0-rc.7 + '@solidjs/compiler-darwin-x64': 2.0.0-rc.7 + '@solidjs/compiler-linux-arm64-gnu': 2.0.0-rc.7 + '@solidjs/compiler-linux-x64-gnu': 2.0.0-rc.7 + '@solidjs/compiler-wasm32-wasi': 2.0.0-rc.7 + '@solidjs/compiler-win32-x64-msvc': 2.0.0-rc.7 - '@solidjs/diagnostics@2.0.0-rc.6(vitest@4.1.11)': + '@solidjs/diagnostics@2.0.0-rc.7(vitest@4.1.11)': dependencies: - '@solidjs/signals': 2.0.0-rc.6 + '@solidjs/signals': 2.0.0-rc.7 optionalDependencies: vitest: 4.1.11(@types/node@24.13.3)(@vitest/browser-playwright@4.1.11)(jsdom@26.1.0)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.2)) - '@solidjs/signals@2.0.0-rc.6': {} + '@solidjs/signals@2.0.0-rc.7': {} - '@solidjs/start-devtools@1.0.0-next.4(@solidjs/web@2.0.0-rc.6(solid-js@2.0.0-rc.6))(solid-js@2.0.0-rc.6)': + '@solidjs/start-devtools@1.0.0-next.4(@solidjs/web@2.0.0-rc.7(solid-js@2.0.0-rc.7))(solid-js@2.0.0-rc.7)': dependencies: - '@solidjs/web': 2.0.0-rc.6(solid-js@2.0.0-rc.6) - solid-js: 2.0.0-rc.6 + '@solidjs/web': 2.0.0-rc.7(solid-js@2.0.0-rc.7) + solid-js: 2.0.0-rc.7 - '@solidjs/testing-library@1.0.0-beta.2(@solidjs/web@2.0.0-rc.6(solid-js@2.0.0-rc.6))(solid-js@2.0.0-rc.6)': + '@solidjs/testing-library@1.0.0-beta.2(@solidjs/web@2.0.0-rc.7(solid-js@2.0.0-rc.7))(solid-js@2.0.0-rc.7)': dependencies: - '@solidjs/web': 2.0.0-rc.6(solid-js@2.0.0-rc.6) + '@solidjs/web': 2.0.0-rc.7(solid-js@2.0.0-rc.7) '@testing-library/dom': 10.4.1 - solid-js: 2.0.0-rc.6 + solid-js: 2.0.0-rc.7 - '@solidjs/web@2.0.0-rc.6(solid-js@2.0.0-rc.6)': + '@solidjs/web@2.0.0-rc.7(solid-js@2.0.0-rc.7)': dependencies: seroval: 1.5.6 seroval-plugins: 1.5.6(seroval@1.5.6) - solid-js: 2.0.0-rc.6 + solid-js: 2.0.0-rc.7 '@standard-schema/spec@1.1.0': {} @@ -5964,9 +5964,9 @@ snapshots: astral-regex: 2.0.0 is-fullwidth-code-point: 3.0.0 - solid-js@2.0.0-rc.6: + solid-js@2.0.0-rc.7: dependencies: - '@solidjs/signals': 2.0.0-rc.6 + '@solidjs/signals': 2.0.0-rc.7 csstype: 3.2.3 seroval: 1.5.6 seroval-plugins: 1.5.6(seroval@1.5.6) diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 7375893..1c2a955 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -8,27 +8,27 @@ allowBuilds: msw: true catalog: - solid-js: "^2.0.0-rc.6" - "@solidjs/web": "^2.0.0-rc.6" + solid-js: "^2.0.0-rc.7" + "@solidjs/web": "^2.0.0-rc.7" ignoredBuiltDependencies: - cypress minimumReleaseAgeExclude: - - '@solidjs/signals@2.0.0-beta.30 || 2.0.0-beta.31 || 2.0.0-beta.32 || 2.0.0-rc.0 || 2.0.0-rc.1 || 2.0.0-rc.2 || 2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6' + - '@solidjs/signals@2.0.0-beta.30 || 2.0.0-beta.31 || 2.0.0-beta.32 || 2.0.0-rc.0 || 2.0.0-rc.1 || 2.0.0-rc.2 || 2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6 || 2.0.0-rc.7' - '@solidjs/start-devtools@1.0.0-next.1 || 1.0.0-next.2 || 1.0.0-next.3' - - '@solidjs/web@2.0.0-beta.30 || 2.0.0-beta.31 || 2.0.0-beta.32 || 2.0.0-rc.0 || 2.0.0-rc.1 || 2.0.0-rc.2 || 2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6' - - '@solidjs/babel-plugin@2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6' - - '@solidjs/compiler@2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6' - - '@solidjs/compiler-darwin-arm64@2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6' - - '@solidjs/compiler-darwin-x64@2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6' - - '@solidjs/compiler-linux-arm64-gnu@2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6' - - '@solidjs/compiler-linux-x64-gnu@2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6' - - '@solidjs/compiler-win32-x64-msvc@2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6' - - '@solidjs/compiler-wasm32-wasi@2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6' - - '@solidjs/diagnostics@2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6' + - '@solidjs/web@2.0.0-beta.30 || 2.0.0-beta.31 || 2.0.0-beta.32 || 2.0.0-rc.0 || 2.0.0-rc.1 || 2.0.0-rc.2 || 2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6 || 2.0.0-rc.7' + - '@solidjs/babel-plugin@2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6 || 2.0.0-rc.7' + - '@solidjs/compiler@2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6 || 2.0.0-rc.7' + - '@solidjs/compiler-darwin-arm64@2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6 || 2.0.0-rc.7' + - '@solidjs/compiler-darwin-x64@2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6 || 2.0.0-rc.7' + - '@solidjs/compiler-linux-arm64-gnu@2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6 || 2.0.0-rc.7' + - '@solidjs/compiler-linux-x64-gnu@2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6 || 2.0.0-rc.7' + - '@solidjs/compiler-win32-x64-msvc@2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6 || 2.0.0-rc.7' + - '@solidjs/compiler-wasm32-wasi@2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6 || 2.0.0-rc.7' + - '@solidjs/diagnostics@2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6 || 2.0.0-rc.7' - '@tsrx/core@0.1.63' - - solid-js@2.0.0-beta.30 || 2.0.0-beta.31 || 2.0.0-beta.32 || 2.0.0-rc.0 || 2.0.0-rc.1 || 2.0.0-rc.2 || 2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6 + - solid-js@2.0.0-beta.30 || 2.0.0-beta.31 || 2.0.0-beta.32 || 2.0.0-rc.0 || 2.0.0-rc.1 || 2.0.0-rc.2 || 2.0.0-rc.3 || 2.0.0-rc.4 || 2.0.0-rc.5 || 2.0.0-rc.6 || 2.0.0-rc.7 - '@dom-expressions/babel-plugin-jsx@0.50.0-next.35 || 0.50.0-next.37 || 0.50.0-next.40 || 0.50.0-next.43' - '@dom-expressions/compiler-darwin-arm64@0.50.0-next.35 || 0.50.0-next.37 || 0.50.0-next.40 || 0.50.0-next.43' - '@dom-expressions/compiler-darwin-x64@0.50.0-next.35 || 0.50.0-next.37 || 0.50.0-next.40 || 0.50.0-next.43' diff --git a/src/index.ts b/src/index.ts index 83bf9fd..7dcbf51 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1108,6 +1108,33 @@ export default function solidPlugin(options: Partial = {}): Plugin[] { 'development', ...(config.resolve.externalConditions ?? defaultExternalConditions), ]; + + // `externalConditions` only reaches the imports the module runner + // resolves itself. An externalized package's OWN imports are resolved + // by Node, with Node's conditions — never `development`. Since + // solid 2.0.0-rc.7 both `solid-js` and `@solidjs/web` ship a + // `dist/server.dev.*` behind that condition, so leaving them external + // splits the framework in two under `vite dev`: the app's `solid-js` + // is the runner's dev copy while `@solidjs/web`'s `import "solid-js"` + // lands on Node's prod copy. `renderToStream` then installs the asset + // resolver on one `sharedConfig` and `lazy()` reads the other ("no + // asset manifest is set"), with every other module-level singleton + // (owner tracking, request events, hydration keys) split the same + // way. Inlining the two core packages makes every resolution — theirs + // included — go through the environment's conditions, so one dev + // build is loaded end to end. Framework packages that declare the + // `solid` export condition are already inlined via vitefu below and + // reach the same copy. Vitest projects manage their own inlining + // (`test.server.deps` above) and are left alone, as is a host that + // set `noExternal: true` (everything is inlined already). + if (!isTestMode && config.resolve.noExternal !== true) { + const noExternal = config.resolve.noExternal; + config.resolve.noExternal = [ + ...(Array.isArray(noExternal) ? noExternal : noExternal ? [noExternal] : []), + 'solid-js', + '@solidjs/web', + ]; + } } // Set resolve.noExternal and resolve.external for the SSR environment. diff --git a/src/ssr/index.ts b/src/ssr/index.ts index daf7480..90f0005 100644 --- a/src/ssr/index.ts +++ b/src/ssr/index.ts @@ -762,9 +762,9 @@ export function startServe( ].join('\n'); } const { app } = requireEntries(); - const streamOptions = `{ manifest, onCompleteAll: commitResponseHead${serverComponents ? ', plugins: [ServerComponentPlugin]' : ''} }`; + const streamOptions = `{ manifest${serverComponents ? ', plugins: [ServerComponentPlugin]' : ''} }`; return [ - `import { renderToStream, getRequestEvent, commitResponseStub } from '@solidjs/web';`, + `import { renderToStream${setupPath ? ', getRequestEvent' : ''} } from '@solidjs/web';`, ...(serverComponents ? [ `import { configureServerFunctionsServer } from '@solidjs/web/server-functions';`, @@ -797,19 +797,6 @@ export function startServe( ``, ] : []), - // Commits the response head when the render completes — BEFORE the - // runtime disposes the render. `httpStatus`/`httpHeader` register - // cleanups that revert their declarations unless the stub is already - // committed; streaming commits at shell flush (this is a no-op there), - // but the async render mode resolves the complete document only after - // that disposal (`renderToStream(...).then` disposes, then resolves), - // so without this the settled 404 / Location would be reverted before - // createSSRResponse's string path could commit them. - `function commitResponseHead() {`, - ` const event = getRequestEvent();`, - ` if (event) commitResponseStub(event.response);`, - `}`, - ``, ...(setupPath ? [ // The per-request seam: the hook sees the same event the