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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -180,8 +180,8 @@ same server functions.
180
180
  The object form carries the options (`start: true` is pure sugar for
181
181
  `start: {}` — both mean the identical start mode with defaults, and
182
182
  `false`/absent means off): `app`, `document`, `entryServer`, `entryClient`,
183
- `middleware`, `setup`, `env`, `devtools`, `errorBoundary`, `css`, `external`,
184
- all documented below.
183
+ `middleware`, `setup`, `renderMode`, `env`, `devtools`, `errorBoundary`,
184
+ `css`, `external`, all documented below.
185
185
 
186
186
  Install `@solidjs/start-devtools` as a development dependency to add the
187
187
  development toolbar with runtime errors and server function calls:
@@ -376,6 +376,71 @@ whatever the hook renders must be matched client-side for hydration —
376
376
  routers that own both sides (their client entry re-creates the router and
377
377
  hydrates the same tree) fit naturally.
378
378
 
379
+ **`renderMode`** — how a page render becomes a response body: `'stream'`
380
+ (the default) or `'async'`, or a module path deciding per request.
381
+
382
+ Streaming flushes the document shell as soon as it is ready, with every
383
+ `<Loading>` fallback in place, and streams the boundaries' content behind it
384
+ in later chunks; inline scripts swap that content into the page as it
385
+ arrives. That is the best time-to-first-byte a server render can have, but a
386
+ client that never runs JavaScript — a crawler, `curl`, a browser with
387
+ scripts disabled — is left looking at the fallbacks forever
388
+ ([solidjs/solid#3280](https://github.com/solidjs/solid/issues/3280)).
389
+ `'async'` is the other end of that trade: the handler awaits the render until
390
+ every boundary has settled and sends one complete document.
391
+
392
+ ```ts
393
+ solid({ start: { renderMode: 'async' }, ssr: true });
394
+ ```
395
+
396
+ Because nothing has flushed when a boundary resolves, its content is spliced
397
+ in place of its placeholder — the document carries no fallback markup, no
398
+ swap templates, no swap scripts — while hydration data still serializes
399
+ exactly as before, so JavaScript clients hydrate the settled document the
400
+ same way they hydrate a streamed one. The tradeoffs are inherent: the
401
+ response waits for the slowest boundary before its first byte, and the whole
402
+ page buffers in memory before it goes out. Two consequences worth knowing:
403
+ `deferStream` is moot under `'async'` (everything defers), and a `Location`
404
+ header written mid-render — the post-flush script redirect in stream mode —
405
+ becomes a real 3xx with no body, which is exactly what a no-JS client needs.
406
+
407
+ Most apps want streaming for browsers and a complete document for the few
408
+ clients that cannot run the swap. The per-request form is a module path
409
+ (relative to the Vite root, following the `middleware`/`setup` convention
410
+ — a Vite config cannot serialize a closure into the generated handler)
411
+ default-exporting `(event) => 'stream' | 'async' | Promise<'stream' |
412
+ 'async'>`. It runs inside the request scope after the middleware chain, so
413
+ `event.locals` is decorated by the time it decides:
414
+
415
+ ```ts
416
+ // vite.config.ts
417
+ solid({ start: { renderMode: './src/render-mode.ts' }, ssr: true });
418
+
419
+ // src/render-mode.ts
420
+ import type { RequestEvent } from '@solidjs/web';
421
+
422
+ const CRAWLER = /Googlebot|bingbot|DuckDuckBot|Slurp|Baiduspider|YandexBot/i;
423
+
424
+ export default function renderMode(event: RequestEvent) {
425
+ const { request } = event;
426
+ if (new URL(request.url).searchParams.has('nojs')) return 'async';
427
+ if (CRAWLER.test(request.headers.get('user-agent') ?? '')) return 'async';
428
+ return 'stream';
429
+ }
430
+ ```
431
+
432
+ Hosts driving the handler directly can decide per call instead:
433
+ `handleRequest(request, { renderMode: 'async' })`. Precedence is that
434
+ runtime option, then the module function's result, then the static config;
435
+ an unknown value from any of the three is an error naming its source. The
436
+ mode applies to generated and authored entries alike — an authored
437
+ `render()` returning a `renderToStream` result is awaited the same way (and
438
+ in production its client-entry reference is still rewritten). `httpStatus()` /
439
+ `httpHeader()` declarations survive either mode: the runtime freezes the
440
+ response head when the awaited render completes (`@solidjs/web` 2.0.0-rc.7+),
441
+ just as streaming freezes it at shell flush. Server mode only — in client mode the served shell has no boundaries to
442
+ settle, so the option is a documented no-op there.
443
+
379
444
  **`env`** — first-party typed environment variables. A schema file at the
380
445
  project root — `env.ts` (or `env.js`), probed automatically; point
381
446
  elsewhere with `start: { env: './path' }`, disable with `env: false` —