Skip to content

Releases: solidjs/solid-vite-plugin

@solidjs/vite-plugin@3.0.0-next.43

Pre-release

Choose a tag to compare

@github-actions github-actions released this 11 Sep 17:10
5b6612b

Patch Changes

  • 4fb1af3: Honor the host's resolve.noExternal patterns when adding vitefu's externals to the SSR environment. The plugin already refused to re-externalize anything noExternal inlines, 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 in ssr.external — so a host that inlines its packages by pattern (TanStack Start's @tanstack/start**, whose @tanstack/start-server-core resolves its #tanstack-* imports only when Vite processes it) saw them re-externalized, and vite dev failed with ERR_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 RegExp noExternal value is kept instead of being dropped.
  • b173c94: New observe option: resolve Solid's observe builds for production observability. observe: true adds the observe export 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's componentNames option, so component owner labels (<Home>) survive minification in diagnostics and attribution paths. componentNames is also enabled under the dev posture, where lazy() 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

Pre-release

Choose a tag to compare

@github-actions github-actions released this 10 Sep 08:46
4236073

Patch Changes

  • ed9b798: Allow @testing-library/jest-dom v7 in the optional peer dependency range (ports #287 from main). The Solid 2.0 templates pin @testing-library/jest-dom@^7.0.0, and npm 7+ enforces peer ranges, so a clean npm install of a freshly created project failed with ERESOLVE against the ^6.* range (solidjs/solid#3341). v7 keeps the @testing-library/jest-dom/vitest subpath the plugin auto-injects into test.setupFiles, so only the range changes.

@solidjs/vite-plugin@3.0.0-next.41

Pre-release

Choose a tag to compare

@github-actions github-actions released this 10 Sep 00:24
e796386

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 a build.rollupOptions.input, and since #347 those records rightly keep isEntry in virtual:solid-manifest. The generated handler resolved the client entry by scanning for the first isEntry record, so a route key sorting ahead of the plugin's own virtual:solid-ssr-entry-client.tsx won: 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 — _entry carries 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 _entry before falling back to the isEntry scan for hand-rolled manifests. @solidjs/web's registerEntryAssets, which links the entry graph's stylesheets and modulepreloads by the first isEntry record, therefore agrees on the same chunk. Other configured inputs keep isEntry; they are genuine entries, just not the one the document boots.
  • bd04c66: Packages that consume the Solid runtime without declaring a solid export condition are now inlined in dev server environments too, closing the remaining half of the two-instance split. Inlining solid-js and @solidjs/web fixes every resolution those two perform, and vitefu inlines packages that advertise a solid export condition — but a package that does neither is still externalized, and Node resolves its own import "solid-js" without the development condition, so it loads the production server build while the inlined graph holds the dev one. @solidjs/meta is the first-party example: it has no solid condition, so under solid-js 2.0.0-rc.7 an app rendering a <Title> still died in useContext on a second sharedConfig even with the core packages inlined. The crawl now also classifies any package declaring solid-js or @solidjs/web in its dependencies or peerDependencies as a semi-framework package — ssr.noExternal without optimizeDeps.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 declares solid-js as a peer but never runs inside the SSR module runner — @solidjs/vite-plugin itself, vite, vitest, eslint-plugin-*, vite-plugin-*, prettier-plugin-*, @types/* — is skipped entirely (classifying the plugin would also crawl its dependencies and pre-bundle @babel/core and @solidjs/babel-plugin into the browser's optimizeDeps, several megabytes of dead weight per cold start); and the ssr.external list vitefu derives from framework packages' non-framework dependencies is filtered against the final noExternal list, because Vite gives external precedence — a framework package listing @solidjs/web under dependencies (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

Pre-release

Choose a tag to compare

@github-actions github-actions released this 08 Sep 17:47
09d73a9

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 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).

Patch Changes

  • a810d09: 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.

  • a3cc782: Fix vite dev breaking after a mid-session dependency re-optimization when the development toolbar is installed. The generated entries' @solidjs/start-devtools import 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 answered 504 Outdated Optimize Dep and the stale bundle brought a second solid-js instance 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/browser and /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 explicit configureServerFunctionsServer({ secret }) still outranks it.

  • 1f5f6ca: Never strip isEntry from 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/client lazily imports the serialization decoder, so a static import of @solidjs/web/serialization/decode anywhere in the client graph merges the decoder into the entry chunk and the entry ends up listing itself under dynamicImports. Demoting it left the bundle and manifest.json with no entry at all ("No entry file found" in downstream manifest capture such as TanStack Start's). Chunks whose facade matches a configured build.rollupOptions.input (or the default index.html / the start-mode client entry) now keep isEntry in the raw bundle and in virtual:solid-manifest, a chunk's dynamic import of itself is ignored, emitted lazy() 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 repairs isDynamicEntry on lazy facades, which rolldown drops when syncing generateBundle mutations back.

@solidjs/vite-plugin@3.0.0-next.39

Pre-release

Choose a tag to compare

@github-actions github-actions released this 05 Sep 08:49
3d6411e

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 as PersistedServerFunctionManifest).

@solidjs/vite-plugin@3.0.0-next.38

Pre-release

Choose a tag to compare

@github-actions github-actions released this 02 Sep 21:05
66ce052

Patch Changes

  • dfabe22: Auto-enable the agent diagnostics surface (dev serve only) when @solidjs/diagnostics is installed in the app — installing the dev dependency is now the whole setup. The diagnostics option becomes an override: true forces it on (erroring if the package is missing), false opts 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/diagnostics in 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.components now also accepts 'external': identical to true, but declares that a composing host (e.g. the Astro adapter or TanStack Start's Solid integration) owns the document wiring — render plugin + client-side installServerComponents() 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 at components: 'external'.
  • e8ffe62: Add experimental .tsrx compilation 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

Pre-release

Choose a tag to compare

@github-actions github-actions released this 01 Sep 18:43
022d5c2

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 under vite dev. Dispatch itself was unaffected (mount matching is prefix-based). The id now parses from behind the literal data segment too; a function id spelled data still 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 whole document, 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-Id header 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 from split('-')[1] rather than the first segment.

@solidjs/vite-plugin@3.0.0-next.36

Pre-release

Choose a tag to compare

@github-actions github-actions released this 29 Aug 09:08
7914afa

Patch Changes

  • 9f0ec40: Dev servers now resolve the development export condition for externalized server deps. Externalized SSR imports are resolved with resolve.externalConditions (default ['node', 'module-sync']), so packages selecting their dev build through the development condition — @solidjs/web's server-functions runtime among them — loaded their production copy under vite 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 prepends development to each server environment's externalConditions whenever it injects dev mode, matching the treatment resolve.conditions already got.

@solidjs/vite-plugin@3.0.0-next.35

Pre-release

Choose a tag to compare

@github-actions github-actions released this 28 Aug 22:10
3ffde4a

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 retired X-Server-Function-Id header 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: true is set: two extra lines after Vite's URLs naming the /__solid/diagnostics endpoint (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

Pre-release

Choose a tag to compare

@github-actions github-actions released this 26 Aug 07:59
447bbd9

Minor Changes

  • da12802: New diagnostics option (dev serve only): injects a client module that installs the in-page bridge from the app's own @solidjs/diagnostics and serves a /__solid/diagnostics endpoint 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/diagnostics is 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 (was babel-preset-solid — now a plugin rather than a preset, hosted in plugins with 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-flow builtIns, contextToCustomElements, wrapConditionals), so the plugin only passes the posture it actually decides (generate/hydratable/dev/serverComponents) plus user solid options, which override the built-in defaults exactly as before.

Patch Changes

  • f0412e6: The server-only/client-only boundary guard no longer crashes when
    this.environment isn't available on resolve hooks, and now detects the
    target environment through the same getEnvironmentConsumer helper used
    by the rest of the plugin, falling back to the resolve hook's ssr flag
    when the environment is absent.