Releases: solidjs/solid-vite-plugin
Release list
@solidjs/vite-plugin@3.0.0-next.43
Patch Changes
- 4fb1af3: Honor the host's
resolve.noExternalpatterns when adding vitefu's externals to the SSR environment. The plugin already refused to re-externalize anythingnoExternalinlines, but it compared literal names only, while Vite treats string entries as picomatch patterns and RegExp entries as tests (createFilter(undefined, noExternal, { resolve: false })). Since 3.0.0-next.41 the crawl also reaches the packages that consume the Solid runtime, and their non-Solid dependencies land inssr.external— so a host that inlines its packages by pattern (TanStack Start's@tanstack/start**, whose@tanstack/start-server-coreresolves its#tanstack-*imports only when Vite processes it) saw them re-externalized, andvite devfailed withERR_PACKAGE_IMPORT_NOT_DEFINED: Package import specifier "#tanstack-router-entry" is not defined. The externals are now filtered with the same matcher Vite uses, and a single string or RegExpnoExternalvalue is kept instead of being dropped. - b173c94: New
observeoption: resolve Solid's observe builds for production observability.observe: trueadds theobserveexport condition to every environment — client and server, inlined and externalized (resolve.externalConditions), inlining the core runtime and its consumers for server builds the way the dev posture already does so one build is loaded end to end — and turns on the compiler'scomponentNamesoption, so component owner labels (<Home>) survive minification in diagnostics and attribution paths.componentNamesis also enabled under the dev posture, wherelazy()and HMR wrappers otherwise hide the tag name. Requires@solidjs/compiler/@solidjs/babel-plugin≥ 2.0.0-rc.8 (the release that adds the option).
@solidjs/vite-plugin@3.0.0-next.42
Patch Changes
- ed9b798: Allow
@testing-library/jest-domv7 in the optional peer dependency range (ports #287 frommain). The Solid 2.0 templates pin@testing-library/jest-dom@^7.0.0, and npm 7+ enforces peer ranges, so a cleannpm installof a freshly created project failed withERESOLVEagainst the^6.*range (solidjs/solid#3341). v7 keeps the@testing-library/jest-dom/vitestsubpath the plugin auto-injects intotest.setupFiles, so only the range changes.
@solidjs/vite-plugin@3.0.0-next.41
Patch Changes
- 38434e1: Fix the start-mode handler booting the wrong chunk when the client build has several configured inputs (#353, a regression of 3.0.0-next.40 / #347). With filesystem-routing's
fileRoutes({ routers: { client }, buildInputs: 'client' })every route module is abuild.rollupOptions.input, and since #347 those records rightly keepisEntryinvirtual:solid-manifest. The generated handler resolved the client entry by scanning for the firstisEntryrecord, so a route key sorting ahead of the plugin's ownvirtual:solid-ssr-entry-client.tsxwon: the document's<script type="module">pointed at the route chunk (the page never hydrated) and<head>linked that route's CSS while the entry graph's global stylesheet was never linked. The manifest module now names the client entry explicitly —_entrycarries its key (the entry start mode injects, or the single configured input outside start mode) and its record is serialized first — and the handler reads_entrybefore falling back to theisEntryscan for hand-rolled manifests.@solidjs/web'sregisterEntryAssets, which links the entry graph's stylesheets and modulepreloads by the firstisEntryrecord, therefore agrees on the same chunk. Other configured inputs keepisEntry; they are genuine entries, just not the one the document boots. - bd04c66: Packages that consume the Solid runtime without declaring a
solidexport condition are now inlined in dev server environments too, closing the remaining half of the two-instance split. Inliningsolid-jsand@solidjs/webfixes every resolution those two perform, and vitefu inlines packages that advertise asolidexport condition — but a package that does neither is still externalized, and Node resolves its ownimport "solid-js"without thedevelopmentcondition, so it loads the production server build while the inlined graph holds the dev one.@solidjs/metais the first-party example: it has nosolidcondition, so under solid-js 2.0.0-rc.7 an app rendering a<Title>still died inuseContexton a secondsharedConfigeven with the core packages inlined. The crawl now also classifies any package declaringsolid-jsor@solidjs/webin itsdependenciesorpeerDependenciesas a semi-framework package —ssr.noExternalwithoutoptimizeDeps.exclude, since these hold no raw Solid components — so third-party component libraries and metadata helpers reach the same copy as everything else. Gated on the dev-condition swap (and off under vitest, which manages inlining itself), leaving builds unchanged. Two guards keep the rule narrow: tooling that declaressolid-jsas a peer but never runs inside the SSR module runner —@solidjs/vite-pluginitself,vite,vitest,eslint-plugin-*,vite-plugin-*,prettier-plugin-*,@types/*— is skipped entirely (classifying the plugin would also crawl its dependencies and pre-bundle@babel/coreand@solidjs/babel-plugininto the browser'soptimizeDeps, several megabytes of dead weight per cold start); and thessr.externallist vitefu derives from framework packages' non-frameworkdependenciesis filtered against the finalnoExternallist, because Vite givesexternalprecedence — a framework package listing@solidjs/webunderdependencies(e.g.@tanstack/solid-router) would otherwise re-externalize a core the plugin just inlined and split the runtime again.
@solidjs/vite-plugin@3.0.0-next.40
Minor Changes
- 0985ce8:
start.renderMode: 'stream' | 'async'(default'stream'), plus a per-request form and a runtime override — the fix for streaming SSR leaving<Loading>fallbacks unresolved for clients that never run JavaScript (solidjs/solid#3280).'async'makes the generated handler adopt therenderToStreamresult'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 takescreateSSRResponse's string path: the response head commits, the document gets the doctype and client-entry injection, and aLocationwritten 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;deferStreamis moot (everything defers). The per-request form follows themiddleware/setupconvention —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 passhandleRequest(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. Requiressolid-js/@solidjs/web^2.0.0-rc.7, which freezes the response head when the awaited render completes sohttpStatus/httpHeaderdeclarations reach the response (solidjs/solid#3292).
Patch Changes
-
a810d09: Dev servers now inline
solid-jsand@solidjs/webinto every server environment instead of externalizing them.resolve.externalConditionsonly governs the imports Vite's module runner resolves itself; an externalized package's own imports are resolved by Node with Node's conditions, neverdevelopment. Since solid 2.0.0-rc.7 both core packages ship adist/server.dev.*behind that condition, so undervite devthe framework split in two: the app'ssolid-jswas the runner's dev copy while@solidjs/web'simport "solid-js"landed on Node's production copy.renderToStreaminstalled the asset resolver on onesharedConfigandlazy()read the other — every dev SSR page with alazy()component failed withlazy() 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 inresolve.noExternalevery 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 setnoExternal: trueare left as they are. -
a3cc782: Fix
vite devbreaking after a mid-session dependency re-optimization when the development toolbar is installed. The generated entries'@solidjs/start-devtoolsimport reused the id captured when the toolbar was detected; in the client environment that id is the optimizer's pre-bundled URL, stamped with the browserHash of the pass that produced it. Any dependency discovered after the initial scan re-optimizes — the toolbar's chunks are re-emitted under new names and the hash moves on — and the frozen id kept the entry on the previous pass: its lazy chunks answered504 Outdated Optimize Depand the stale bundle brought a secondsolid-jsinstance into the page (hydration key misses,REACTIVITY_HALTED). The import is now resolved afresh on every request, so it always follows the current optimizer pass.The most common trigger is also removed: the agent diagnostics bridge (
@solidjs/diagnostics/browserand/protocol) reaches the page through a virtual module the dependency scanner never crawls, so its first load discovered the two imports and forced exactly that re-optimize + reload. The diagnostics plugin now pre-bundles them up front whenever the surface is enabled. -
c16985a: Provide the deployment secret to server builds (solidjs/solid#3239): the generated server-function handler module now leads with
globalThis.__SOLID_SECRET__ ??= "<random-per-build>", giving the runtime's encrypted no-JS flash cookie a key with zero configuration. One value is generated per plugin instance, so a production build bakes a single secret into the emitted server chunk (shared by every instance of that deployment) and a dev session holds one for its lifetime. Server output only — the handler module is already hard-gated against client graphs — and an explicitconfigureServerFunctionsServer({ secret })still outranks it. -
1f5f6ca: Never strip
isEntryfrom a genuine configured entry when reclassifying emitted lazy facade chunks. The normalization used to demote every chunk that is a dynamic-import target, which misfires once the real client entry absorbs a module that is also imported dynamically: with Solid 2,@solidjs/web/frames/clientlazily imports the serialization decoder, so a static import of@solidjs/web/serialization/decodeanywhere in the client graph merges the decoder into the entry chunk and the entry ends up listing itself underdynamicImports. Demoting it left the bundle andmanifest.jsonwith no entry at all ("No entry file found" in downstream manifest capture such as TanStack Start's). Chunks whose facade matches a configuredbuild.rollupOptions.input(or the defaultindex.html/ the start-mode client entry) now keepisEntryin the raw bundle and invirtual:solid-manifest, a chunk's dynamic import of itself is ignored, emittedlazy()facades are still reclassified, and a demotion the plugin cannot attribute to one of its own emitted chunks is reported with a warning describing the graph shape. The virtual manifest also repairsisDynamicEntryon lazy facades, which rolldown drops when syncinggenerateBundlemutations back.
@solidjs/vite-plugin@3.0.0-next.39
Patch Changes
- 9fbbef6: The persisted server-function manifest (
dist/client/.vite/solid-server-functions.json) now records every server function the client build can reach, by wire id, alongside the module list:{ modules: string[], functions: Array<{ id, name, module }> }. Build tooling that needs the client-reachable set — a static-site prerenderer verifying that each reachable function was captured at build time, for example — reads it from here instead of re-deriving it from compiled output. The previous array shape is still accepted when read (the type is exported asPersistedServerFunctionManifest).
@solidjs/vite-plugin@3.0.0-next.38
Patch Changes
- dfabe22: Auto-enable the agent diagnostics surface (dev serve only) when
@solidjs/diagnosticsis installed in the app — installing the dev dependency is now the whole setup. Thediagnosticsoption becomes an override:trueforces it on (erroring if the package is missing),falseopts out entirely, omitted auto-detects. Start mode's generated/authored client entries follow the same detection for the bridge import. - f463de5: Diagnostics auto-detection now requires the app to declare
@solidjs/diagnosticsin its own package.json (presence in ancestor node_modules surprise-enabled the surface for monorepo fixture apps), and the surface never activates in test mode (vitest browser mode runs a dev serve and was getting the bridge injected into test pages). - cf13314:
serverFunctions.componentsnow also accepts'external': identical totrue, but declares that a composing host (e.g. the Astro adapter or TanStack Start's Solid integration) owns the document wiring — render plugin + client-sideinstallServerComponents()call — itself, so the without-SSR-start-mode warning is skipped instead of printing on every host build. The remaining warning text is also updated: it listed "the bootstrap script" as a required app-side piece, but head bootstrap injection was removed (serialized references self-bootstrap the registry), and it now points hosts atcomponents: 'external'. - e8ffe62: Add experimental
.tsrxcompilation with native and Babel backends, scoped CSS sidecars, HMR and SSR asset integration, and function-level server functions.
@solidjs/vite-plugin@3.0.0-next.37
Patch Changes
- 73751ca: Only attach a request body in the dev middlewares' Node-to-web bridging when the incoming request actually carries one (Content-Length/Transfer-Encoding, or the h2 END_STREAM flag). An unconditionally attached empty stream made bodyless POSTs — zero-argument scripted server function calls, synthetic dispatches — parse as a present-but-unusable body, which @solidjs/web 2.0.0-rc.5 rejects as malformed (400) instead of ignoring.
- 16245b6: Dev middleware recognizes the scripted transport's data address. Scripted server-function calls now go to
<endpoint>/data/<id>(solidjs/solid#3094), and the middleware's module-preload step assumed exactly one path segment after the mount — a cold function only client code references would never be evaluated in the SSR environment for a data-addressed call, answering 404 undervite dev. Dispatch itself was unaffected (mount matching is prefix-based). The id now parses from behind the literaldatasegment too; a function id spelleddatastill parses at the bare address, since an id occupies exactly one segment. - 3a7ff44: Document shell edits now trigger a full page reload instead of being silently absorbed (solidjs/solid#3151). Two sides: the resolved
start.document/src/Document.*module declines HMR in its client compile (it hydrates the wholedocument, so no component swap can ever apply — self-accept + invalidate makes Vite reload instead), and server-environment updates for files with no client-graph counterpart (client-mode documents, authored entry-server, middleware) send a browser full-reload rather than staying suppressed — the suppression exists to protect client HMR from full-reload races, but a server-only file has no client update to race with. - fb9f447: Drop the retired
X-Server-Function-Idheader and?id=addressing fallback from the dev middleware's module-preload path. Addressing is path-only (<endpoint>/<id>and<endpoint>/data/<id>), matching the runtime's removal of its own transitional shims during the RC. - e9b2a39: Read the file hash from the second id segment. Server-function ids are now identity-keyed
<name>-<hash>[-<ordinal>](solidjs/solid#3109) instead of positional<hash>-<ordinal>, so the dev middleware's id-to-module lookup takes the hash fromsplit('-')[1]rather than the first segment.
@solidjs/vite-plugin@3.0.0-next.36
Patch Changes
- 9f0ec40: Dev servers now resolve the
developmentexport condition for externalized server deps. Externalized SSR imports are resolved withresolve.externalConditions(default['node', 'module-sync']), so packages selecting their dev build through thedevelopmentcondition — @solidjs/web's server-functions runtime among them — loaded their production copy undervite dev: thrown server errors reached the client sanitized to "Internal Server Error" instead of carrying the real message, and dev-only diagnostics vanished. The plugin now prependsdevelopmentto each server environment'sexternalConditionswhenever it injects dev mode, matching the treatmentresolve.conditionsalready got.
@solidjs/vite-plugin@3.0.0-next.35
Minor Changes
- 2f0384a: Route path-addressed server function calls (solidjs/solid#3076). A call's address is now
<endpoint>/<id>with arguments in the query, so the dev middleware and the generated request-dispatch gate match the endpoint by mount prefix instead of exact pathname, and the dev middleware's module-preload id comes from the path segment. The retiredX-Server-Function-Idheader and?id=forms remain as transitional fallbacks for the RC window only — they will be dropped before the stable release.
Patch Changes
- 5c50681: Announce the diagnostics surface in the dev-server startup block when
diagnostics: trueis set: two extra lines after Vite's URLs naming the/__solid/diagnosticsendpoint (with its method vocabulary) and the agent skill documents shipped in node_modules. Startup output is the one channel agents reliably read even in projects with no AGENTS.md, making this the discovery path for existing apps and ports. Dev-serve only.
@solidjs/vite-plugin@3.0.0-next.34
Minor Changes
- da12802: New
diagnosticsoption (dev serve only): injects a client module that installs the in-page bridge from the app's own@solidjs/diagnosticsand serves a/__solid/diagnosticsendpoint on the dev server. Out-of-process consumers (agents, tests, curl) drive capture sessions (begin/end),whyDidRun, and cost queries over the Vite WebSocket. Works for plain index.html apps (transformIndexHtml injection) and start mode (generated/custom client entry injection).@solidjs/diagnosticsis a type-only dependency of the plugin; the runtime bridge always comes from the app's installed copy. - da12802: Move to the renamed Solid 2.0 compiler packages: the native JSX/directives/lazy/refresh compiler is now
@solidjs/compiler(was@dom-expressions/compiler) and the Babel escape hatch is@solidjs/babel-plugin(wasbabel-preset-solid— now a plugin rather than a preset, hosted inpluginswith the same pass order: user plugins run before it, user presets after). Both backends now bake in the Solid defaults (moduleName: "@solidjs/web", the control-flowbuiltIns,contextToCustomElements,wrapConditionals), so the plugin only passes the posture it actually decides (generate/hydratable/dev/serverComponents) plus usersolidoptions, which override the built-in defaults exactly as before.
Patch Changes
- f0412e6: The
server-only/client-onlyboundary guard no longer crashes when
this.environmentisn't available on resolve hooks, and now detects the
target environment through the samegetEnvironmentConsumerhelper used
by the rest of the plugin, falling back to the resolve hook'sssrflag
when the environment is absent.