streetui 1.6.0 → 1.6.1
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/dist/bin.cjs +1 -1
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/bin.js.map +1 -1
- package/dist/create-bin.cjs +1 -1
- package/dist/create-bin.cjs.map +1 -1
- package/dist/create-bin.js +1 -1
- package/dist/create-bin.js.map +1 -1
- package/dist/index.cjs +139 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -6
- package/dist/index.d.ts +35 -6
- package/dist/index.js +138 -3
- package/dist/index.js.map +1 -1
- package/dist/{server-C2xovHHb.d.cts → server-ZBh5DO-z.d.cts} +26 -0
- package/dist/{server-xU-BEwAj.d.ts → server-jbB-7oN-.d.ts} +26 -0
- package/dist/server.cjs +137 -3
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +137 -3
- package/dist/server.js.map +1 -1
- package/dist/testing.cjs +189 -109
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.js +189 -109
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
|
@@ -11,6 +11,13 @@ interface DOMAdapter {
|
|
|
11
11
|
createTextNode(data: string): Text;
|
|
12
12
|
createComment(data: string): Comment;
|
|
13
13
|
createFragment(): DocumentFragment;
|
|
14
|
+
/**
|
|
15
|
+
* Optional, server-only: create a verbatim pre-serialized HTML node used by
|
|
16
|
+
* the v1.7 static SSR plan. The browser adapter does not implement it; the
|
|
17
|
+
* renderer only calls it when a static SSR plan is active (i.e. during SSR),
|
|
18
|
+
* so client builds never reach this path and it stays tree-shakeable.
|
|
19
|
+
*/
|
|
20
|
+
createRawHTML?(html: string): Node;
|
|
14
21
|
appendChild(parent: Node, child: Node): void;
|
|
15
22
|
insertBefore(parent: Node, child: Node, reference: Node | null): void;
|
|
16
23
|
removeChild(parent: Node, child: Node): void;
|
|
@@ -62,6 +69,13 @@ declare class ServerDOMAdapter implements DOMAdapter {
|
|
|
62
69
|
createTextNode(data: string): Text;
|
|
63
70
|
createComment(data: string): Comment;
|
|
64
71
|
createFragment(): DocumentFragment;
|
|
72
|
+
/**
|
|
73
|
+
* Create a verbatim pre-serialized HTML node (v1.7 static SSR plan, §6).
|
|
74
|
+
* Server-only: the browser adapter does not implement this, and the renderer
|
|
75
|
+
* fast path only invokes it when a static SSR plan is present (SSR). The
|
|
76
|
+
* stored HTML was produced by this same serializer, so it is emitted as-is.
|
|
77
|
+
*/
|
|
78
|
+
createRawHTML(html: string): Node;
|
|
65
79
|
appendChild(parent: Node, child: Node): void;
|
|
66
80
|
insertBefore(parent: Node, child: Node, reference: Node | null): void;
|
|
67
81
|
removeChild(parent: Node, child: Node): void;
|
|
@@ -152,6 +166,18 @@ interface RenderToStringOptions {
|
|
|
152
166
|
* `ServerDOMAdapter` per call so concurrent renders never share state.
|
|
153
167
|
*/
|
|
154
168
|
readonly domAdapter?: ServerDOMAdapter;
|
|
169
|
+
/**
|
|
170
|
+
* @internal — testing/benchmark knob for the v1.7 static SSR plan.
|
|
171
|
+
*
|
|
172
|
+
* `undefined` (default): use the per-app cached plan (build once, reuse).
|
|
173
|
+
* `null`: disable the plan entirely — the exact v1.6 runtime mount path, used
|
|
174
|
+
* by the byte-identity gate and A/B benchmark as the "legacy" baseline.
|
|
175
|
+
* a map: use this explicit plan.
|
|
176
|
+
*
|
|
177
|
+
* Not part of the supported public API; output is byte-identical regardless
|
|
178
|
+
* of this value (§8).
|
|
179
|
+
*/
|
|
180
|
+
readonly staticPlan?: ReadonlyMap<string, string> | null;
|
|
155
181
|
}
|
|
156
182
|
/**
|
|
157
183
|
* Render a compiled StreetUI application to an HTML string.
|
|
@@ -11,6 +11,13 @@ interface DOMAdapter {
|
|
|
11
11
|
createTextNode(data: string): Text;
|
|
12
12
|
createComment(data: string): Comment;
|
|
13
13
|
createFragment(): DocumentFragment;
|
|
14
|
+
/**
|
|
15
|
+
* Optional, server-only: create a verbatim pre-serialized HTML node used by
|
|
16
|
+
* the v1.7 static SSR plan. The browser adapter does not implement it; the
|
|
17
|
+
* renderer only calls it when a static SSR plan is active (i.e. during SSR),
|
|
18
|
+
* so client builds never reach this path and it stays tree-shakeable.
|
|
19
|
+
*/
|
|
20
|
+
createRawHTML?(html: string): Node;
|
|
14
21
|
appendChild(parent: Node, child: Node): void;
|
|
15
22
|
insertBefore(parent: Node, child: Node, reference: Node | null): void;
|
|
16
23
|
removeChild(parent: Node, child: Node): void;
|
|
@@ -62,6 +69,13 @@ declare class ServerDOMAdapter implements DOMAdapter {
|
|
|
62
69
|
createTextNode(data: string): Text;
|
|
63
70
|
createComment(data: string): Comment;
|
|
64
71
|
createFragment(): DocumentFragment;
|
|
72
|
+
/**
|
|
73
|
+
* Create a verbatim pre-serialized HTML node (v1.7 static SSR plan, §6).
|
|
74
|
+
* Server-only: the browser adapter does not implement this, and the renderer
|
|
75
|
+
* fast path only invokes it when a static SSR plan is present (SSR). The
|
|
76
|
+
* stored HTML was produced by this same serializer, so it is emitted as-is.
|
|
77
|
+
*/
|
|
78
|
+
createRawHTML(html: string): Node;
|
|
65
79
|
appendChild(parent: Node, child: Node): void;
|
|
66
80
|
insertBefore(parent: Node, child: Node, reference: Node | null): void;
|
|
67
81
|
removeChild(parent: Node, child: Node): void;
|
|
@@ -152,6 +166,18 @@ interface RenderToStringOptions {
|
|
|
152
166
|
* `ServerDOMAdapter` per call so concurrent renders never share state.
|
|
153
167
|
*/
|
|
154
168
|
readonly domAdapter?: ServerDOMAdapter;
|
|
169
|
+
/**
|
|
170
|
+
* @internal — testing/benchmark knob for the v1.7 static SSR plan.
|
|
171
|
+
*
|
|
172
|
+
* `undefined` (default): use the per-app cached plan (build once, reuse).
|
|
173
|
+
* `null`: disable the plan entirely — the exact v1.6 runtime mount path, used
|
|
174
|
+
* by the byte-identity gate and A/B benchmark as the "legacy" baseline.
|
|
175
|
+
* a map: use this explicit plan.
|
|
176
|
+
*
|
|
177
|
+
* Not part of the supported public API; output is byte-identical regardless
|
|
178
|
+
* of this value (§8).
|
|
179
|
+
*/
|
|
180
|
+
readonly staticPlan?: ReadonlyMap<string, string> | null;
|
|
155
181
|
}
|
|
156
182
|
/**
|
|
157
183
|
* Render a compiled StreetUI application to an HTML string.
|
package/dist/server.cjs
CHANGED
|
@@ -30,13 +30,14 @@ __export(server_exports, {
|
|
|
30
30
|
module.exports = __toCommonJS(server_exports);
|
|
31
31
|
|
|
32
32
|
// ../renderer/src/render-context.ts
|
|
33
|
-
function createRenderContext(dom, graph, container, hydrationDiagnostics) {
|
|
33
|
+
function createRenderContext(dom, graph, container, hydrationDiagnostics, staticHTML) {
|
|
34
34
|
return {
|
|
35
35
|
dom,
|
|
36
36
|
graph,
|
|
37
37
|
instances: /* @__PURE__ */ new Map(),
|
|
38
38
|
container,
|
|
39
|
-
...hydrationDiagnostics !== void 0 ? { hydrationDiagnostics } : {}
|
|
39
|
+
...hydrationDiagnostics !== void 0 ? { hydrationDiagnostics } : {},
|
|
40
|
+
...staticHTML !== void 0 ? { staticHTML } : {}
|
|
40
41
|
};
|
|
41
42
|
}
|
|
42
43
|
|
|
@@ -481,6 +482,17 @@ function mountGraph(ctx) {
|
|
|
481
482
|
}
|
|
482
483
|
function mountNode(ctx, graphNode, parentDom) {
|
|
483
484
|
const { dom, graph } = ctx;
|
|
485
|
+
const staticHTML = ctx.staticHTML;
|
|
486
|
+
if (staticHTML !== void 0 && dom.createRawHTML !== void 0) {
|
|
487
|
+
const precomputed = staticHTML.get(graphNode.id);
|
|
488
|
+
if (precomputed !== void 0) {
|
|
489
|
+
const raw = dom.createRawHTML(precomputed);
|
|
490
|
+
dom.appendChild(parentDom, raw);
|
|
491
|
+
const instance2 = new NodeInstance(graphNode, raw);
|
|
492
|
+
ctx.instances.set(graphNode.id, instance2);
|
|
493
|
+
return instance2;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
484
496
|
if (graphNode.type === "application") {
|
|
485
497
|
const instance2 = new NodeInstance(graphNode, parentDom);
|
|
486
498
|
ctx.instances.set(graphNode.id, instance2);
|
|
@@ -787,6 +799,14 @@ var ServerFragment = class {
|
|
|
787
799
|
parent = null;
|
|
788
800
|
children = [];
|
|
789
801
|
};
|
|
802
|
+
var ServerRawHTML = class {
|
|
803
|
+
kind = "raw";
|
|
804
|
+
parent = null;
|
|
805
|
+
html;
|
|
806
|
+
constructor(html) {
|
|
807
|
+
this.html = html;
|
|
808
|
+
}
|
|
809
|
+
};
|
|
790
810
|
var ServerElement = class {
|
|
791
811
|
kind = "element";
|
|
792
812
|
parent = null;
|
|
@@ -937,6 +957,8 @@ function serializeServerNode(node) {
|
|
|
937
957
|
return `<!--${node.data}-->`;
|
|
938
958
|
case "fragment":
|
|
939
959
|
return serializeChildren(node);
|
|
960
|
+
case "raw":
|
|
961
|
+
return node.html;
|
|
940
962
|
case "element": {
|
|
941
963
|
const el = node;
|
|
942
964
|
const tag = el.tagName;
|
|
@@ -976,6 +998,15 @@ var ServerDOMAdapter = class {
|
|
|
976
998
|
createFragment() {
|
|
977
999
|
return new ServerFragment();
|
|
978
1000
|
}
|
|
1001
|
+
/**
|
|
1002
|
+
* Create a verbatim pre-serialized HTML node (v1.7 static SSR plan, §6).
|
|
1003
|
+
* Server-only: the browser adapter does not implement this, and the renderer
|
|
1004
|
+
* fast path only invokes it when a static SSR plan is present (SSR). The
|
|
1005
|
+
* stored HTML was produced by this same serializer, so it is emitted as-is.
|
|
1006
|
+
*/
|
|
1007
|
+
createRawHTML(html) {
|
|
1008
|
+
return new ServerRawHTML(html);
|
|
1009
|
+
}
|
|
979
1010
|
appendChild(parent, child) {
|
|
980
1011
|
const p = asParent(parent);
|
|
981
1012
|
const c = asServer(child);
|
|
@@ -1163,11 +1194,114 @@ function readState(dom, root) {
|
|
|
1163
1194
|
}
|
|
1164
1195
|
}
|
|
1165
1196
|
|
|
1197
|
+
// ../compiler/dist/diagnostics.js
|
|
1198
|
+
var TEXT_PROP_KEYS = /* @__PURE__ */ new Set(["text", "label", "value"]);
|
|
1199
|
+
function analyzeGraph(graph) {
|
|
1200
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
1201
|
+
const summary = {
|
|
1202
|
+
totalNodes: 0,
|
|
1203
|
+
staticNodes: 0,
|
|
1204
|
+
staticSubtrees: 0,
|
|
1205
|
+
dynamicTextNodes: 0,
|
|
1206
|
+
dynamicAttrNodes: 0,
|
|
1207
|
+
eventNodes: 0,
|
|
1208
|
+
lists: 0,
|
|
1209
|
+
conditionals: 0
|
|
1210
|
+
};
|
|
1211
|
+
const visit = (node) => {
|
|
1212
|
+
let allChildrenStatic = true;
|
|
1213
|
+
for (const child of node.children) {
|
|
1214
|
+
const childSubtreeStatic = visit(child);
|
|
1215
|
+
if (!childSubtreeStatic) allChildrenStatic = false;
|
|
1216
|
+
}
|
|
1217
|
+
let hasDynamicText = false;
|
|
1218
|
+
let hasDynamicAttr = false;
|
|
1219
|
+
for (const ref of node.stateRefs) {
|
|
1220
|
+
if (TEXT_PROP_KEYS.has(ref.propKey)) hasDynamicText = true;
|
|
1221
|
+
else hasDynamicAttr = true;
|
|
1222
|
+
}
|
|
1223
|
+
const hasEvents = node.events.length > 0;
|
|
1224
|
+
const isList = node.type === "reactive-list";
|
|
1225
|
+
const isConditional = node.type === "conditional";
|
|
1226
|
+
const isStatic = node.stateRefs.length === 0 && !hasEvents && !isList && !isConditional;
|
|
1227
|
+
const isStaticSubtree = isStatic && allChildrenStatic;
|
|
1228
|
+
nodes.set(node.id, {
|
|
1229
|
+
isStatic,
|
|
1230
|
+
isStaticSubtree,
|
|
1231
|
+
hasDynamicText,
|
|
1232
|
+
hasDynamicAttr,
|
|
1233
|
+
hasEvents,
|
|
1234
|
+
isList,
|
|
1235
|
+
isConditional
|
|
1236
|
+
});
|
|
1237
|
+
summary.totalNodes += 1;
|
|
1238
|
+
if (isStatic) summary.staticNodes += 1;
|
|
1239
|
+
if (isStaticSubtree) summary.staticSubtrees += 1;
|
|
1240
|
+
if (hasDynamicText) summary.dynamicTextNodes += 1;
|
|
1241
|
+
if (hasDynamicAttr) summary.dynamicAttrNodes += 1;
|
|
1242
|
+
if (hasEvents) summary.eventNodes += 1;
|
|
1243
|
+
if (isList) summary.lists += 1;
|
|
1244
|
+
if (isConditional) summary.conditionals += 1;
|
|
1245
|
+
return isStaticSubtree;
|
|
1246
|
+
};
|
|
1247
|
+
visit(graph.root);
|
|
1248
|
+
return { nodes, summary };
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
// ../renderer/src/static-ssr-plan.ts
|
|
1252
|
+
function collectMaximalStaticRoots(graph) {
|
|
1253
|
+
const analysis = analyzeGraph(graph);
|
|
1254
|
+
const roots = [];
|
|
1255
|
+
const walk = (node) => {
|
|
1256
|
+
if (node.type !== "application") {
|
|
1257
|
+
const a = analysis.nodes.get(node.id);
|
|
1258
|
+
if (a !== void 0 && a.isStaticSubtree) {
|
|
1259
|
+
roots.push(node);
|
|
1260
|
+
return;
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
for (const child of node.children) walk(child);
|
|
1264
|
+
};
|
|
1265
|
+
walk(graph.root);
|
|
1266
|
+
return roots;
|
|
1267
|
+
}
|
|
1268
|
+
function serializeStaticSubtree(dom, graph, root) {
|
|
1269
|
+
const container = dom.createElement("div");
|
|
1270
|
+
const ctx = createRenderContext(dom, graph, container);
|
|
1271
|
+
const instance = mountNode(ctx, root, container);
|
|
1272
|
+
const html = dom.serializeInner(container);
|
|
1273
|
+
instance.dispose();
|
|
1274
|
+
ctx.instances.clear();
|
|
1275
|
+
return html;
|
|
1276
|
+
}
|
|
1277
|
+
function buildStaticSSRPlan(compiled) {
|
|
1278
|
+
const graph = compiled.graph;
|
|
1279
|
+
const roots = collectMaximalStaticRoots(graph);
|
|
1280
|
+
const plan = /* @__PURE__ */ new Map();
|
|
1281
|
+
if (roots.length === 0) return plan;
|
|
1282
|
+
const dom = new ServerDOMAdapter();
|
|
1283
|
+
for (const root of roots) {
|
|
1284
|
+
plan.set(root.id, serializeStaticSubtree(dom, graph, root));
|
|
1285
|
+
}
|
|
1286
|
+
return plan;
|
|
1287
|
+
}
|
|
1288
|
+
var PLAN_CACHE = /* @__PURE__ */ new WeakMap();
|
|
1289
|
+
function getStaticSSRPlan(compiled) {
|
|
1290
|
+
let plan = PLAN_CACHE.get(compiled);
|
|
1291
|
+
if (plan === void 0) {
|
|
1292
|
+
plan = buildStaticSSRPlan(compiled);
|
|
1293
|
+
PLAN_CACHE.set(compiled, plan);
|
|
1294
|
+
}
|
|
1295
|
+
return plan;
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1166
1298
|
// ../renderer/src/ssr.ts
|
|
1167
1299
|
function renderToString(compiled, options = {}) {
|
|
1168
1300
|
const dom = options.domAdapter ?? new ServerDOMAdapter();
|
|
1301
|
+
const plan = options.staticPlan === null ? void 0 : options.staticPlan ?? getStaticSSRPlan(compiled);
|
|
1302
|
+
const staticHTML = plan !== void 0 && plan.size > 0 ? plan : void 0;
|
|
1169
1303
|
const container = dom.createElement("div");
|
|
1170
|
-
const ctx = createRenderContext(dom, compiled.graph, container);
|
|
1304
|
+
const ctx = createRenderContext(dom, compiled.graph, container, void 0, staticHTML);
|
|
1171
1305
|
const rootInstance = mountGraph(ctx);
|
|
1172
1306
|
const html = dom.serializeInner(container);
|
|
1173
1307
|
rootInstance.dispose();
|