one 1.2.38 → 1.2.39-1766066124062

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.
Files changed (144) hide show
  1. package/dist/cjs/cli/build.cjs +16 -4
  2. package/dist/cjs/cli/build.js +18 -5
  3. package/dist/cjs/cli/build.js.map +1 -1
  4. package/dist/cjs/cli/build.native.js +27 -4
  5. package/dist/cjs/cli/build.native.js.map +1 -1
  6. package/dist/cjs/cli/buildPage.cjs +59 -14
  7. package/dist/cjs/cli/buildPage.js +56 -14
  8. package/dist/cjs/cli/buildPage.js.map +1 -1
  9. package/dist/cjs/cli/buildPage.native.js +66 -19
  10. package/dist/cjs/cli/buildPage.native.js.map +1 -1
  11. package/dist/cjs/cli/generateSitemap.test.cjs +10 -10
  12. package/dist/cjs/cli/generateSitemap.test.js +8 -8
  13. package/dist/cjs/cli/generateSitemap.test.js.map +1 -1
  14. package/dist/cjs/cli/generateSitemap.test.native.js +12 -12
  15. package/dist/cjs/cli/generateSitemap.test.native.js.map +1 -1
  16. package/dist/cjs/constants.cjs +1 -0
  17. package/dist/cjs/constants.js +1 -0
  18. package/dist/cjs/constants.js.map +1 -1
  19. package/dist/cjs/constants.native.js +1 -0
  20. package/dist/cjs/constants.native.js.map +1 -1
  21. package/dist/cjs/createApp.cjs +2 -1
  22. package/dist/cjs/createApp.js +2 -1
  23. package/dist/cjs/createApp.js.map +1 -1
  24. package/dist/cjs/server/ServerContextScript.cjs +3 -1
  25. package/dist/cjs/server/ServerContextScript.js +2 -1
  26. package/dist/cjs/server/ServerContextScript.js.map +1 -1
  27. package/dist/cjs/server/ServerContextScript.native.js +3 -1
  28. package/dist/cjs/server/ServerContextScript.native.js.map +1 -1
  29. package/dist/cjs/server/oneServe.cjs +3 -2
  30. package/dist/cjs/server/oneServe.js +4 -2
  31. package/dist/cjs/server/oneServe.js.map +2 -2
  32. package/dist/cjs/server/oneServe.native.js +3 -2
  33. package/dist/cjs/server/oneServe.native.js.map +1 -1
  34. package/dist/cjs/server-render.cjs +9 -1
  35. package/dist/cjs/server-render.js +9 -1
  36. package/dist/cjs/server-render.js.map +1 -1
  37. package/dist/cjs/server-render.native.js +12 -3
  38. package/dist/cjs/server-render.native.js.map +1 -1
  39. package/dist/cjs/setup.native.js.map +6 -1
  40. package/dist/cjs/ui/common.cjs +5 -15
  41. package/dist/cjs/ui/common.js +5 -8
  42. package/dist/cjs/ui/common.js.map +1 -1
  43. package/dist/cjs/ui/common.native.js +4 -12
  44. package/dist/cjs/ui/common.native.js.map +1 -1
  45. package/dist/esm/cli/build.js +18 -5
  46. package/dist/esm/cli/build.js.map +1 -1
  47. package/dist/esm/cli/build.mjs +16 -4
  48. package/dist/esm/cli/build.mjs.map +1 -1
  49. package/dist/esm/cli/build.native.js +27 -4
  50. package/dist/esm/cli/build.native.js.map +1 -1
  51. package/dist/esm/cli/buildPage.js +56 -14
  52. package/dist/esm/cli/buildPage.js.map +1 -1
  53. package/dist/esm/cli/buildPage.mjs +59 -14
  54. package/dist/esm/cli/buildPage.mjs.map +1 -1
  55. package/dist/esm/cli/buildPage.native.js +66 -19
  56. package/dist/esm/cli/buildPage.native.js.map +1 -1
  57. package/dist/esm/cli/generateSitemap.test.js +9 -9
  58. package/dist/esm/cli/generateSitemap.test.js.map +1 -1
  59. package/dist/esm/cli/generateSitemap.test.mjs +11 -11
  60. package/dist/esm/cli/generateSitemap.test.mjs.map +1 -1
  61. package/dist/esm/cli/generateSitemap.test.native.js +13 -13
  62. package/dist/esm/cli/generateSitemap.test.native.js.map +1 -1
  63. package/dist/esm/constants.js +1 -0
  64. package/dist/esm/constants.js.map +1 -1
  65. package/dist/esm/constants.mjs +1 -0
  66. package/dist/esm/constants.mjs.map +1 -1
  67. package/dist/esm/constants.native.js +1 -0
  68. package/dist/esm/constants.native.js.map +1 -1
  69. package/dist/esm/createApp.js +2 -1
  70. package/dist/esm/createApp.js.map +1 -1
  71. package/dist/esm/createApp.mjs +2 -1
  72. package/dist/esm/createApp.mjs.map +1 -1
  73. package/dist/esm/server/ServerContextScript.js +2 -1
  74. package/dist/esm/server/ServerContextScript.js.map +1 -1
  75. package/dist/esm/server/ServerContextScript.mjs +3 -1
  76. package/dist/esm/server/ServerContextScript.mjs.map +1 -1
  77. package/dist/esm/server/ServerContextScript.native.js +3 -1
  78. package/dist/esm/server/ServerContextScript.native.js.map +1 -1
  79. package/dist/esm/server/oneServe.js +4 -2
  80. package/dist/esm/server/oneServe.js.map +2 -2
  81. package/dist/esm/server/oneServe.mjs +3 -2
  82. package/dist/esm/server/oneServe.mjs.map +1 -1
  83. package/dist/esm/server/oneServe.native.js +3 -2
  84. package/dist/esm/server/oneServe.native.js.map +1 -1
  85. package/dist/esm/server-render.js +9 -1
  86. package/dist/esm/server-render.js.map +1 -1
  87. package/dist/esm/server-render.mjs +9 -1
  88. package/dist/esm/server-render.mjs.map +1 -1
  89. package/dist/esm/server-render.native.js +12 -3
  90. package/dist/esm/server-render.native.js.map +1 -1
  91. package/dist/esm/ui/common.js +3 -5
  92. package/dist/esm/ui/common.js.map +1 -1
  93. package/dist/esm/ui/common.mjs +3 -13
  94. package/dist/esm/ui/common.mjs.map +1 -1
  95. package/dist/esm/ui/common.native.js +1 -9
  96. package/dist/esm/ui/common.native.js.map +1 -1
  97. package/package.json +10 -10
  98. package/src/cli/build.ts +43 -6
  99. package/src/cli/buildPage.ts +88 -12
  100. package/src/cli/generateSitemap.test.ts +20 -10
  101. package/src/constants.ts +1 -0
  102. package/src/createApp.tsx +1 -0
  103. package/src/server/ServerContextScript.tsx +2 -0
  104. package/src/server/oneServe.ts +3 -2
  105. package/src/server-render.tsx +29 -2
  106. package/src/types.ts +9 -0
  107. package/src/ui/common.tsx +2 -8
  108. package/src/vite/types.ts +21 -0
  109. package/types/cli/build.d.ts.map +1 -1
  110. package/types/cli/buildPage.d.ts +1 -1
  111. package/types/cli/buildPage.d.ts.map +1 -1
  112. package/types/constants.d.ts.map +1 -1
  113. package/types/createApp.d.ts.map +1 -1
  114. package/types/server/ServerContextScript.d.ts.map +1 -1
  115. package/types/server/oneServe.d.ts.map +1 -1
  116. package/types/server-render.d.ts +14 -2
  117. package/types/server-render.d.ts.map +1 -1
  118. package/types/types.d.ts +9 -0
  119. package/types/types.d.ts.map +1 -1
  120. package/types/ui/common.d.ts.map +1 -1
  121. package/types/vite/types.d.ts +20 -0
  122. package/types/vite/types.d.ts.map +1 -1
  123. package/dist/cjs/layouts/stack-utils/__tests__/composition.test.cjs +0 -189
  124. package/dist/cjs/layouts/stack-utils/__tests__/composition.test.js +0 -184
  125. package/dist/cjs/layouts/stack-utils/__tests__/composition.test.js.map +0 -6
  126. package/dist/cjs/layouts/stack-utils/__tests__/composition.test.native.js +0 -204
  127. package/dist/cjs/layouts/stack-utils/__tests__/composition.test.native.js.map +0 -1
  128. package/dist/cjs/vite/plugins/resolveIdScan.test.cjs +0 -47
  129. package/dist/cjs/vite/plugins/resolveIdScan.test.js +0 -42
  130. package/dist/cjs/vite/plugins/resolveIdScan.test.js.map +0 -6
  131. package/dist/cjs/vite/plugins/resolveIdScan.test.native.js +0 -58
  132. package/dist/cjs/vite/plugins/resolveIdScan.test.native.js.map +0 -1
  133. package/dist/esm/layouts/stack-utils/__tests__/composition.test.js +0 -197
  134. package/dist/esm/layouts/stack-utils/__tests__/composition.test.js.map +0 -6
  135. package/dist/esm/layouts/stack-utils/__tests__/composition.test.mjs +0 -190
  136. package/dist/esm/layouts/stack-utils/__tests__/composition.test.mjs.map +0 -1
  137. package/dist/esm/layouts/stack-utils/__tests__/composition.test.native.js +0 -202
  138. package/dist/esm/layouts/stack-utils/__tests__/composition.test.native.js.map +0 -1
  139. package/dist/esm/vite/plugins/resolveIdScan.test.js +0 -23
  140. package/dist/esm/vite/plugins/resolveIdScan.test.js.map +0 -6
  141. package/dist/esm/vite/plugins/resolveIdScan.test.mjs +0 -26
  142. package/dist/esm/vite/plugins/resolveIdScan.test.mjs.map +0 -1
  143. package/dist/esm/vite/plugins/resolveIdScan.test.native.js +0 -34
  144. package/dist/esm/vite/plugins/resolveIdScan.test.native.js.map +0 -1
package/src/cli/build.ts CHANGED
@@ -385,7 +385,8 @@ export async function build(args: {
385
385
  return []
386
386
  })()
387
387
 
388
- const preloads = [
388
+ // All preloads combined (original behavior)
389
+ const allPreloads = [
389
390
  ...new Set([
390
391
  ...preloadSetupFilePreloads,
391
392
  // add the route entry js (like ./app/index.ts)
@@ -395,9 +396,38 @@ export async function build(args: {
395
396
  ...entryImports,
396
397
  ...layoutImports,
397
398
  ]),
398
- ]
399
- // nested path pages need to reference root assets
400
- .map((path) => `/${path}`)
399
+ ].map((path) => `/${path}`)
400
+
401
+ // Check experimental script loading mode
402
+ const scriptLoadingMode = oneOptions.web?.experimental_scriptLoading
403
+
404
+ // When 'defer-non-critical' is enabled, separate critical from non-critical
405
+ const useDeferredLoading = scriptLoadingMode === 'defer-non-critical'
406
+
407
+ // Critical: scripts that must execute immediately (async)
408
+ const criticalPreloads = useDeferredLoading
409
+ ? [
410
+ ...new Set([
411
+ ...preloadSetupFilePreloads,
412
+ // add the virtual entry (framework bootstrap)
413
+ vxrnOutput.clientManifest['virtual:one-entry'].file,
414
+ // add the route entry js (like ./app/index.ts)
415
+ clientManifestEntry.file,
416
+ // add layout files (but not their deep imports)
417
+ ...layoutEntries.map((entry) => entry.file),
418
+ ]),
419
+ ].map((path) => `/${path}`)
420
+ : undefined
421
+
422
+ // Non-critical: component imports, utilities - will be modulepreload hints only
423
+ const deferredPreloads = useDeferredLoading
424
+ ? [...new Set([...entryImports, ...layoutEntries.flatMap((entry) => collectImports(entry))])]
425
+ .filter((path) => !criticalPreloads!.includes(`/${path}`))
426
+ .map((path) => `/${path}`)
427
+ : undefined
428
+
429
+ // Use all preloads when not using deferred loading
430
+ const preloads = useDeferredLoading ? [...criticalPreloads!, ...deferredPreloads!] : allPreloads
401
431
 
402
432
  const allEntries = [clientManifestEntry, ...layoutEntries]
403
433
  const allCSS = allEntries
@@ -471,9 +501,13 @@ export async function build(args: {
471
501
  // Get route-level sitemap export if present
472
502
  const routeSitemapExport = exported.sitemap as One.RouteSitemap | undefined
473
503
 
504
+ // Determine if after-lcp script loading should be used for this route
505
+ // Only applies to SSG pages (SPA pages need JS to render anything)
506
+ const useAfterLCP = foundRoute.type === 'ssg' && scriptLoadingMode === 'after-lcp'
507
+
474
508
  for (const params of paramsList) {
475
509
  const path = getPathnameFromFilePath(relativeId, params, foundRoute.type === 'ssg')
476
- console.info(` ↦ route ${path}`)
510
+ console.info(` ↦ route ${path}${useAfterLCP ? ' (after-lcp)' : ''}`)
477
511
 
478
512
  const built = await runWithAsyncLocalContext(async () => {
479
513
  return await buildPage(
@@ -490,7 +524,10 @@ export async function build(args: {
490
524
  preloads,
491
525
  allCSS,
492
526
  routePreloads,
493
- allCSSContents
527
+ allCSSContents,
528
+ criticalPreloads,
529
+ deferredPreloads,
530
+ useAfterLCP
494
531
  )
495
532
  })
496
533
 
@@ -23,7 +23,10 @@ export async function buildPage(
23
23
  preloads: string[],
24
24
  allCSS: string[],
25
25
  routePreloads: Record<string, string>,
26
- allCSSContents?: string[]
26
+ allCSSContents?: string[],
27
+ criticalPreloads?: string[],
28
+ deferredPreloads?: string[],
29
+ useAfterLCP?: boolean
27
30
  ): Promise<One.RouteBuildInfo> {
28
31
  const render = await getRender(serverEntry)
29
32
  const htmlPath = `${path.endsWith('/') ? `${removeTrailingSlash(path)}/index` : path}.html`
@@ -65,13 +68,19 @@ export async function buildPage(
65
68
  await FSExtra.writeFile(join(clientDir, preloadPath), preloadContent)
66
69
 
67
70
  // Generate CSS preload file with prefetch (on hover) and inject (on navigation) functions
71
+ // Deduplicate CSS URLs to avoid loading the same file multiple times
72
+ const uniqueCSS = [...new Set(allCSS)]
68
73
  const cssPreloadContent = `
69
74
  const CSS_TIMEOUT = 1000
70
- const cssUrls = ${JSON.stringify(allCSS)}
75
+ const cssUrls = ${JSON.stringify(uniqueCSS)}
76
+
77
+ // Global cache for loaded CSS - avoids DOM queries and tracks across navigations
78
+ const loaded = (window.__oneLoadedCSS ||= new Set())
71
79
 
72
80
  // Prefetch CSS without applying - called on link hover
73
81
  export function prefetchCSS() {
74
82
  cssUrls.forEach(href => {
83
+ if (loaded.has(href)) return
75
84
  if (document.querySelector(\`link[href="\${href}"]\`)) return
76
85
  const link = document.createElement('link')
77
86
  link.rel = 'prefetch'
@@ -84,21 +93,31 @@ export function prefetchCSS() {
84
93
  // Inject CSS to apply styles - called on actual navigation
85
94
  export function injectCSS() {
86
95
  return Promise.all(cssUrls.map(href => {
96
+ // Skip if already loaded
97
+ if (loaded.has(href)) return Promise.resolve()
87
98
  // Remove any prefetch link for this href
88
99
  const prefetchLink = document.querySelector(\`link[rel="prefetch"][href="\${href}"]\`)
89
100
  if (prefetchLink) prefetchLink.remove()
90
- // Skip if stylesheet already exists
91
- if (document.querySelector(\`link[rel="stylesheet"][href="\${href}"]\`)) return Promise.resolve()
101
+ // Skip if stylesheet already exists in DOM
102
+ if (document.querySelector(\`link[rel="stylesheet"][href="\${href}"]\`)) {
103
+ loaded.add(href)
104
+ return Promise.resolve()
105
+ }
92
106
  return new Promise(resolve => {
93
107
  const link = document.createElement('link')
94
108
  link.rel = 'stylesheet'
95
109
  link.href = href
96
- link.onload = link.onerror = resolve
97
- document.head.appendChild(link)
98
- setTimeout(() => {
110
+ const timeoutId = setTimeout(() => {
99
111
  console.warn('[one] CSS load timeout:', href)
112
+ loaded.add(href)
100
113
  resolve()
101
114
  }, CSS_TIMEOUT)
115
+ link.onload = link.onerror = () => {
116
+ clearTimeout(timeoutId)
117
+ loaded.add(href)
118
+ resolve()
119
+ }
120
+ document.head.appendChild(link)
102
121
  })
103
122
  }))
104
123
  }
@@ -134,9 +153,11 @@ if (typeof document === 'undefined') globalThis.document = {}
134
153
  globalThis['__vxrnresetState']?.()
135
154
 
136
155
  if (foundRoute.type === 'ssg') {
137
- const html = await render({
156
+ let html = await render({
138
157
  path,
139
- preloads,
158
+ // Use separated preloads if available, otherwise fall back to all preloads
159
+ preloads: criticalPreloads || preloads,
160
+ deferredPreloads: deferredPreloads,
140
161
  loaderProps,
141
162
  loaderData,
142
163
  css: allCSS,
@@ -144,6 +165,12 @@ if (typeof document === 'undefined') globalThis.document = {}
144
165
  mode: 'ssg',
145
166
  routePreloads,
146
167
  })
168
+
169
+ // Apply after-LCP script loading if enabled
170
+ if (useAfterLCP) {
171
+ html = applyAfterLCPScriptLoad(html, preloads)
172
+ }
173
+
147
174
  await outputFile(htmlOutPath, html)
148
175
  } else if (foundRoute.type === 'spa') {
149
176
  // Generate CSS - either inline styles or link tags
@@ -154,13 +181,22 @@ if (typeof document === 'undefined') globalThis.document = {}
154
181
  .join('\n')
155
182
  : allCSS.map((file) => ` <link rel="stylesheet" href=${file} />`).join('\n')
156
183
 
184
+ // Use separated preloads if available
185
+ const criticalScripts = (criticalPreloads || preloads)
186
+ .map((preload) => ` <script type="module" src="${preload}" async=""></script>`)
187
+ .join('\n')
188
+
189
+ // Non-critical scripts as modulepreload hints only
190
+ const deferredLinks = (deferredPreloads || [])
191
+ .map((preload) => ` <link rel="modulepreload" fetchPriority="low" href="${preload}"/>`)
192
+ .join('\n')
193
+
157
194
  await outputFile(
158
195
  htmlOutPath,
159
196
  `<html><head>
160
197
  ${constants.getSpaHeaderElements({ serverContext: { loaderProps, loaderData } })}
161
- ${preloads
162
- .map((preload) => ` <script type="module" src="${preload}"></script>`)
163
- .join('\n')}
198
+ ${criticalScripts}
199
+ ${deferredLinks}
164
200
  ${cssOutput}
165
201
  </head></html>`
166
202
  )
@@ -202,6 +238,8 @@ params:\n\n${JSON.stringify(params || null, null, 2)}`
202
238
  params,
203
239
  path,
204
240
  preloads,
241
+ criticalPreloads,
242
+ deferredPreloads,
205
243
  }
206
244
  }
207
245
 
@@ -234,3 +272,41 @@ async function getRender(serverEntry: string) {
234
272
  function removeTrailingSlash(path: string) {
235
273
  return path.endsWith('/') ? path.slice(0, path.length - 1) : path
236
274
  }
275
+
276
+ /**
277
+ * Transforms HTML to delay script execution until after first paint.
278
+ * Keeps modulepreload links so scripts download immediately in parallel.
279
+ * Removes async script tags and adds a double-rAF loader that executes
280
+ * scripts after at least one paint has happened.
281
+ */
282
+ function applyAfterLCPScriptLoad(html: string, preloads: string[]): string {
283
+ // Remove all <script type="module" ... async> tags (prevents immediate execution)
284
+ // Keep modulepreload links so scripts download in parallel immediately
285
+ html = html.replace(/<script\s+type="module"[^>]*async[^>]*><\/script>/gi, '')
286
+
287
+ // Create the double-rAF loader script
288
+ // Downloads happen immediately via modulepreload, execution waits for paint
289
+ const loaderScript = `
290
+ <script>
291
+ (function() {
292
+ var scripts = ${JSON.stringify(preloads)};
293
+ function loadScripts() {
294
+ scripts.forEach(function(src) {
295
+ var script = document.createElement('script');
296
+ script.type = 'module';
297
+ script.src = src;
298
+ document.head.appendChild(script);
299
+ });
300
+ }
301
+ // Double rAF ensures at least one paint has happened before executing JS
302
+ requestAnimationFrame(function() {
303
+ requestAnimationFrame(loadScripts);
304
+ });
305
+ })();
306
+ </script>`
307
+
308
+ // Insert the loader script before </head>
309
+ html = html.replace('</head>', `${loaderScript}</head>`)
310
+
311
+ return html
312
+ }
@@ -1,8 +1,23 @@
1
- import { describe, expect, it } from 'vitest'
1
+ import { describe, expect, it, beforeEach, afterEach } from 'vitest'
2
2
  import { generateSitemap, type RouteSitemapData } from './generateSitemap'
3
3
  import type { One } from '../vite/types'
4
4
 
5
5
  describe('generateSitemap', () => {
6
+ let originalEnv: string | undefined
7
+
8
+ beforeEach(() => {
9
+ originalEnv = process.env.ONE_SERVER_URL
10
+ delete process.env.ONE_SERVER_URL
11
+ })
12
+
13
+ afterEach(() => {
14
+ if (originalEnv !== undefined) {
15
+ process.env.ONE_SERVER_URL = originalEnv
16
+ } else {
17
+ delete process.env.ONE_SERVER_URL
18
+ }
19
+ })
20
+
6
21
  it('generates basic sitemap XML', () => {
7
22
  const routes: RouteSitemapData[] = [{ path: '/' }, { path: '/about' }, { path: '/blog' }]
8
23
  const options: One.SitemapOptions = {}
@@ -42,19 +57,14 @@ describe('generateSitemap', () => {
42
57
  })
43
58
 
44
59
  it('uses ONE_SERVER_URL env var when baseUrl not provided', () => {
45
- const originalEnv = process.env.ONE_SERVER_URL
46
60
  process.env.ONE_SERVER_URL = 'https://env-url.com'
47
61
 
48
- try {
49
- const routes: RouteSitemapData[] = [{ path: '/test' }]
50
- const options: One.SitemapOptions = {}
62
+ const routes: RouteSitemapData[] = [{ path: '/test' }]
63
+ const options: One.SitemapOptions = {}
51
64
 
52
- const result = generateSitemap(routes, options)
65
+ const result = generateSitemap(routes, options)
53
66
 
54
- expect(result).toContain('<loc>https://env-url.com/test</loc>')
55
- } finally {
56
- process.env.ONE_SERVER_URL = originalEnv
57
- }
67
+ expect(result).toContain('<loc>https://env-url.com/test</loc>')
58
68
  })
59
69
 
60
70
  it('applies default priority to all routes', () => {
package/src/constants.ts CHANGED
@@ -28,4 +28,5 @@ export const getSpaHeaderElements = ({
28
28
  <script>globalThis['global'] = globalThis</script>
29
29
  <script>globalThis['__vxrnIsSPA'] = true</script>
30
30
  <script>globalThis["${SERVER_CONTEXT_KEY}"] = ${JSON.stringify(serverContext)}</script>
31
+ <script>globalThis.__oneLoadedCSS = new Set(${JSON.stringify(serverContext.css || [])})</script>
31
32
  `
package/src/createApp.tsx CHANGED
@@ -73,6 +73,7 @@ export function createApp(options: CreateAppProps) {
73
73
 
74
74
  let html = await renderToString(rootElement, {
75
75
  preloads: props.preloads,
76
+ deferredPreloads: props.deferredPreloads,
76
77
  })
77
78
 
78
79
  try {
@@ -19,6 +19,7 @@ export function ServerContextScript() {
19
19
 
20
20
  if (process.env.VITE_ENVIRONMENT === 'ssr') {
21
21
  const context = useServerContext()
22
+ const cssUrls = context?.css || []
22
23
 
23
24
  return (
24
25
  <script
@@ -32,6 +33,7 @@ export function ServerContextScript() {
32
33
  ...context,
33
34
  postRenderData: SERVER_CONTEXT_POST_RENDER_STRING,
34
35
  })};
36
+ globalThis.__oneLoadedCSS = new Set(${JSON.stringify(cssUrls)});
35
37
  `,
36
38
  }}
37
39
  />
@@ -111,7 +111,6 @@ export async function oneServe(oneOptions: One.PluginOptions, buildInfo: One.Bui
111
111
  try {
112
112
  const exported = await import(toAbsolute(buildInfo.serverJsPath))
113
113
  const loaderData = await exported.loader?.(loaderProps)
114
- const preloads = buildInfo.preloads
115
114
 
116
115
  const headers = new Headers()
117
116
  headers.set('content-type', 'text/html')
@@ -121,7 +120,9 @@ export async function oneServe(oneOptions: One.PluginOptions, buildInfo: One.Bui
121
120
  loaderData,
122
121
  loaderProps,
123
122
  path: loaderProps?.path || '/',
124
- preloads,
123
+ // Use separated preloads for optimal loading
124
+ preloads: buildInfo.criticalPreloads || buildInfo.preloads,
125
+ deferredPreloads: buildInfo.deferredPreloads,
125
126
  css: buildInfo.css,
126
127
  cssContents: buildInfo.cssContents,
127
128
  })
@@ -1,11 +1,38 @@
1
1
  import ReactDOMServer from 'react-dom/server.browser'
2
2
 
3
- export const renderToString = async (app: React.ReactElement, options: { preloads?: string[] }) => {
3
+ export type RenderToStringOptions = {
4
+ /**
5
+ * Critical scripts that need to execute immediately (will use async).
6
+ * These are added to bootstrapModules and generate both modulepreload links and async script tags.
7
+ * Keep this list minimal (typically: setupClient, one-entry, page entry).
8
+ */
9
+ preloads?: string[]
10
+
11
+ /**
12
+ * Non-critical scripts that can wait (will only be modulepreload hints).
13
+ * These only generate <link rel="modulepreload"> tags and are loaded when imported.
14
+ * Use this for component libraries, utilities, and other non-essential modules.
15
+ */
16
+ deferredPreloads?: string[]
17
+ }
18
+
19
+ export const renderToString = async (app: React.ReactElement, options: RenderToStringOptions) => {
4
20
  const readableStream = await ReactDOMServer.renderToReadableStream(app, {
21
+ // Only pass critical scripts to bootstrapModules
22
+ // These generate both modulepreload links AND async script tags
5
23
  bootstrapModules: options.preloads,
6
24
  })
7
25
  await readableStream.allReady
8
- const out = await streamToString(readableStream)
26
+ let out = await streamToString(readableStream)
27
+
28
+ // Add non-critical modulepreload links to head (just hints, no script execution)
29
+ if (options.deferredPreloads?.length) {
30
+ const modulepreloadLinks = options.deferredPreloads
31
+ .map((src) => `<link rel="modulepreload" fetchPriority="low" href="${src}"/>`)
32
+ .join('')
33
+ out = out.replace('</head>', `${modulepreloadLinks}</head>`)
34
+ }
35
+
9
36
  return out
10
37
  }
11
38
 
package/src/types.ts CHANGED
@@ -19,7 +19,16 @@ export type LoaderProps<Params extends Object = Record<string, string | string[]
19
19
  export type RenderAppProps = {
20
20
  mode: One.RouteRenderMode
21
21
  path: string
22
+ /**
23
+ * Critical scripts that need to execute immediately (will use async).
24
+ * These generate both modulepreload links and async script tags.
25
+ */
22
26
  preloads?: string[]
27
+ /**
28
+ * Non-critical scripts that can wait (will only be modulepreload hints).
29
+ * These only generate <link rel="modulepreload"> tags and load when imported.
30
+ */
31
+ deferredPreloads?: string[]
23
32
  css?: string[]
24
33
  /** When inlineLayoutCSS is enabled, this contains the actual CSS content to inline */
25
34
  cssContents?: string[]
package/src/ui/common.tsx CHANGED
@@ -7,6 +7,7 @@ import { resolveHref } from '../link/href'
7
7
  import { sortRoutesWithInitial } from '../router/sortRoutes'
8
8
  import type { OneRouter } from '../interfaces/router'
9
9
  import { Slot } from './Slot'
10
+ import { Screen, createGetIdForRoute, getQualifiedRouteComponent } from '../router/useScreens'
10
11
 
11
12
  export const ViewSlot = Slot
12
13
 
@@ -190,10 +191,6 @@ export function triggersToScreens(
190
191
  const children: React.JSX.Element[] = []
191
192
  const triggerMap: TriggerMap = { ...parentTriggerMap }
192
193
 
193
- // Import routeToScreen from One's useScreens
194
- const { Screen } = require('../router/useScreens')
195
- const { createGetIdForRoute } = require('../router/useScreens')
196
-
197
194
  for (const [index, config] of sortedConfigs.entries()) {
198
195
  triggerMap[config.name] = { ...config, index }
199
196
 
@@ -219,10 +216,7 @@ export function triggersToScreens(
219
216
 
220
217
  return output
221
218
  }}
222
- getComponent={() => {
223
- const { getQualifiedRouteComponent } = require('../router/useScreens')
224
- return getQualifiedRouteComponent(route)
225
- }}
219
+ getComponent={() => getQualifiedRouteComponent(route)}
226
220
  />
227
221
  )
228
222
  }
package/src/vite/types.ts CHANGED
@@ -344,6 +344,22 @@ export namespace One {
344
344
  */
345
345
  inlineLayoutCSS?: boolean
346
346
 
347
+ /**
348
+ * @experimental
349
+ * Controls how scripts are loaded for improved performance.
350
+ *
351
+ * - `'defer-non-critical'`: Critical scripts (framework entry, page, layouts) load immediately.
352
+ * Non-critical scripts (component imports, utilities) become modulepreload hints only,
353
+ * reducing network/CPU contention.
354
+ *
355
+ * - `'after-lcp'`: Scripts download immediately via modulepreload but execution is deferred
356
+ * until after first paint using double requestAnimationFrame. This allows the browser to
357
+ * paint the SSR content before executing JavaScript. Only applies to SSG pages.
358
+ *
359
+ * @default undefined (all scripts load with async)
360
+ */
361
+ experimental_scriptLoading?: 'defer-non-critical' | 'after-lcp'
362
+
347
363
  /**
348
364
  * Generate a sitemap.xml file during build.
349
365
  *
@@ -445,7 +461,12 @@ export namespace One {
445
461
  serverJsPath: string
446
462
  params: Object
447
463
  loaderData: any
464
+ /** All preloads (for backwards compatibility) */
448
465
  preloads: string[]
466
+ /** Critical preloads that load immediately with async */
467
+ criticalPreloads?: string[]
468
+ /** Non-critical preloads that are modulepreload hints only */
469
+ deferredPreloads?: string[]
449
470
  css: string[]
450
471
  /** When inlineLayoutCSS is enabled, contains the actual CSS content */
451
472
  cssContents?: string[]
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"AAoCA,wBAAsB,KAAK,CAAC,IAAI,EAAE;IAChC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,CAAA;CACrC,iBAqmBA"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"AAoCA,wBAAsB,KAAK,CAAC,IAAI,EAAE;IAChC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,CAAA;CACrC,iBA0oBA"}
@@ -1,3 +1,3 @@
1
1
  import type { One, RouteInfo } from '../vite/types';
2
- export declare function buildPage(serverEntry: string, path: string, relativeId: string, params: any, foundRoute: RouteInfo<string>, clientManifestEntry: any, staticDir: string, clientDir: string, builtMiddlewares: Record<string, string>, serverJsPath: string, preloads: string[], allCSS: string[], routePreloads: Record<string, string>, allCSSContents?: string[]): Promise<One.RouteBuildInfo>;
2
+ export declare function buildPage(serverEntry: string, path: string, relativeId: string, params: any, foundRoute: RouteInfo<string>, clientManifestEntry: any, staticDir: string, clientDir: string, builtMiddlewares: Record<string, string>, serverJsPath: string, preloads: string[], allCSS: string[], routePreloads: Record<string, string>, allCSSContents?: string[], criticalPreloads?: string[], deferredPreloads?: string[], useAfterLCP?: boolean): Promise<One.RouteBuildInfo>;
3
3
  //# sourceMappingURL=buildPage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"buildPage.d.ts","sourceRoot":"","sources":["../../src/cli/buildPage.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAInD,wBAAsB,SAAS,CAC7B,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,GAAG,EACX,UAAU,EAAE,SAAS,CAAC,MAAM,CAAC,EAC7B,mBAAmB,EAAE,GAAG,EACxB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACxC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAAE,EAClB,MAAM,EAAE,MAAM,EAAE,EAChB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,cAAc,CAAC,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAmL7B"}
1
+ {"version":3,"file":"buildPage.d.ts","sourceRoot":"","sources":["../../src/cli/buildPage.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAInD,wBAAsB,SAAS,CAC7B,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,GAAG,EACX,UAAU,EAAE,SAAS,CAAC,MAAM,CAAC,EAC7B,mBAAmB,EAAE,GAAG,EACxB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACxC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAAE,EAClB,MAAM,EAAE,MAAM,EAAE,EAChB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,cAAc,CAAC,EAAE,MAAM,EAAE,EACzB,gBAAgB,CAAC,EAAE,MAAM,EAAE,EAC3B,gBAAgB,CAAC,EAAE,MAAM,EAAE,EAC3B,WAAW,CAAC,EAAE,OAAO,GACpB,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAsN7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAEvC,eAAO,MAAM,WAAW,SAA2E,CAAA;AACnG,eAAO,MAAM,WAAW,SAA2E,CAAA;AACnG,eAAO,MAAM,QAAQ,SAA0C,CAAA;AAE/D,eAAO,MAAM,SAAS,QAA4E,CAAA;AAElG,eAAO,MAAM,0BAA0B,oBAAoB,CAAA;AAC3D,eAAO,MAAM,8BAA8B,0BAAwC,CAAA;AACnF,eAAO,MAAM,uBAAuB,QAA6C,CAAA;AACjF,eAAO,MAAM,iBAAiB,QAA+C,CAAA;AAE7E,eAAO,MAAM,kBAAkB,QAA6B,CAAA;AAC5D,eAAO,MAAM,sBAAsB,QAAiC,CAAA;AAGpE,eAAO,MAAM,qBAAqB,wBAAwB,CAAA;AAC1D,eAAO,MAAM,oBAAoB,oCAAyC,CAAA;AAE1E,eAAO,MAAM,kBAAkB,2BAA2B,CAAA;AAE1D,eAAO,MAAM,oBAAoB,GAAI,qBAElC;IACD,aAAa,CAAC,EAAE,GAAG,CAAC,aAAa,CAAA;CAC7B,WAIL,CAAA"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAEvC,eAAO,MAAM,WAAW,SAA2E,CAAA;AACnG,eAAO,MAAM,WAAW,SAA2E,CAAA;AACnG,eAAO,MAAM,QAAQ,SAA0C,CAAA;AAE/D,eAAO,MAAM,SAAS,QAA4E,CAAA;AAElG,eAAO,MAAM,0BAA0B,oBAAoB,CAAA;AAC3D,eAAO,MAAM,8BAA8B,0BAAwC,CAAA;AACnF,eAAO,MAAM,uBAAuB,QAA6C,CAAA;AACjF,eAAO,MAAM,iBAAiB,QAA+C,CAAA;AAE7E,eAAO,MAAM,kBAAkB,QAA6B,CAAA;AAC5D,eAAO,MAAM,sBAAsB,QAAiC,CAAA;AAGpE,eAAO,MAAM,qBAAqB,wBAAwB,CAAA;AAC1D,eAAO,MAAM,oBAAoB,oCAAyC,CAAA;AAE1E,eAAO,MAAM,kBAAkB,2BAA2B,CAAA;AAE1D,eAAO,MAAM,oBAAoB,GAAI,qBAElC;IACD,aAAa,CAAC,EAAE,GAAG,CAAC,aAAa,CAAA;CAC7B,WAKL,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"createApp.d.ts","sourceRoot":"","sources":["../src/createApp.tsx"],"names":[],"mappings":"AAAA,OAAO,SAAS,CAAA;AAQhB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAK7C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAEvC,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;IAC9C,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,GAAG,CAAC,KAAK,CAAA;CAClB,CAAA;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,cAAc;;oBAIrB,cAAc;EAwIzC"}
1
+ {"version":3,"file":"createApp.d.ts","sourceRoot":"","sources":["../src/createApp.tsx"],"names":[],"mappings":"AAAA,OAAO,SAAS,CAAA;AAQhB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAK7C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAEvC,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;IAC9C,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,GAAG,CAAC,KAAK,CAAA;CAClB,CAAA;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,cAAc;;oBAIrB,cAAc;EAyIzC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ServerContextScript.d.ts","sourceRoot":"","sources":["../../src/server/ServerContextScript.tsx"],"names":[],"mappings":"AAIA,wBAAgB,mBAAmB,mDAqClC"}
1
+ {"version":3,"file":"ServerContextScript.d.ts","sourceRoot":"","sources":["../../src/server/ServerContextScript.tsx"],"names":[],"mappings":"AAIA,wBAAgB,mBAAmB,mDAuClC"}
@@ -1 +1 @@
1
- {"version":3,"file":"oneServe.d.ts","sourceRoot":"","sources":["../../src/server/oneServe.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAqB,MAAM,MAAM,CAAA;AAoBnD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAA;AAKxC,wBAAsB,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,aAAa,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,EAAE,IAAI,iBA+ThG"}
1
+ {"version":3,"file":"oneServe.d.ts","sourceRoot":"","sources":["../../src/server/oneServe.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAqB,MAAM,MAAM,CAAA;AAoBnD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAA;AAKxC,wBAAsB,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,aAAa,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,EAAE,IAAI,iBAgUhG"}
@@ -1,4 +1,16 @@
1
- export declare const renderToString: (app: React.ReactElement, options: {
1
+ export type RenderToStringOptions = {
2
+ /**
3
+ * Critical scripts that need to execute immediately (will use async).
4
+ * These are added to bootstrapModules and generate both modulepreload links and async script tags.
5
+ * Keep this list minimal (typically: setupClient, one-entry, page entry).
6
+ */
2
7
  preloads?: string[];
3
- }) => Promise<string>;
8
+ /**
9
+ * Non-critical scripts that can wait (will only be modulepreload hints).
10
+ * These only generate <link rel="modulepreload"> tags and are loaded when imported.
11
+ * Use this for component libraries, utilities, and other non-essential modules.
12
+ */
13
+ deferredPreloads?: string[];
14
+ };
15
+ export declare const renderToString: (app: React.ReactElement, options: RenderToStringOptions) => Promise<string>;
4
16
  //# sourceMappingURL=server-render.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server-render.d.ts","sourceRoot":"","sources":["../src/server-render.tsx"],"names":[],"mappings":"AAEA,eAAO,MAAM,cAAc,GAAU,KAAK,KAAK,CAAC,YAAY,EAAE,SAAS;IAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,oBAO7F,CAAA"}
1
+ {"version":3,"file":"server-render.d.ts","sourceRoot":"","sources":["../src/server-render.tsx"],"names":[],"mappings":"AAEA,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IAEnB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC5B,CAAA;AAED,eAAO,MAAM,cAAc,GAAU,KAAK,KAAK,CAAC,YAAY,EAAE,SAAS,qBAAqB,oBAkB3F,CAAA"}
package/types/types.d.ts CHANGED
@@ -13,7 +13,16 @@ export type LoaderProps<Params extends Object = Record<string, string | string[]
13
13
  export type RenderAppProps = {
14
14
  mode: One.RouteRenderMode;
15
15
  path: string;
16
+ /**
17
+ * Critical scripts that need to execute immediately (will use async).
18
+ * These generate both modulepreload links and async script tags.
19
+ */
16
20
  preloads?: string[];
21
+ /**
22
+ * Non-critical scripts that can wait (will only be modulepreload hints).
23
+ * These only generate <link rel="modulepreload"> tags and load when imported.
24
+ */
25
+ deferredPreloads?: string[];
17
26
  css?: string[];
18
27
  /** When inlineLayoutCSS is enabled, this contains the actual CSS content to inline */
19
28
  cssContents?: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAEvC,yFAAyF;AACzF,MAAM,MAAM,WAAW,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;AAEhF,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;AAExE,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;AAE1E,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;AAElE,MAAM,MAAM,WAAW,CAAC,MAAM,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI;IACnF,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,GAAG,CAAC,eAAe,CAAA;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAA;IACd,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,gBAAgB,CAAC,EAAE,GAAG,CAAA;IACtB,UAAU,CAAC,EAAE,GAAG,CAAA;IAChB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACvC,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AAEvC,yFAAyF;AACzF,MAAM,MAAM,WAAW,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;AAEhF,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;AAExE,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;AAE1E,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;AAElE,MAAM,MAAM,WAAW,CAAC,MAAM,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI;IACnF,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,GAAG,CAAC,eAAe,CAAA;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC3B,GAAG,CAAC,EAAE,MAAM,EAAE,CAAA;IACd,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,gBAAgB,CAAC,EAAE,GAAG,CAAA;IACtB,UAAU,CAAC,EAAE,GAAG,CAAA;IAChB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACvC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/ui/common.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAA;AAElG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAA;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAGhD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAE7B,eAAO,MAAM,QAAQ,8GAAO,CAAA;AAE5B,MAAM,MAAM,aAAa,GACrB;IACE,IAAI,EAAE,UAAU,CAAA;IAChB,IAAI,EAAE,SAAS,CAAC,IAAI,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;CACb,GACD;IACE,IAAI,EAAE,UAAU,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAEL,KAAK,sBAAsB,GAAG,OAAO,CAAC,iBAAiB,EAAE;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC,CAAA;AAC7E,KAAK,aAAa,GACd;IACE,IAAI,EAAE,UAAU,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,SAAS,CAAA;IACpB,MAAM,EAAE,sBAAsB,CAAA;CAC/B,GACD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEpD,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AA+B1E,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,aAAa,EAAE,EACzB,eAAe,EAAE,SAAS,EAC1B,OAAO,EAAE,cAAc,CAAC,aAAa,CAAC,EACtC,gBAAgB,EAAE,SAAS,GAAG,MAAM,EACpC,gBAAgB,EAAE,UAAU,EAC5B,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,MAAM;;;EAgKnB;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAAG,SAAS,EAClE,YAAY,CAAC,EAAE,MAAM,GACpB,sBAAsB,CAsCxB"}
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/ui/common.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAA;AAElG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAA;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAGhD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAG7B,eAAO,MAAM,QAAQ,8GAAO,CAAA;AAE5B,MAAM,MAAM,aAAa,GACrB;IACE,IAAI,EAAE,UAAU,CAAA;IAChB,IAAI,EAAE,SAAS,CAAC,IAAI,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;CACb,GACD;IACE,IAAI,EAAE,UAAU,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAEL,KAAK,sBAAsB,GAAG,OAAO,CAAC,iBAAiB,EAAE;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC,CAAA;AAC7E,KAAK,aAAa,GACd;IACE,IAAI,EAAE,UAAU,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,SAAS,CAAA;IACpB,MAAM,EAAE,sBAAsB,CAAA;CAC/B,GACD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEpD,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AA+B1E,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,aAAa,EAAE,EACzB,eAAe,EAAE,SAAS,EAC1B,OAAO,EAAE,cAAc,CAAC,aAAa,CAAC,EACtC,gBAAgB,EAAE,SAAS,GAAG,MAAM,EACpC,gBAAgB,EAAE,UAAU,EAC5B,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,MAAM;;;EAyJnB;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAAG,SAAS,EAClE,YAAY,CAAC,EAAE,MAAM,GACpB,sBAAsB,CAsCxB"}
@@ -300,6 +300,21 @@ export declare namespace One {
300
300
  * @default false
301
301
  */
302
302
  inlineLayoutCSS?: boolean;
303
+ /**
304
+ * @experimental
305
+ * Controls how scripts are loaded for improved performance.
306
+ *
307
+ * - `'defer-non-critical'`: Critical scripts (framework entry, page, layouts) load immediately.
308
+ * Non-critical scripts (component imports, utilities) become modulepreload hints only,
309
+ * reducing network/CPU contention.
310
+ *
311
+ * - `'after-lcp'`: Scripts download immediately via modulepreload but execution is deferred
312
+ * until after first paint using double requestAnimationFrame. This allows the browser to
313
+ * paint the SSR content before executing JavaScript. Only applies to SSG pages.
314
+ *
315
+ * @default undefined (all scripts load with async)
316
+ */
317
+ experimental_scriptLoading?: 'defer-non-critical' | 'after-lcp';
303
318
  /**
304
319
  * Generate a sitemap.xml file during build.
305
320
  *
@@ -390,7 +405,12 @@ export declare namespace One {
390
405
  serverJsPath: string;
391
406
  params: Object;
392
407
  loaderData: any;
408
+ /** All preloads (for backwards compatibility) */
393
409
  preloads: string[];
410
+ /** Critical preloads that load immediately with async */
411
+ criticalPreloads?: string[];
412
+ /** Non-critical preloads that are modulepreload hints only */
413
+ deferredPreloads?: string[];
394
414
  css: string[];
395
415
  /** When inlineLayoutCSS is enabled, contains the actual CSS content */
396
416
  cssContents?: string[];