@fictjs/ssr 0.27.0 → 0.28.0

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
@@ -1,6 +1,13 @@
1
1
  # @fictjs/ssr
2
2
 
3
- Fict's Server-Side Rendering (SSR) package, providing high-performance server-side rendering and client-side resumability capabilities.
3
+ Fict's Satellite Server-Side Rendering (SSR) package, providing supported
4
+ string and streaming rendering plus opt-in client resumability.
5
+
6
+ > **Preview** — resumability, snapshot schema v2, and partial prerendering have no
7
+ > semver guarantee and are excluded from Core 1.0. They require
8
+ > `includeSnapshot: true`, compiler `resumable: true`, and the
9
+ > `fict/experimental/loader` entrypoint. Basic string and streaming SSR does not
10
+ > enable them by default.
4
11
 
5
12
  ## Table of Contents
6
13
 
@@ -20,7 +27,9 @@ Fict's Server-Side Rendering (SSR) package, providing high-performance server-si
20
27
 
21
28
  ## Overview
22
29
 
23
- Fict SSR adopts a **Resumability** architecture, which is fundamentally different from traditional Hydration:
30
+ Supported SSR produces HTML without a resumability snapshot by default. The
31
+ optional **Preview Resumability** architecture is fundamentally different from
32
+ traditional hydration:
24
33
 
25
34
  | Feature | Traditional Hydration | Fict Resumability |
26
35
  | ------------------------- | --------------------------------- | --------------------------------- |
@@ -29,7 +38,7 @@ Fict SSR adopts a **Resumability** architecture, which is fundamentally differen
29
38
  | Handler Loading | All preloaded | Lazy loaded on demand |
30
39
  | State Restoration | Re-calculated | Restored from serialized snapshot |
31
40
 
32
- ### How it Works
41
+ ### How Preview Resumability Works
33
42
 
34
43
  ```
35
44
  ┌─────────────────────────────────────────────────────────────────┐
@@ -79,7 +88,7 @@ import { renderToString } from '@fictjs/ssr'
79
88
  import { App } from './App'
80
89
 
81
90
  const html = renderToString(() => <App />, {
82
- includeSnapshot: true, // Include state snapshot (default true)
91
+ includeSnapshot: true, // Explicit Preview snapshot opt-in (default false)
83
92
  containerId: 'app',
84
93
  manifest: './dist/client/fict.manifest.json',
85
94
  })
@@ -90,7 +99,7 @@ const html = renderToString(() => <App />, {
90
99
  ```typescript
91
100
  // entry-client.tsx
92
101
  import { render } from 'fict'
93
- import { installResumableLoader } from 'fict/loader'
102
+ import { installResumableLoader } from 'fict/experimental/loader'
94
103
  import { App } from './App'
95
104
 
96
105
  // Load manifest (production)
@@ -285,7 +294,7 @@ interface RenderToStringOptions {
285
294
  doctype?: string | null
286
295
 
287
296
  // Resumability Configuration
288
- includeSnapshot?: boolean // Default: true
297
+ includeSnapshot?: boolean // Preview opt-in; default: false
289
298
  snapshotScriptId?: string // Default: '__FICT_SNAPSHOT__'
290
299
  snapshotTarget?: 'container' | 'body' | 'head'
291
300
 
@@ -299,7 +308,11 @@ By default SSR does not write `window`, `document`, `Node`, or related DOM const
299
308
  `globalThis`. This keeps concurrent renders from racing over process-global DOM state. Components
300
309
  should use Fict's render-provided document/ownerDocument paths; set `exposeGlobals: true` only for
301
310
  legacy code that still reads DOM globals during server render. That compatibility mode is restored
302
- on `dispose()`, but it is not concurrency-safe while overlapping renders are active.
311
+ on `dispose()`. Default renders may overlap each other, but a compatibility render is exclusive
312
+ with every other SSR render so no request can observe another request's process-global DOM. On a
313
+ non-extensible hardened global object, ordinary render-local SSR remains available without a
314
+ process marker; compatibility mode remains unavailable because it cannot acquire its exclusive
315
+ lease or install DOM globals.
303
316
 
304
317
  ### renderToStringAsync
305
318
 
@@ -367,6 +380,11 @@ Trusted Types deployments should use this external observer runtime. The patch
367
380
  runtime moves `<template>` content with DOM APIs (`content` + `insertBefore`) and
368
381
  does not call `innerHTML`, `insertAdjacentHTML`, `eval`, or `Function`.
369
382
 
383
+ When Preview snapshots are enabled on a nonce-free strict-CSP route, keep
384
+ `snapshotTarget` at `container` or `body`. Incremental `head` snapshots require a
385
+ small executable mover; external runtime mode rejects that combination unless
386
+ `scriptNonce` is non-empty.
387
+
370
388
  Each shell stream receives an automatic unique namespace for its Suspense patch
371
389
  identifiers. When independently cached fragments or streams from multiple
372
390
  services can be composed into one document, pass a stable
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fictjs/ssr",
3
- "version": "0.27.0",
3
+ "version": "0.28.0",
4
4
  "description": "Fict server-side rendering",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -46,11 +46,11 @@
46
46
  ],
47
47
  "dependencies": {
48
48
  "linkedom": "^0.18.12",
49
- "@fictjs/runtime": "0.27.0"
49
+ "@fictjs/runtime": "0.28.0"
50
50
  },
51
51
  "devDependencies": {
52
52
  "tsdown": "^0.22.3",
53
- "fict": "0.27.0"
53
+ "fict": "0.28.0"
54
54
  },
55
55
  "keywords": [
56
56
  "fict",
@@ -1,3 +0,0 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_render_core = require("./render-core-D_EheVwh.cjs");
3
- exports.renderToPartial = require_render_core.renderToPartial;
@@ -1,2 +0,0 @@
1
- import { l as renderToPartial, t as PartialPrerenderResult } from "./render-core-KCiJV_SK.cjs";
2
- export { type PartialPrerenderResult, renderToPartial };
@@ -1,2 +0,0 @@
1
- import { l as renderToPartial, t as PartialPrerenderResult } from "./render-core-KCiJV_SK.js";
2
- export { type PartialPrerenderResult, renderToPartial };
@@ -1,2 +0,0 @@
1
- import { r as renderToPartial } from "./render-core-D0nOT_Pe.js";
2
- export { renderToPartial };
@@ -1,5 +0,0 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_render_core = require("./render-core-D_EheVwh.cjs");
3
- require("./node-session-carrier-CTo-1Awq.cjs");
4
- require("./experimental.cjs");
5
- exports.renderToPartial = require_render_core.renderToPartial;
@@ -1,2 +0,0 @@
1
- import { l as renderToPartial, t as PartialPrerenderResult } from "./render-core-KCiJV_SK.cjs";
2
- export { type PartialPrerenderResult, renderToPartial };
@@ -1,2 +0,0 @@
1
- import { l as renderToPartial, t as PartialPrerenderResult } from "./render-core-KCiJV_SK.js";
2
- export { type PartialPrerenderResult, renderToPartial };
@@ -1,4 +0,0 @@
1
- import { r as renderToPartial } from "./render-core-D0nOT_Pe.js";
2
- import "./node-session-carrier-ClqRbdoQ.js";
3
- import "./experimental.js";
4
- export { renderToPartial };
@@ -1 +0,0 @@
1
- (function(){var runtime=window.__FICT_STREAM;function walk(root,visit){var stack=[root];while(stack.length){var node=stack.pop();if(visit(node)===false)return false;var container=node.nodeType===1&&node.localName==="template"&&node.content?node.content:node;for(var child=container.lastChild;child;child=child.previousSibling)stack.push(child);}return true;}if(!runtime||typeof runtime.apply!=="function"){var cache=new Map();function findTemplate(id){var tpl=null;walk(document,function(n){if(n.nodeType===1&&n.localName==="template"&&n.content&&n.getAttribute("data-fict-suspense")===id){tpl=n;return false;}});return tpl;}function find(id){var hit=cache.get(id);if(hit)return hit;var startMarker="fict:suspense-start:"+id,endMarker="fict:suspense-end:"+id;walk(document,function(n){if(n.nodeType!==8||n.data!==startMarker)return;var end=n.nextSibling;while(end&&(end.nodeType!==8||end.data!==endMarker))end=end.nextSibling;if(end){hit={start:n,end:end};return false;}});if(hit)cache.set(id,hit);return hit;}function apply(id){if(typeof id!=="string"||!id)return;var tpl=findTemplate(id);if(!tpl)return;var b=find(id);if(!b)return;var parent=b.start.parentNode;if(!parent||b.end.parentNode!==parent)return;var cursor=b.start.nextSibling;while(cursor&&cursor!==b.end)cursor=cursor.nextSibling;if(cursor!==b.end)return;var content=tpl.content;var ns=tpl.getAttribute("data-fict-patch-namespace");if(ns){var tag=ns==="svg"?"svg":ns==="mathml"?"math":null;var wrapper=content.firstElementChild;if(!tag||!wrapper||wrapper.localName!==tag)return;var fragment=document.createDocumentFragment();while(wrapper.firstChild)fragment.appendChild(wrapper.firstChild);content=fragment;}var node=b.start.nextSibling;while(node&&node!==b.end){var next=node.nextSibling;node.parentNode&&node.parentNode.removeChild(node);node=next;}parent.insertBefore(content,b.end);tpl.parentNode&&tpl.parentNode.removeChild(tpl);}runtime={apply:apply};window.__FICT_STREAM=runtime;}if(runtime.observerInstalled)return;runtime.observerInstalled=true;function scan(root){var ids=[];walk(root,function(n){if(n.nodeType===1&&n.localName==="template"&&n.content&&n.hasAttribute("data-fict-suspense")){var id=n.getAttribute("data-fict-suspense");if(id)ids.push(id);}});for(var i=0;i<ids.length;i++)runtime.apply(ids[i]);}if(typeof MutationObserver==="function"){new MutationObserver(function(muts){for(var i=0;i<muts.length;i++){for(var j=0;j<muts[i].addedNodes.length;j++){var n=muts[i].addedNodes[j];if(n.nodeType===1)scan(n);}}}).observe(document.documentElement||document,{childList:true,subtree:true});}if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",function(){scan(document);},{once:true});}else{scan(document);}})();
package/dist/index.cjs DELETED
@@ -1,8 +0,0 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_render_core = require("./render-core-D_EheVwh.cjs");
3
- exports.createSSRDocument = require_render_core.createSSRDocument;
4
- exports.renderToDocument = require_render_core.renderToDocument;
5
- exports.renderToPipeableStream = require_render_core.renderToPipeableStream;
6
- exports.renderToStream = require_render_core.renderToStream;
7
- exports.renderToString = require_render_core.renderToString;
8
- exports.renderToStringAsync = require_render_core.renderToStringAsync;
package/dist/index.d.cts DELETED
@@ -1,2 +0,0 @@
1
- import { a as RenderToStringOptions, c as renderToDocument, d as renderToStream, f as renderToString, i as RenderToStreamOptions, n as PipeableStream, o as SSRDom, p as renderToStringAsync, r as RenderToDocumentResult, s as createSSRDocument, u as renderToPipeableStream } from "./render-core-KCiJV_SK.cjs";
2
- export { type PipeableStream, type RenderToDocumentResult, type RenderToStreamOptions, type RenderToStringOptions, type SSRDom, createSSRDocument, renderToDocument, renderToPipeableStream, renderToStream, renderToString, renderToStringAsync };
package/dist/index.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import { a as RenderToStringOptions, c as renderToDocument, d as renderToStream, f as renderToString, i as RenderToStreamOptions, n as PipeableStream, o as SSRDom, p as renderToStringAsync, r as RenderToDocumentResult, s as createSSRDocument, u as renderToPipeableStream } from "./render-core-KCiJV_SK.js";
2
- export { type PipeableStream, type RenderToDocumentResult, type RenderToStreamOptions, type RenderToStringOptions, type SSRDom, createSSRDocument, renderToDocument, renderToPipeableStream, renderToStream, renderToString, renderToStringAsync };
package/dist/index.js DELETED
@@ -1,2 +0,0 @@
1
- import { a as renderToStream, i as renderToPipeableStream, n as renderToDocument, o as renderToString, s as renderToStringAsync, t as createSSRDocument } from "./render-core-D0nOT_Pe.js";
2
- export { createSSRDocument, renderToDocument, renderToPipeableStream, renderToStream, renderToString, renderToStringAsync };
@@ -1,10 +0,0 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_render_core = require("./render-core-D_EheVwh.cjs");
3
- require("./index.cjs");
4
- require("./node-session-carrier-CTo-1Awq.cjs");
5
- exports.createSSRDocument = require_render_core.createSSRDocument;
6
- exports.renderToDocument = require_render_core.renderToDocument;
7
- exports.renderToPipeableStream = require_render_core.renderToPipeableStream;
8
- exports.renderToStream = require_render_core.renderToStream;
9
- exports.renderToString = require_render_core.renderToString;
10
- exports.renderToStringAsync = require_render_core.renderToStringAsync;
@@ -1,2 +0,0 @@
1
- import { a as RenderToStringOptions, c as renderToDocument, d as renderToStream, f as renderToString, i as RenderToStreamOptions, n as PipeableStream, o as SSRDom, p as renderToStringAsync, r as RenderToDocumentResult, s as createSSRDocument, u as renderToPipeableStream } from "./render-core-KCiJV_SK.cjs";
2
- export { type PipeableStream, type RenderToDocumentResult, type RenderToStreamOptions, type RenderToStringOptions, type SSRDom, createSSRDocument, renderToDocument, renderToPipeableStream, renderToStream, renderToString, renderToStringAsync };
@@ -1,2 +0,0 @@
1
- import { a as RenderToStringOptions, c as renderToDocument, d as renderToStream, f as renderToString, i as RenderToStreamOptions, n as PipeableStream, o as SSRDom, p as renderToStringAsync, r as RenderToDocumentResult, s as createSSRDocument, u as renderToPipeableStream } from "./render-core-KCiJV_SK.js";
2
- export { type PipeableStream, type RenderToDocumentResult, type RenderToStreamOptions, type RenderToStringOptions, type SSRDom, createSSRDocument, renderToDocument, renderToPipeableStream, renderToStream, renderToString, renderToStringAsync };
@@ -1,4 +0,0 @@
1
- import { a as renderToStream, i as renderToPipeableStream, n as renderToDocument, o as renderToString, s as renderToStringAsync, t as createSSRDocument } from "./render-core-D0nOT_Pe.js";
2
- import "./index.js";
3
- import "./node-session-carrier-ClqRbdoQ.js";
4
- export { createSSRDocument, renderToDocument, renderToPipeableStream, renderToStream, renderToString, renderToStringAsync };
@@ -1,8 +0,0 @@
1
- let _fictjs_runtime_internal = require("@fictjs/runtime/internal");
2
- //#region src/node-session-carrier.ts
3
- const sessionStorage = new (require("node:async_hooks")).AsyncLocalStorage();
4
- (0, _fictjs_runtime_internal.__fictInstallSSRSessionCarrier)({
5
- getStore: () => sessionStorage.getStore(),
6
- run: (session, fn) => sessionStorage.run(session, fn)
7
- });
8
- //#endregion
@@ -1,12 +0,0 @@
1
- import { __fictInstallSSRSessionCarrier } from "@fictjs/runtime/internal";
2
- import { AsyncLocalStorage } from "node:async_hooks";
3
- //#region src/node-session-carrier.ts
4
- const sessionStorage = new AsyncLocalStorage();
5
- __fictInstallSSRSessionCarrier({
6
- getStore: () => sessionStorage.getStore(),
7
- run: (session, fn) => sessionStorage.run(session, fn)
8
- });
9
- //#endregion
10
- export {};
11
-
12
- //# sourceMappingURL=node-session-carrier-ClqRbdoQ.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"node-session-carrier-ClqRbdoQ.js","names":[],"sources":["../src/node-session-carrier.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\n\nimport { __fictInstallSSRSessionCarrier, type FictSSRSession } from '@fictjs/runtime/internal'\n\nconst sessionStorage = new AsyncLocalStorage<FictSSRSession>()\n\n__fictInstallSSRSessionCarrier({\n getStore: () => sessionStorage.getStore(),\n run: (session, fn) => sessionStorage.run(session, fn),\n})\n"],"mappings":";;;AAIA,MAAM,iBAAiB,IAAI,kBAAkC;AAE7D,+BAA+B;CAC7B,gBAAgB,eAAe,SAAS;CACxC,MAAM,SAAS,OAAO,eAAe,IAAI,SAAS,EAAE;AACtD,CAAC"}