Repository navigation
Version Packages (next) - #398
Merged
Merged
Conversation
github-actions
Bot
force-pushed
the
changeset-release/next
branch
6 times, most recently
from
October 8, 2026 20:29
f24c0ab to
5291104
Compare
github-actions
Bot
force-pushed
the
changeset-release/next
branch
from
October 8, 2026 21:10
5291104 to
96691bb
Compare
github-actions
Bot
force-pushed
the
changeset-release/next
branch
from
October 8, 2026 21:16
96691bb to
07ca4db
Compare
commit: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to next, this PR will be updated.
nextis currently in pre mode so this branch has prereleases rather than normal releases. If you want to exit prereleases, runchangeset pre exitonnext.Releases
@solidjs/vite-plugin@3.0.0-next.48
Minor Changes
(event, next) => Response | Promise<Response>, with the request atevent.request. The plugin composes the chain itself.next()takes no arguments — assignevent.requestbefore calling it to substitute the request downstream;next(request)throws a migration error. Per-request render inputs live on the event, set beforenext()(the render runs inside it):event.nonce(a string or{ script, style }) andevent.renderMode('stream'|'async').handleRequest(request, { nonce, renderMode })is seeded onto the event before the chain and wins over a middleware write, then the event field, then staticstart.renderMode, then'stream'. Invalid host options reject the call before the chain. Generated entries passevent.noncetorenderToStream; authored entries must forward thecontext.noncethe handler passes them. The injected client-entry script, redirect fallback, dev head, dev styles, and (when there is a style nonce) a<meta property="csp-nonce">carry it too. Thestart.renderModemodule form, which only shipped in 3.0.0-next prereleases, is removed — a path is a config error pointing atevent.renderModein middleware. The static'stream'|'async'shorthand stays. A nonce set while prerendering the client-mode shell is not baked intodist/client/index.html(the build warns). In dev, changingevent.nonceorevent.renderModeafter the render has read them warns.Patch Changes
[...404].tsxbuilt to_...404_-<hash>.js, and hosts, CDNs or middleware that reject any URL containing..refused that chunk, so the lazy route failed to hydrate. Builds now run the configuredoutput.sanitizeFileName(or the bundler default) and then collapse every run of dots in the last segment of the name to one: the chunk becomes_.404_-<hash>.js. Directories are left alone: withpreserveModulesthey are part of the name. The server build is named the same way, so the asset URLs it writes into server-rendered markup keep pointing at the files the client build wrote. A customsanitizeFileNamestill runs, with the collapse applied after it, whether it comes from the config or from another plugin'soutputOptionshook;sanitizeFileName: falseis left alone. Fixes Catch-all route chunks are named_...404_-<hash>.js; the..trips path-traversal guards and breaks the lazy preload #391.handleRequest(request, { nonce })accepts the{ script, style }form of@solidjs/web'sCSPNonceand uses itsscriptvalue for the scripts the handler writes: the injected client-entry tag and the post-flush redirect fallback. A pair used to throwTypeError: value.replace is not a function. A value outsideCSPNonce(anything but a string or a{ script, style }object with both keys, each a non-empty string orfalse) now rejects the call up front with an error naming the option, before the middleware chain runs; an empty value (undefined,nullor'') still means no nonce. The option is now declared in thevirtual:solid-ssr-handlertypes.lazy()moduleUrl with a leading slash (lazy(() => import("./Page"), undefined, "/src/Page.tsx")) now resolves like the project-relative keysrc/Page.tsx(lazy() moduleUrl with a leading slash never resolves: dev emits//src/…, the build manifest lookup misses #390). In dev the asset resolver built a protocol-relative//src/Page.tsxURL, so the preload failed and hydration fell back to a client render; in production thevirtual:solid-manifestlookup missed, no client assets or root module map were emitted, and hydration threw "was not preloaded before hydration". The dev resolver (in-process, HTTP bridge, and the generated fallback) now strips the leading slash before building the URL and walking the module graph, and the baked build manifest answers slash-prefixed lookups through non-enumerable aliases, sofor…in,Object.keys, and JSON consumers see the manifest unchanged.Response, or theResponsea thrownrespond()envelope carries, becomes the response in dev and production, sothrow redirect()works from middleware. In a production build any other failure (a middleware throw, astart.setuporstart.renderModemodule failure) is reported once to theconfigureServerErrorshook as{ kind: 'render', handling: 'failed' }with the request event, or logged withconsole.errorwithout a hook, and answered with a bodyless 500. That 500 keeps the headers and cookies written to the request event while the response head is still open, that is, unlessnext()already returned a rendered page. In dev those failures still reject, so the dev server sees the original error. An invalidrenderModepassed tohandleRequeststill rejects the call. A client-mode build now fails when prerendering the shell answers a non-2xx status, instead of writing that response toindex.html.client(Vite 8: dep scan JSX is only set for the client environment, so ssr scans (e.g. Cloudflare) fail on react/jsx-dev-runtime #387). Vite seeds only theclientenvironment from the top-leveloptimizeDeps, so anssr(or other server) environment with discovery turned back on — as@cloudflare/vite-plugindoes for workerd SSR — scanned Solid TSX with Rolldown's default React automatic runtime. The scan failed on an unresolvablereact/jsx-dev-runtimeand pre-bundling was skipped for that environment, which showed up as duplicate Solid instances in the app.configEnvironmentnow gives non-client environments the classic scanner JSX runtime (unless the app set its own per-environmenttransform.jsx), the.tsrxextension, and the tsrx scan plugin.__SOLID_SERVER_COMPONENTS__so libraries can drop server-component-only client code (Define__SOLID_SERVER_COMPONENTS__at build time so libraries can drop server-component-only client code #396). The value is"true"whenserverFunctions.componentsis set (including'external') and"false"otherwise, and it is always defined — an absent identifier cannot be eliminated. It is set on Vite'sdefine(build, and dev source via/@vite/env) and on every environment'soptimizeDeps.rolldownOptions.transform.define, because the optimizer ignores top-leveldefineand only theclientenvironment inherits top-leveloptimizeDeps. A user-provideddefinevalue wins, and so does a value already set on that environment's optimizer.serverFunctionson, the dev server now pre-bundles the server-function client runtime even withoutcomponents(@solidjs/web/server-functions, orruntime.clientwhen it names a package), so a cold cache no longer re-optimizes and reloads on the first"use server"module. In Vitest browser mode that reload showed up as "Vite unexpectedly reloaded a test".on*name (onclick) as a plain attribute everywhere (both compilers, spread/assign, and the server spread walk); onlyonfollowed by an uppercase letter is an event handler, and a function handed to a lowercaseon*attribute is escaped rather than bound. Server-component frame markup also moved: refetched content lands at the transition's commit. With the old^2.0.0-rc.13floor an existing lockfile could keep an rc.13 compiler while the app's runtime moved to rc.14, so compiled output and the frames runtime would disagree; the floor bump closes that window.vite devthe SSR environment now inlinesserovalandseroval-pluginsnext tosolid-jsand@solidjs/web. Both ship adist/devbuild behind thedevelopmentcondition, and@solidjs/webimports both. Left external,seroval-pluginsloaded through Node and its ownimport "seroval"resolved to the prod copy, while the inlined@solidjs/webgot the runner's dev copy. Seroval detects streams withinstanceof Stream, so theStreamthatReadableStreamPluginbuilds from one copy was rejected by the other copy's serializer. This broke server components (serverFunctions: { components: true }) in dev when a component resolved after the shell flush (for example after anawaitin the server function): itssc:liveReadableStream failed with "Seroval caught an error during the parsing process … cannot be parsed/serialized", the<Loading>boundary contained the error, and the component only rendered on the client. Builds were unaffected because they bundle a single copy. A host that setsnoExternal: trueand Vitest projects are left alone, as before.