@decocms/start 0.30.1 → 0.30.3
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/package.json +1 -1
- package/src/cms/resolve.ts +6 -4
- package/src/sdk/analytics.ts +6 -1
- package/src/sdk/workerEntry.ts +22 -0
- package/src/vite/plugin.js +36 -0
package/package.json
CHANGED
package/src/cms/resolve.ts
CHANGED
|
@@ -228,10 +228,12 @@ if (!G.__deco._builtinMatchersRegistered) {
|
|
|
228
228
|
"website/matchers/never.ts": () => false,
|
|
229
229
|
"website/matchers/device.ts": (rule, ctx) => {
|
|
230
230
|
const ua = (ctx.userAgent || "").toLowerCase();
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
231
|
+
const isTablet = /ipad|android(?!.*mobile)|tablet/i.test(ua);
|
|
232
|
+
const isMobile = !isTablet && /mobile|android|iphone|ipod|webos|blackberry|opera mini|iemobile/i.test(ua);
|
|
233
|
+
const isDesktop = !isMobile && !isTablet;
|
|
234
|
+
// If no flags are set, match everything (permissive default)
|
|
235
|
+
if (!rule.mobile && !rule.tablet && !rule.desktop) return true;
|
|
236
|
+
return !!(rule.mobile && isMobile) || !!(rule.tablet && isTablet) || !!(rule.desktop && isDesktop);
|
|
235
237
|
},
|
|
236
238
|
"website/matchers/random.ts": (rule) => {
|
|
237
239
|
const traffic = typeof rule.traffic === "number" ? rule.traffic : 0.5;
|
package/src/sdk/analytics.ts
CHANGED
|
@@ -61,7 +61,12 @@ export const ANALYTICS_SCRIPT = `
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
observeAll();
|
|
64
|
-
new MutationObserver(observeAll)
|
|
64
|
+
var mo = new MutationObserver(observeAll);
|
|
65
|
+
if (typeof requestIdleCallback !== 'undefined') {
|
|
66
|
+
requestIdleCallback(function() { mo.observe(document.body, { childList: true, subtree: true }); });
|
|
67
|
+
} else {
|
|
68
|
+
setTimeout(function() { mo.observe(document.body, { childList: true, subtree: true }); }, 0);
|
|
69
|
+
}
|
|
65
70
|
})();
|
|
66
71
|
`;
|
|
67
72
|
|
package/src/sdk/workerEntry.ts
CHANGED
|
@@ -34,6 +34,23 @@ import {
|
|
|
34
34
|
import { buildHtmlShell } from "./htmlShell";
|
|
35
35
|
import { cleanPathForCacheKey } from "./urlUtils";
|
|
36
36
|
import { isMobileUA } from "./useDevice";
|
|
37
|
+
import { getRenderShellConfig } from "../admin/setup";
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Append Link preload headers for CSS and fonts so the browser starts
|
|
41
|
+
* fetching them before parsing HTML. Only applied to HTML responses.
|
|
42
|
+
*/
|
|
43
|
+
function appendResourceHints(resp: Response): void {
|
|
44
|
+
const ct = resp.headers.get("content-type");
|
|
45
|
+
if (!ct || !ct.includes("text/html")) return;
|
|
46
|
+
const { cssHref, fontHrefs } = getRenderShellConfig();
|
|
47
|
+
if (cssHref) {
|
|
48
|
+
resp.headers.append("Link", `<${cssHref}>; rel=preload; as=style`);
|
|
49
|
+
}
|
|
50
|
+
for (const href of fontHrefs) {
|
|
51
|
+
resp.headers.append("Link", `<${href}>; rel=preload; as=font; crossorigin`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
37
54
|
|
|
38
55
|
// ---------------------------------------------------------------------------
|
|
39
56
|
// Types
|
|
@@ -736,6 +753,7 @@ export function createDecoWorkerEntry(
|
|
|
736
753
|
// CDN auto-caching would bypass that versioning and serve stale HTML
|
|
737
754
|
// after deploys (referencing old CSS/JS fingerprinted filenames).
|
|
738
755
|
hit.headers.set("CDN-Cache-Control", "no-store");
|
|
756
|
+
appendResourceHints(hit);
|
|
739
757
|
return hit;
|
|
740
758
|
}
|
|
741
759
|
} catch {
|
|
@@ -750,6 +768,7 @@ export function createDecoWorkerEntry(
|
|
|
750
768
|
const resp = new Response(origin.body, origin);
|
|
751
769
|
resp.headers.set("X-Cache", "BYPASS");
|
|
752
770
|
resp.headers.set("X-Cache-Reason", `status:${origin.status}`);
|
|
771
|
+
appendResourceHints(resp);
|
|
753
772
|
return resp;
|
|
754
773
|
}
|
|
755
774
|
|
|
@@ -764,6 +783,7 @@ export function createDecoWorkerEntry(
|
|
|
764
783
|
resp.headers.delete("CDN-Cache-Control");
|
|
765
784
|
resp.headers.set("X-Cache", "BYPASS");
|
|
766
785
|
resp.headers.set("X-Cache-Reason", "set-cookie");
|
|
786
|
+
appendResourceHints(resp);
|
|
767
787
|
return resp;
|
|
768
788
|
}
|
|
769
789
|
|
|
@@ -776,6 +796,7 @@ export function createDecoWorkerEntry(
|
|
|
776
796
|
resp.headers.set("Cache-Control", "private, no-cache, no-store, must-revalidate");
|
|
777
797
|
resp.headers.set("X-Cache", "BYPASS");
|
|
778
798
|
resp.headers.set("X-Cache-Reason", `profile:${profile}`);
|
|
799
|
+
appendResourceHints(resp);
|
|
779
800
|
return resp;
|
|
780
801
|
}
|
|
781
802
|
|
|
@@ -804,6 +825,7 @@ export function createDecoWorkerEntry(
|
|
|
804
825
|
// BUILD_HASH-versioned keys; CDN auto-caching would bypass versioning
|
|
805
826
|
// and serve stale HTML after deploys.
|
|
806
827
|
toReturn.headers.set("CDN-Cache-Control", "no-store");
|
|
828
|
+
appendResourceHints(toReturn);
|
|
807
829
|
|
|
808
830
|
// For Cache API storage, use sMaxAge as max-age since the Cache API
|
|
809
831
|
// ignores s-maxage and only respects max-age for TTL decisions.
|
package/src/vite/plugin.js
CHANGED
|
@@ -117,6 +117,42 @@ export function decoVitePlugin() {
|
|
|
117
117
|
});
|
|
118
118
|
},
|
|
119
119
|
|
|
120
|
+
config(_cfg, { command }) {
|
|
121
|
+
// Only split chunks for production builds — dev uses unbundled ESM.
|
|
122
|
+
if (command !== "build") return;
|
|
123
|
+
return {
|
|
124
|
+
build: {
|
|
125
|
+
rollupOptions: {
|
|
126
|
+
output: {
|
|
127
|
+
manualChunks(id) {
|
|
128
|
+
if (
|
|
129
|
+
id.includes("node_modules/react-dom") ||
|
|
130
|
+
id.includes("node_modules/react/")
|
|
131
|
+
) {
|
|
132
|
+
return "vendor-react";
|
|
133
|
+
}
|
|
134
|
+
if (
|
|
135
|
+
id.includes("@tanstack/react-router") ||
|
|
136
|
+
id.includes("@tanstack/start")
|
|
137
|
+
) {
|
|
138
|
+
return "vendor-router";
|
|
139
|
+
}
|
|
140
|
+
if (id.includes("@tanstack/react-query")) {
|
|
141
|
+
return "vendor-query";
|
|
142
|
+
}
|
|
143
|
+
if (id.includes("@decocms/start")) {
|
|
144
|
+
return "vendor-deco";
|
|
145
|
+
}
|
|
146
|
+
if (id.includes("@decocms/apps")) {
|
|
147
|
+
return "vendor-commerce";
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
},
|
|
155
|
+
|
|
120
156
|
configEnvironment(name, env) {
|
|
121
157
|
if (name === "ssr" || name === "client") {
|
|
122
158
|
env.optimizeDeps = env.optimizeDeps || {};
|