@kasperrt/smolter 0.3.4 → 0.3.5
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.
|
@@ -96,7 +96,22 @@ export async function mountApplication(
|
|
|
96
96
|
};
|
|
97
97
|
|
|
98
98
|
if (hydration) {
|
|
99
|
-
|
|
99
|
+
// Explicitly unmanaged head nodes must not participate in positional hydration.
|
|
100
|
+
const preserved = Array.from(
|
|
101
|
+
document.head.querySelectorAll(":scope > [data-smolter-preserve]"),
|
|
102
|
+
(node) => ({ node, next: node.nextSibling }),
|
|
103
|
+
);
|
|
104
|
+
for (const { node } of preserved) node.remove();
|
|
105
|
+
|
|
106
|
+
await Promise.resolve()
|
|
107
|
+
.then(() => hydrate(<RouterApplication {...props} document />, document))
|
|
108
|
+
.finally(() => {
|
|
109
|
+
for (const { node, next } of preserved.reverse())
|
|
110
|
+
document.head.insertBefore(
|
|
111
|
+
node,
|
|
112
|
+
next?.parentNode === document.head ? next : null,
|
|
113
|
+
);
|
|
114
|
+
});
|
|
100
115
|
|
|
101
116
|
return router;
|
|
102
117
|
}
|
|
@@ -35,12 +35,12 @@ export function lazyFiles(
|
|
|
35
35
|
function visit(file: string) {
|
|
36
36
|
if (files.has(file)) return;
|
|
37
37
|
|
|
38
|
-
files.add(file);
|
|
39
|
-
|
|
40
38
|
const dependency = bundle[file];
|
|
41
39
|
|
|
42
40
|
if (dependency?.type !== "chunk") return;
|
|
43
41
|
|
|
42
|
+
files.add(file);
|
|
43
|
+
|
|
44
44
|
for (const imported of dependency.imports) visit(imported);
|
|
45
45
|
}
|
|
46
46
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.5
|
|
4
|
+
|
|
5
|
+
- Preserve explicitly unmanaged head elements marked data-smolter-preserve during Preact document hydration, without matching them to application-owned nodes.
|
|
6
|
+
- Test injected script/meta preservation, one-time script execution, styling and subsequent navigation.
|
|
7
|
+
- Add interaction-before/after-deferred-completion assertions and document that streaming does not provide progressive hydration.
|
|
8
|
+
- Fix route asset manifests incorrectly including external module specifiers as preload file URLs; retain transitive emitted chunks and leave optional dynamic imports lazy. No general request-count or latency improvement is claimed.
|
|
9
|
+
|
|
3
10
|
## 0.3.4
|
|
4
11
|
|
|
5
12
|
- Cancel stale deployment checks when newer Back/Forward operations return to the current route, including hash changes.
|
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# smolter _
|
|
2
2
|
|
|
3
3
|
<!-- bundlejs:start -->
|
|
4
|
-
[](https://bundlejs.com/?q=%40kasperrt%2Fsmolter%400.3.5%2Freact&treeshake=%5B*%5D&config=%7B%22compression%22%3A%22gzip%22%2C%22esbuild%22%3A%7B%22external%22%3A%5B%22react%22%2C%22react%2F*%22%5D%7D%7D&bundle)
|
|
5
|
+
[](https://bundlejs.com/?q=%40kasperrt%2Fsmolter%400.3.5%2Fpreact&treeshake=%5B*%5D&config=%7B%22compression%22%3A%22gzip%22%2C%22esbuild%22%3A%7B%22external%22%3A%5B%22preact%22%2C%22preact%2F*%22%5D%7D%7D&bundle)
|
|
6
6
|
<!-- bundlejs:end -->
|
|
7
7
|
|
|
8
8
|
A typed data router for React and Preact. **Zero runtime dependencies.**
|
|
@@ -607,8 +607,8 @@ a claim of identical features.
|
|
|
607
607
|
| `@kasperrt/smolter/preact` | 4842 |
|
|
608
608
|
| `@kasperrt/smolter/react + @kasperrt/smolter/react/client` | 4104 |
|
|
609
609
|
| `@kasperrt/smolter/preact + server transport` | 5950 |
|
|
610
|
-
| `@kasperrt/smolter/preact + client + document (application without lazy routes)` |
|
|
611
|
-
| `@kasperrt/smolter/preact + client + document + lazy-route (file-routed application)` |
|
|
610
|
+
| `@kasperrt/smolter/preact + client + document (application without lazy routes)` | 8607 |
|
|
611
|
+
| `@kasperrt/smolter/preact + client + document + lazy-route (file-routed application)` | 8890 |
|
|
612
612
|
| `@kasperrt/smolter/react/data (optional resource API)` | 2962 |
|
|
613
613
|
| `React: common routing/data exports` | 2761 |
|
|
614
614
|
| `Preact: common routing/data exports` | 3046 |
|
|
@@ -751,3 +751,16 @@ await mountApplication(routes, root, { deployment });
|
|
|
751
751
|
Preact SSR starts root and route loaders concurrently. Return nested promises and render them with `Await` inside `Suspense` to stream a shell before optional data resolves. The Node/Express adapter streams the response; hydration starts after the document stream finishes. Root-loader failures render the root error boundary. Vite development HTML transformation still buffers the document.
|
|
752
752
|
|
|
753
753
|
Successful action redirects refresh registered root data without replaying the mutation. Loader arguments expose `reason` to distinguish initial loads, navigation, revalidation and fetcher reads without comparing browser URLs.
|
|
754
|
+
|
|
755
|
+
|
|
756
|
+
### Document hydration and injected tags
|
|
757
|
+
|
|
758
|
+
Preact hydrates the complete document after the response finishes. A streamed shell is visible before optional data settles, but event handlers are not active yet. Measure a successful interaction rather than treating TTFB or DOMContentLoaded as hydration completion.
|
|
759
|
+
|
|
760
|
+
Infrastructure that injects direct children of `<head>` can mark those external nodes with `data-smolter-preserve`. Smolter excludes them from positional hydration and restores the same nodes afterward. Do not also render them in the application layout. Unmarked HTML rewriting, body injection and changes to the hydration payload are not supported.
|
|
761
|
+
|
|
762
|
+
```html
|
|
763
|
+
<script data-smolter-preserve src="/infrastructure-instrumentation.js"></script>
|
|
764
|
+
```
|
|
765
|
+
|
|
766
|
+
The generated route asset manifest follows static imports for each route and leaves optional dynamic imports lazy. Serve the matched route's preload hints with the correct asset base; do not preload every route to reduce a waterfall. Chunk counts and total emitted bytes alone do not establish initial-load latency.
|
package/dist/preact/client.js
CHANGED
|
@@ -50,10 +50,17 @@ async function mountApplication(routes, rootModule, options = false) {
|
|
|
50
50
|
rootError: hydration?.rootError
|
|
51
51
|
};
|
|
52
52
|
if (hydration) {
|
|
53
|
-
|
|
53
|
+
const preserved = Array.from(document.head.querySelectorAll(":scope > [data-smolter-preserve]"), (node) => ({
|
|
54
|
+
node,
|
|
55
|
+
next: node.nextSibling
|
|
56
|
+
}));
|
|
57
|
+
for (const { node } of preserved) node.remove();
|
|
58
|
+
await Promise.resolve().then(() => hydrate(/* @__PURE__ */ jsx(RouterApplication, {
|
|
54
59
|
...props,
|
|
55
60
|
document: true
|
|
56
|
-
}), document)
|
|
61
|
+
}), document)).finally(() => {
|
|
62
|
+
for (const { node, next } of preserved.reverse()) document.head.insertBefore(node, next?.parentNode === document.head ? next : null);
|
|
63
|
+
});
|
|
57
64
|
return router;
|
|
58
65
|
}
|
|
59
66
|
const target = document.getElementById("root");
|
|
@@ -22,9 +22,9 @@ function lazyFiles(directory, dataEndpoint = "/_smolter") {
|
|
|
22
22
|
const files = /* @__PURE__ */ new Set();
|
|
23
23
|
function visit(file) {
|
|
24
24
|
if (files.has(file)) return;
|
|
25
|
-
files.add(file);
|
|
26
25
|
const dependency = bundle[file];
|
|
27
26
|
if (dependency?.type !== "chunk") return;
|
|
27
|
+
files.add(file);
|
|
28
28
|
for (const imported of dependency.imports) visit(imported);
|
|
29
29
|
}
|
|
30
30
|
visit(chunk.fileName);
|
package/jsr.json
CHANGED