@decocms/start 0.30.1 → 0.30.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decocms/start",
3
- "version": "0.30.1",
3
+ "version": "0.30.2",
4
4
  "type": "module",
5
5
  "description": "Deco framework for TanStack Start - CMS bridge, admin protocol, hooks, schema generation",
6
6
  "main": "./src/index.ts",
@@ -61,7 +61,12 @@ export const ANALYTICS_SCRIPT = `
61
61
  }
62
62
 
63
63
  observeAll();
64
- new MutationObserver(observeAll).observe(document.body, { childList: true, subtree: true });
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
 
@@ -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.
@@ -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 || {};