one 1.25.13 → 1.25.16
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/cjs/cli/build.cjs +29 -25
- package/dist/cjs/cli/build.native.js +262 -219
- package/dist/cjs/cli/build.native.js.map +1 -1
- package/dist/cjs/cli/buildPage.cjs +8 -19
- package/dist/cjs/cli/buildPage.native.js +8 -19
- package/dist/cjs/cli/buildPage.native.js.map +1 -1
- package/dist/cjs/cli/buildPageWorker.cjs +1 -1
- package/dist/cjs/cli/buildPageWorker.native.js +1 -1
- package/dist/cjs/cli/buildPageWorker.native.js.map +1 -1
- package/dist/cjs/cli/serverRouteModules.cjs +47 -0
- package/dist/cjs/cli/serverRouteModules.native.js +52 -0
- package/dist/cjs/cli/serverRouteModules.native.js.map +1 -0
- package/dist/cjs/cli/workerPool.native.js.map +1 -1
- package/dist/cjs/createApp.cjs +3 -0
- package/dist/cjs/headless-server.native.js.map +1 -1
- package/dist/cjs/headless.cjs +4 -0
- package/dist/cjs/headless.native.js +4 -0
- package/dist/cjs/headless.native.js.map +1 -1
- package/dist/cjs/router/diagnoseRouteLoadFailure.native.js.map +1 -1
- package/dist/cjs/router/useViteRoutes.cjs +9 -1
- package/dist/cjs/router/useViteRoutes.native.js +9 -1
- package/dist/cjs/router/useViteRoutes.native.js.map +1 -1
- package/dist/cjs/server/oneServe.cjs +23 -4
- package/dist/cjs/server/oneServe.native.js +25 -6
- package/dist/cjs/server/oneServe.native.js.map +1 -1
- package/dist/cjs/server/routeExportsFromEntry.cjs +47 -0
- package/dist/cjs/server/routeExportsFromEntry.native.js +52 -0
- package/dist/cjs/server/routeExportsFromEntry.native.js.map +1 -0
- package/dist/cjs/server/workerHandler.cjs +19 -6
- package/dist/cjs/server/workerHandler.native.js +20 -6
- package/dist/cjs/server/workerHandler.native.js.map +1 -1
- package/dist/cjs/server/workerHandler.test.cjs +24 -16
- package/dist/cjs/server/workerHandler.test.native.js +27 -16
- package/dist/cjs/server/workerHandler.test.native.js.map +1 -1
- package/dist/cjs/views/ScrollBehavior.native.js.map +1 -1
- package/dist/cjs/vite/cloudflareWranglerConfig.native.js.map +1 -1
- package/dist/cjs/vite/one.cjs +5 -2
- package/dist/cjs/vite/one.native.js +5 -2
- package/dist/cjs/vite/one.native.js.map +1 -1
- package/dist/cjs/vite/plugins/clientTreeShakePlugin.cjs +5 -3
- package/dist/cjs/vite/plugins/clientTreeShakePlugin.native.js +6 -3
- package/dist/cjs/vite/plugins/clientTreeShakePlugin.native.js.map +1 -1
- package/dist/cjs/vite/plugins/clientTreeShakePlugin.test.cjs +18 -0
- package/dist/cjs/vite/plugins/clientTreeShakePlugin.test.native.js +18 -0
- package/dist/cjs/vite/plugins/clientTreeShakePlugin.test.native.js.map +1 -1
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.cjs +4 -9
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.native.js +4 -9
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.native.js.map +1 -1
- package/dist/cjs/vite/plugins/virtualEntryPlugin.cjs +7 -6
- package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js +9 -6
- package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js.map +1 -1
- package/dist/cjs/vite/plugins/workerdDevPlugin.cjs +0 -13
- package/dist/cjs/vite/plugins/workerdDevPlugin.native.js +26 -58
- package/dist/cjs/vite/plugins/workerdDevPlugin.native.js.map +1 -1
- package/dist/esm/cli/build.mjs +30 -26
- package/dist/esm/cli/build.mjs.map +1 -1
- package/dist/esm/cli/build.native.js +263 -220
- package/dist/esm/cli/build.native.js.map +1 -1
- package/dist/esm/cli/buildPage.mjs +8 -19
- package/dist/esm/cli/buildPage.mjs.map +1 -1
- package/dist/esm/cli/buildPage.native.js +8 -19
- package/dist/esm/cli/buildPage.native.js.map +1 -1
- package/dist/esm/cli/buildPageWorker.mjs +1 -1
- package/dist/esm/cli/buildPageWorker.mjs.map +1 -1
- package/dist/esm/cli/buildPageWorker.native.js +1 -1
- package/dist/esm/cli/buildPageWorker.native.js.map +1 -1
- package/dist/esm/cli/serverRouteModules.mjs +22 -0
- package/dist/esm/cli/serverRouteModules.mjs.map +1 -0
- package/dist/esm/cli/serverRouteModules.native.js +24 -0
- package/dist/esm/cli/serverRouteModules.native.js.map +1 -0
- package/dist/esm/cli/workerPool.mjs.map +1 -1
- package/dist/esm/cli/workerPool.native.js.map +1 -1
- package/dist/esm/createApp.mjs +4 -1
- package/dist/esm/createApp.mjs.map +1 -1
- package/dist/esm/fork/useLinking.native.test.mjs +1 -1
- package/dist/esm/getURL.native.test.mjs +1 -1
- package/dist/esm/headless-server.mjs.map +1 -1
- package/dist/esm/headless-server.native.js.map +1 -1
- package/dist/esm/headless.mjs +4 -0
- package/dist/esm/headless.mjs.map +1 -1
- package/dist/esm/headless.native.js +4 -0
- package/dist/esm/headless.native.js.map +1 -1
- package/dist/esm/router/diagnoseRouteLoadFailure.mjs.map +1 -1
- package/dist/esm/router/diagnoseRouteLoadFailure.native.js.map +1 -1
- package/dist/esm/router/hmrImport.native.test.mjs +1 -1
- package/dist/esm/router/routeHmr.native.test.mjs +1 -1
- package/dist/esm/router/routeHmr.native.test.mjs.map +1 -1
- package/dist/esm/router/useViteRoutes.mjs +9 -1
- package/dist/esm/router/useViteRoutes.mjs.map +1 -1
- package/dist/esm/router/useViteRoutes.native.js +9 -1
- package/dist/esm/router/useViteRoutes.native.js.map +1 -1
- package/dist/esm/server/oneServe.mjs +23 -4
- package/dist/esm/server/oneServe.mjs.map +1 -1
- package/dist/esm/server/oneServe.native.js +25 -6
- package/dist/esm/server/oneServe.native.js.map +1 -1
- package/dist/esm/server/routeExportsFromEntry.mjs +21 -0
- package/dist/esm/server/routeExportsFromEntry.mjs.map +1 -0
- package/dist/esm/server/routeExportsFromEntry.native.js +23 -0
- package/dist/esm/server/routeExportsFromEntry.native.js.map +1 -0
- package/dist/esm/server/workerHandler.mjs +19 -6
- package/dist/esm/server/workerHandler.mjs.map +1 -1
- package/dist/esm/server/workerHandler.native.js +20 -6
- package/dist/esm/server/workerHandler.native.js.map +1 -1
- package/dist/esm/server/workerHandler.test.mjs +24 -16
- package/dist/esm/server/workerHandler.test.mjs.map +1 -1
- package/dist/esm/server/workerHandler.test.native.js +27 -16
- package/dist/esm/server/workerHandler.test.native.js.map +1 -1
- package/dist/esm/views/ScrollBehavior.mjs.map +1 -1
- package/dist/esm/views/ScrollBehavior.native.js.map +1 -1
- package/dist/esm/vite/cloudflareWranglerConfig.mjs.map +1 -1
- package/dist/esm/vite/cloudflareWranglerConfig.native.js.map +1 -1
- package/dist/esm/vite/one.mjs +5 -2
- package/dist/esm/vite/one.mjs.map +1 -1
- package/dist/esm/vite/one.native.js +5 -2
- package/dist/esm/vite/one.native.js.map +1 -1
- package/dist/esm/vite/plugins/clientTreeShakePlugin.mjs +5 -3
- package/dist/esm/vite/plugins/clientTreeShakePlugin.mjs.map +1 -1
- package/dist/esm/vite/plugins/clientTreeShakePlugin.native.js +6 -3
- package/dist/esm/vite/plugins/clientTreeShakePlugin.native.js.map +1 -1
- package/dist/esm/vite/plugins/clientTreeShakePlugin.test.mjs +18 -0
- package/dist/esm/vite/plugins/clientTreeShakePlugin.test.mjs.map +1 -1
- package/dist/esm/vite/plugins/clientTreeShakePlugin.test.native.js +18 -0
- package/dist/esm/vite/plugins/clientTreeShakePlugin.test.native.js.map +1 -1
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.mjs +4 -9
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.mjs.map +1 -1
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.native.js +4 -9
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.native.js.map +1 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.mjs +7 -6
- package/dist/esm/vite/plugins/virtualEntryPlugin.mjs.map +1 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.native.js +9 -6
- package/dist/esm/vite/plugins/virtualEntryPlugin.native.js.map +1 -1
- package/dist/esm/vite/plugins/workerdDevPlugin.mjs +0 -13
- package/dist/esm/vite/plugins/workerdDevPlugin.mjs.map +1 -1
- package/dist/esm/vite/plugins/workerdDevPlugin.native.js +26 -58
- package/dist/esm/vite/plugins/workerdDevPlugin.native.js.map +1 -1
- package/package.json +9 -9
- package/src/cli/build.ts +41 -32
- package/src/cli/buildPage.ts +18 -22
- package/src/cli/buildPageWorker.ts +1 -0
- package/src/cli/serverRouteModules.ts +33 -0
- package/src/cli/workerPool.ts +1 -0
- package/src/createApp.tsx +5 -1
- package/src/headless-server.ts +0 -1
- package/src/headless.tsx +5 -0
- package/src/router/diagnoseRouteLoadFailure.ts +3 -1
- package/src/router/useViteRoutes.tsx +9 -1
- package/src/server/oneServe.ts +40 -16
- package/src/server/routeExportsFromEntry.ts +59 -0
- package/src/server/workerHandler.test.ts +21 -16
- package/src/server/workerHandler.ts +25 -7
- package/src/views/ScrollBehavior.tsx +5 -1
- package/src/vite/cloudflareWranglerConfig.ts +8 -4
- package/src/vite/one.ts +8 -3
- package/src/vite/plugins/clientTreeShakePlugin.test.ts +28 -0
- package/src/vite/plugins/clientTreeShakePlugin.ts +17 -4
- package/src/vite/plugins/fileSystemRouterPlugin.tsx +6 -12
- package/src/vite/plugins/virtualEntryPlugin.ts +10 -8
- package/src/vite/plugins/workerdDevPlugin.ts +6 -16
- package/types/cli/build.d.ts.map +1 -1
- package/types/cli/buildPage.d.ts +1 -1
- package/types/cli/buildPage.d.ts.map +1 -1
- package/types/cli/serverRouteModules.d.ts +2 -0
- package/types/cli/serverRouteModules.d.ts.map +1 -0
- package/types/cli/workerPool.d.ts +1 -0
- package/types/cli/workerPool.d.ts.map +1 -1
- package/types/createApp.d.ts.map +1 -1
- package/types/headless-server.d.ts +0 -1
- package/types/headless-server.d.ts.map +1 -1
- package/types/headless.d.ts.map +1 -1
- package/types/router/diagnoseRouteLoadFailure.d.ts.map +1 -1
- package/types/router/useViteRoutes.d.ts.map +1 -1
- package/types/server/oneServe.d.ts +1 -1
- package/types/server/oneServe.d.ts.map +1 -1
- package/types/server/routeExportsFromEntry.d.ts +29 -0
- package/types/server/routeExportsFromEntry.d.ts.map +1 -0
- package/types/server/workerHandler.d.ts +1 -1
- package/types/server/workerHandler.d.ts.map +1 -1
- package/types/views/ScrollBehavior.d.ts.map +1 -1
- package/types/vite/cloudflareWranglerConfig.d.ts.map +1 -1
- package/types/vite/one.d.ts.map +1 -1
- package/types/vite/plugins/clientTreeShakePlugin.d.ts +2 -1
- package/types/vite/plugins/clientTreeShakePlugin.d.ts.map +1 -1
- package/types/vite/plugins/fileSystemRouterPlugin.d.ts.map +1 -1
- package/types/vite/plugins/virtualEntryPlugin.d.ts.map +1 -1
- package/types/vite/plugins/workerdDevPlugin.d.ts.map +1 -1
- package/dist/cjs/vite/replaceLoader.cjs +0 -50
- package/dist/cjs/vite/replaceLoader.native.js +0 -54
- package/dist/cjs/vite/replaceLoader.native.js.map +0 -1
- package/dist/esm/vite/replaceLoader.mjs +0 -25
- package/dist/esm/vite/replaceLoader.mjs.map +0 -1
- package/dist/esm/vite/replaceLoader.native.js +0 -26
- package/dist/esm/vite/replaceLoader.native.js.map +0 -1
- package/src/vite/replaceLoader.ts +0 -39
- package/types/vite/replaceLoader.d.ts +0 -5
- package/types/vite/replaceLoader.d.ts.map +0 -1
package/src/headless.tsx
CHANGED
|
@@ -4,6 +4,7 @@ import type { OneLinkingConfig } from './link/getLinking'
|
|
|
4
4
|
import { Root } from './Root'
|
|
5
5
|
import { resolveClientLoader } from './clientLoaderResolver'
|
|
6
6
|
import { render } from './render'
|
|
7
|
+
import { handleSkewError, isChunkLoadError } from './utils/dynamicImport'
|
|
7
8
|
import { findRootLayout } from './utils/findRootLayout'
|
|
8
9
|
import type { One } from './vite/types'
|
|
9
10
|
|
|
@@ -51,5 +52,9 @@ export function createApp(options: CreateHeadlessAppProps) {
|
|
|
51
52
|
})
|
|
52
53
|
.catch((err) => {
|
|
53
54
|
console.error(`[one/headless] Error during initialization:`, err)
|
|
55
|
+
if (isChunkLoadError(err)) {
|
|
56
|
+
handleSkewError()
|
|
57
|
+
}
|
|
54
58
|
})
|
|
55
59
|
}
|
|
60
|
+
|
|
@@ -28,7 +28,9 @@ function collectImports(source: string, base: string): string[] {
|
|
|
28
28
|
out.push(new URL(spec, base).href)
|
|
29
29
|
} catch {}
|
|
30
30
|
}
|
|
31
|
-
for (const m of source.matchAll(
|
|
31
|
+
for (const m of source.matchAll(
|
|
32
|
+
/(?:^|[\s;}])(?:import|export)[^'"]{0,300}?from\s*["']([^"']+)["']/g
|
|
33
|
+
))
|
|
32
34
|
add(m[1])
|
|
33
35
|
for (const m of source.matchAll(/\bimport\s*\(\s*["']([^"']+)["']\s*\)/g)) add(m[1])
|
|
34
36
|
for (const m of source.matchAll(/(?:^|[\s;}])import\s*["']([^"']+)["']/g)) add(m[1])
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { GlobbedRouteImports } from '../types'
|
|
2
2
|
import type { One } from '../vite/types'
|
|
3
|
+
import { handleSkewError, isChunkLoadError } from '../utils/dynamicImport'
|
|
3
4
|
import { diagnoseRouteLoadFailure } from './diagnoseRouteLoadFailure'
|
|
4
5
|
import { hmrImport } from './hmrImport'
|
|
5
6
|
|
|
@@ -146,7 +147,11 @@ export async function preloadRouteModules(href: string): Promise<void> {
|
|
|
146
147
|
.then((mod: any) => {
|
|
147
148
|
preloadedModules[key] = mod
|
|
148
149
|
})
|
|
149
|
-
.catch(() => {
|
|
150
|
+
.catch((err: any) => {
|
|
151
|
+
if (isChunkLoadError(err)) {
|
|
152
|
+
handleSkewError()
|
|
153
|
+
}
|
|
154
|
+
})
|
|
150
155
|
)
|
|
151
156
|
}
|
|
152
157
|
}
|
|
@@ -284,6 +289,9 @@ export function globbedRoutesToRouteContext(
|
|
|
284
289
|
})
|
|
285
290
|
.catch((err) => {
|
|
286
291
|
console.error(`Error loading route`, id, err, new Error().stack)
|
|
292
|
+
if (isChunkLoadError(err)) {
|
|
293
|
+
handleSkewError()
|
|
294
|
+
}
|
|
287
295
|
// rendering an empty component keeps one bad route from taking down the
|
|
288
296
|
// app, but it also makes the failure invisible: nothing inside the route
|
|
289
297
|
// mounts and the only trace is the line above. in dev, hand it to the
|
package/src/server/oneServe.ts
CHANGED
|
@@ -16,10 +16,12 @@ import {
|
|
|
16
16
|
} from '../createHandleRequest'
|
|
17
17
|
import type { RenderAppProps } from '../types'
|
|
18
18
|
import { getPathFromLoaderPath } from '../utils/cleanUrl'
|
|
19
|
+
import { getRouterRootFromOneOptions } from '../utils/getRouterRootFromOneOptions'
|
|
19
20
|
import { toAbsoluteUrl } from '../utils/toAbsolute'
|
|
20
21
|
import { toServerOutputPath } from '../utils/toServerOutputPath'
|
|
21
22
|
import type { One } from '../vite/types'
|
|
22
23
|
import type { RouteInfoCompiled } from './createRoutesManifest'
|
|
24
|
+
import { getRouteExportsFromEntry } from './routeExportsFromEntry'
|
|
23
25
|
import { setSSRLoaderData } from './ssrLoaderData'
|
|
24
26
|
import { getFetchStaticHtml } from './staticHtmlFetcher'
|
|
25
27
|
|
|
@@ -74,8 +76,8 @@ async function readStaticHtml(htmlPath: string, outDir = 'dist'): Promise<string
|
|
|
74
76
|
* Modules are loaded on-demand when a route is matched, not all upfront.
|
|
75
77
|
*/
|
|
76
78
|
type LazyRoutes = {
|
|
79
|
+
pages?: Record<string, () => Promise<any>>
|
|
77
80
|
serverEntry: () => Promise<{ default: { render: (props: any) => any } }>
|
|
78
|
-
pages: Record<string, () => Promise<any>>
|
|
79
81
|
api: Record<string, () => Promise<any>>
|
|
80
82
|
middlewares: Record<string, () => Promise<any>>
|
|
81
83
|
}
|
|
@@ -150,6 +152,7 @@ export async function oneServe(
|
|
|
150
152
|
}
|
|
151
153
|
|
|
152
154
|
const apiCJS = oneOptions.build?.api?.outputFormat === 'cjs'
|
|
155
|
+
const routerRoot = getRouterRootFromOneOptions(oneOptions)
|
|
153
156
|
|
|
154
157
|
// pre-computed constants to avoid per-request overhead
|
|
155
158
|
const useStreaming = !process.env.ONE_BUFFERED_SSR
|
|
@@ -169,6 +172,26 @@ export async function oneServe(
|
|
|
169
172
|
{ promise: Promise<any>; expires: number }
|
|
170
173
|
>()
|
|
171
174
|
|
|
175
|
+
// route modules are resolved through the built server entry, see
|
|
176
|
+
// routeExportsFromEntry
|
|
177
|
+
async function importRouteModule(
|
|
178
|
+
lazyKey: string | undefined,
|
|
179
|
+
serverPath: string | undefined
|
|
180
|
+
): Promise<any> {
|
|
181
|
+
if (lazyKey && options?.lazyRoutes?.pages?.[lazyKey]) {
|
|
182
|
+
return await options.lazyRoutes.pages[lazyKey]()
|
|
183
|
+
}
|
|
184
|
+
if (lazyKey) {
|
|
185
|
+
const entry = await loadServerEntry()
|
|
186
|
+
const exported = await getRouteExportsFromEntry(entry, routerRoot, lazyKey)
|
|
187
|
+
if (exported) return exported
|
|
188
|
+
}
|
|
189
|
+
// layouts and middlewares outside the router root still resolve by path
|
|
190
|
+
return await import(
|
|
191
|
+
toAbsoluteUrl(toServerOutputPath(serverPath || lazyKey || '', outDir))
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
|
|
172
195
|
// resolve a route module's loader - sync on cache hit, async on cold start
|
|
173
196
|
function resolveLoaderSync(
|
|
174
197
|
serverPath: string | undefined,
|
|
@@ -180,18 +203,11 @@ export async function oneServe(
|
|
|
180
203
|
|
|
181
204
|
// cold path - async import
|
|
182
205
|
return (async () => {
|
|
183
|
-
const pathToResolve = serverPath || lazyKey || ''
|
|
184
|
-
const resolvedPath = toServerOutputPath(pathToResolve, outDir)
|
|
185
|
-
|
|
186
206
|
let routeExported: any
|
|
187
207
|
if (moduleImportCache.has(cacheKey)) {
|
|
188
208
|
routeExported = moduleImportCache.get(cacheKey)
|
|
189
209
|
} else {
|
|
190
|
-
routeExported = lazyKey
|
|
191
|
-
? options?.lazyRoutes?.pages?.[lazyKey]
|
|
192
|
-
? await options.lazyRoutes.pages[lazyKey]()
|
|
193
|
-
: await import(toAbsoluteUrl(resolvedPath))
|
|
194
|
-
: await import(toAbsoluteUrl(serverPath!))
|
|
210
|
+
routeExported = await importRouteModule(lazyKey, serverPath)
|
|
195
211
|
setBounded(moduleImportCache, cacheKey, routeExported, MODULE_CACHE_MAX)
|
|
196
212
|
}
|
|
197
213
|
|
|
@@ -286,18 +302,26 @@ export async function oneServe(
|
|
|
286
302
|
let render: ((props: RenderAppProps) => any) | null = null
|
|
287
303
|
let renderStream: ((props: RenderAppProps) => Promise<ReadableStream>) | null = null
|
|
288
304
|
let renderLoading: Promise<void> | null = null
|
|
305
|
+
let entryLoading: Promise<any> | null = null
|
|
289
306
|
|
|
290
|
-
function
|
|
291
|
-
if (
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
? await options.lazyRoutes.serverEntry()
|
|
296
|
-
: await import(
|
|
307
|
+
function loadServerEntry(): Promise<any> {
|
|
308
|
+
if (!entryLoading) {
|
|
309
|
+
entryLoading = options?.lazyRoutes?.serverEntry
|
|
310
|
+
? options.lazyRoutes.serverEntry()
|
|
311
|
+
: import(
|
|
297
312
|
toAbsoluteUrl(
|
|
298
313
|
`${serverOptions.root}/${outDir}/server/_virtual_one-entry.${typeof oneOptions.build?.server === 'object' && oneOptions.build.server.outputFormat === 'cjs' ? 'c' : ''}js`
|
|
299
314
|
)
|
|
300
315
|
)
|
|
316
|
+
}
|
|
317
|
+
return entryLoading
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function ensureRenderLoaded(): void | Promise<void> {
|
|
321
|
+
if (render) return // sync!
|
|
322
|
+
if (renderLoading) return renderLoading
|
|
323
|
+
renderLoading = (async () => {
|
|
324
|
+
const entry = await loadServerEntry()
|
|
301
325
|
render = entry.default.render as (props: RenderAppProps) => any
|
|
302
326
|
renderStream = entry.default.renderStream as
|
|
303
327
|
| ((props: RenderAppProps) => Promise<ReadableStream>)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* route modules have to be read through the built server entry's own route map,
|
|
3
|
+
* never by importing whichever output chunk happens to contain them.
|
|
4
|
+
*
|
|
5
|
+
* a bundler makes no promise that a chunk re-exports a module's bindings under
|
|
6
|
+
* their source names. when a route is both dynamically imported by the entry and
|
|
7
|
+
* statically imported by another route (docs pages mirrored under a second url,
|
|
8
|
+
* say), or when the app sets `output.strictExecutionOrder`, rolldown emits the
|
|
9
|
+
* chunk as
|
|
10
|
+
*
|
|
11
|
+
* export { loader as a, init__slug_ as i, _slug__exports as n, generateStaticParams as r }
|
|
12
|
+
*
|
|
13
|
+
* so every read by source name comes back undefined: the build then reports a
|
|
14
|
+
* route that exports generateStaticParams as missing it, and any loader on that
|
|
15
|
+
* route silently stops running.
|
|
16
|
+
*
|
|
17
|
+
* the entry's `import.meta.glob` map is written by the bundler itself, which
|
|
18
|
+
* rewrites each entry to whatever preserves the real namespace
|
|
19
|
+
* (`import(chunk).then((n) => (n.i(), n.n))` for the wrapped case above). so it
|
|
20
|
+
* resolves correctly no matter how the chunking lands.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/** the key the entry's globs use: `./posts/[slug]+ssg.tsx` -> `/app/posts/[slug]+ssg.tsx` */
|
|
24
|
+
export function routeEntryKey(routerRoot: string, routeFile: string) {
|
|
25
|
+
return `/${routerRoot}/${routeFile.replace(/^\.?\//, '')}`
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* resolve one route's exports out of an already-loaded server entry namespace.
|
|
30
|
+
* returns null when the entry has no such route.
|
|
31
|
+
*/
|
|
32
|
+
export async function getRouteExportsFromEntry(
|
|
33
|
+
entry: any,
|
|
34
|
+
routerRoot: string,
|
|
35
|
+
routeFile: string
|
|
36
|
+
): Promise<Record<string, any> | null> {
|
|
37
|
+
const key = routeEntryKey(routerRoot, routeFile)
|
|
38
|
+
|
|
39
|
+
// a route that declares spa by filename or parent directory is stubbed out of
|
|
40
|
+
// the route map, so the server never holds its page component. every stubbed
|
|
41
|
+
// route has an entry in this parallel per-export map whether or not it
|
|
42
|
+
// actually exports a loader, which is what tells a stub from a real route. a
|
|
43
|
+
// route that is spa only because of `web.defaultRenderMode` is never stubbed.
|
|
44
|
+
const spaExports = entry?.oneServerSpaRouteExports
|
|
45
|
+
if (spaExports?.loader && key in spaExports.loader) {
|
|
46
|
+
const [loader, loaderCache, generateStaticParams, sitemap] = await Promise.all([
|
|
47
|
+
spaExports.loader[key](),
|
|
48
|
+
spaExports.loaderCache?.[key]?.(),
|
|
49
|
+
spaExports.generateStaticParams?.[key]?.(),
|
|
50
|
+
spaExports.sitemap?.[key]?.(),
|
|
51
|
+
])
|
|
52
|
+
return { loader, loaderCache, generateStaticParams, sitemap }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// some output formats nest the entry default one level deeper
|
|
56
|
+
const app = entry?.default?.options ? entry.default : entry?.default?.default
|
|
57
|
+
const importRoute = app?.options?.routes?.[key]
|
|
58
|
+
return importRoute ? await importRoute() : null
|
|
59
|
+
}
|
|
@@ -2,8 +2,9 @@ import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
|
2
2
|
import type { One } from '../vite/types'
|
|
3
3
|
import { createWorkerHandler, type LazyRoutes } from './workerHandler'
|
|
4
4
|
|
|
5
|
+
// route files are router-root relative, the way createRoutesManifest emits them
|
|
5
6
|
const pageRoute = {
|
|
6
|
-
file: '
|
|
7
|
+
file: './some-page.tsx',
|
|
7
8
|
page: '/some-page',
|
|
8
9
|
namedRegex: '^/some-page(?:/)?$',
|
|
9
10
|
urlPath: '/some-page',
|
|
@@ -14,7 +15,7 @@ const pageRoute = {
|
|
|
14
15
|
} satisfies One.BuildInfo['manifest']['pageRoutes'][number]
|
|
15
16
|
|
|
16
17
|
const apiRoute = {
|
|
17
|
-
file: '
|
|
18
|
+
file: './api/status+api.ts',
|
|
18
19
|
page: '/api/status',
|
|
19
20
|
namedRegex: '^/api/status(?:/)?$',
|
|
20
21
|
urlPath: '/api/status',
|
|
@@ -57,15 +58,21 @@ const buildInfo = {
|
|
|
57
58
|
loaders: {},
|
|
58
59
|
} satisfies One.BuildInfo
|
|
59
60
|
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
// route modules are reached through the server entry's own route map, keyed by
|
|
62
|
+
// the router-root prefixed path its `import.meta.glob` produces
|
|
63
|
+
const routeKey = `/app/${pageRoute.file.slice(2)}`
|
|
64
|
+
|
|
65
|
+
const makeServerEntry =
|
|
66
|
+
(importPage: () => Promise<any> = async () => ({})) =>
|
|
67
|
+
async () => ({
|
|
62
68
|
default: {
|
|
63
69
|
render: () => '<html></html>',
|
|
70
|
+
options: { routes: { [routeKey]: importPage } },
|
|
64
71
|
},
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
const lazyRoutes = {
|
|
75
|
+
serverEntry: makeServerEntry(),
|
|
69
76
|
api: {
|
|
70
77
|
[apiRoute.page]: async () => ({
|
|
71
78
|
HEAD: () => new Response(null, { status: 204 }),
|
|
@@ -77,7 +84,7 @@ const lazyRoutes = {
|
|
|
77
84
|
function createHandler() {
|
|
78
85
|
vi.stubEnv('ONE_BUFFERED_SSR', '1')
|
|
79
86
|
return createWorkerHandler({
|
|
80
|
-
oneOptions: { web: { defaultRenderMode: 'ssr' } },
|
|
87
|
+
oneOptions: { router: { root: 'app' }, web: { defaultRenderMode: 'ssr' } },
|
|
81
88
|
buildInfo,
|
|
82
89
|
lazyRoutes,
|
|
83
90
|
}).handleRequest
|
|
@@ -127,17 +134,15 @@ describe('createWorkerHandler', () => {
|
|
|
127
134
|
vi.stubEnv('ONE_BUFFERED_SSR', '1')
|
|
128
135
|
let imports = 0
|
|
129
136
|
const handleRequest = createWorkerHandler({
|
|
130
|
-
oneOptions: { web: { defaultRenderMode: 'ssr' } },
|
|
137
|
+
oneOptions: { router: { root: 'app' }, web: { defaultRenderMode: 'ssr' } },
|
|
131
138
|
buildInfo,
|
|
132
139
|
disableModuleCache: true,
|
|
133
140
|
lazyRoutes: {
|
|
134
141
|
...lazyRoutes,
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
},
|
|
140
|
-
},
|
|
142
|
+
serverEntry: makeServerEntry(async () => {
|
|
143
|
+
imports += 1
|
|
144
|
+
return {}
|
|
145
|
+
}),
|
|
141
146
|
},
|
|
142
147
|
}).handleRequest
|
|
143
148
|
|
|
@@ -15,21 +15,23 @@ import {
|
|
|
15
15
|
} from '../createHandleRequest'
|
|
16
16
|
import type { RenderAppProps } from '../types'
|
|
17
17
|
import { getPathFromLoaderPath } from '../utils/cleanUrl'
|
|
18
|
+
import { getRouterRootFromOneOptions } from '../utils/getRouterRootFromOneOptions'
|
|
18
19
|
import { isResponse } from '../utils/isResponse'
|
|
19
20
|
import { resolveResponse } from '../vite/resolveResponse'
|
|
20
21
|
import type { One } from '../vite/types'
|
|
21
22
|
import type { RouteInfoCompiled } from './createRoutesManifest'
|
|
23
|
+
import { getRouteExportsFromEntry } from './routeExportsFromEntry'
|
|
22
24
|
import { setSSRLoaderData } from './ssrLoaderData'
|
|
23
25
|
import { getFetchStaticHtml } from './staticHtmlFetcher'
|
|
24
26
|
|
|
25
27
|
export type LazyRoutes = {
|
|
28
|
+
pages?: Record<string, () => Promise<any>>
|
|
26
29
|
serverEntry: () => Promise<{
|
|
27
30
|
default: {
|
|
28
31
|
render: (props: any) => any
|
|
29
32
|
renderStream?: (props: any) => Promise<ReadableStream>
|
|
30
33
|
}
|
|
31
34
|
}>
|
|
32
|
-
pages: Record<string, () => Promise<any>>
|
|
33
35
|
api: Record<string, () => Promise<any>>
|
|
34
36
|
middlewares: Record<string, () => Promise<any>>
|
|
35
37
|
}
|
|
@@ -46,6 +48,7 @@ type WorkerHandlerOptions = {
|
|
|
46
48
|
export function createWorkerHandler(options: WorkerHandlerOptions) {
|
|
47
49
|
const { oneOptions } = options
|
|
48
50
|
const disableModuleCache = !!options.disableModuleCache
|
|
51
|
+
const routerRoot = getRouterRootFromOneOptions(oneOptions)
|
|
49
52
|
|
|
50
53
|
// mutable state for route swapping
|
|
51
54
|
let currentLazyRoutes = options.lazyRoutes
|
|
@@ -95,13 +98,21 @@ export function createWorkerHandler(options: WorkerHandlerOptions) {
|
|
|
95
98
|
let renderStream: ((props: RenderAppProps) => Promise<ReadableStream>) | null = null
|
|
96
99
|
let renderLoading: Promise<void> | null = null
|
|
97
100
|
let renderGeneration = 0
|
|
101
|
+
let entryLoading: Promise<any> | null = null
|
|
102
|
+
|
|
103
|
+
// route modules are resolved through the built server entry, see
|
|
104
|
+
// routeExportsFromEntry
|
|
105
|
+
function loadServerEntry(): Promise<any> {
|
|
106
|
+
if (!entryLoading) entryLoading = currentLazyRoutes.serverEntry()
|
|
107
|
+
return entryLoading
|
|
108
|
+
}
|
|
98
109
|
|
|
99
110
|
function ensureRenderLoaded(): void | Promise<void> {
|
|
100
111
|
if (render) return
|
|
101
112
|
if (renderLoading) return renderLoading
|
|
102
113
|
const gen = ++renderGeneration
|
|
103
114
|
renderLoading = (async () => {
|
|
104
|
-
const entry = await
|
|
115
|
+
const entry = await loadServerEntry()
|
|
105
116
|
// if updateRoutes was called while we were loading, discard stale entry
|
|
106
117
|
if (gen !== renderGeneration) return
|
|
107
118
|
render = entry.default.render as any
|
|
@@ -150,13 +161,19 @@ export function createWorkerHandler(options: WorkerHandlerOptions) {
|
|
|
150
161
|
let routeExported: any
|
|
151
162
|
if (!disableModuleCache && moduleImportCache.has(cacheKey)) {
|
|
152
163
|
routeExported = moduleImportCache.get(cacheKey)
|
|
153
|
-
} else if (
|
|
154
|
-
routeExported = await currentLazyRoutes.pages[
|
|
164
|
+
} else if (currentLazyRoutes.pages?.[cacheKey]) {
|
|
165
|
+
routeExported = await currentLazyRoutes.pages[cacheKey]()
|
|
155
166
|
if (!disableModuleCache) moduleImportCache.set(cacheKey, routeExported)
|
|
156
167
|
} else {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
168
|
+
routeExported = lazyKey
|
|
169
|
+
? await getRouteExportsFromEntry(await loadServerEntry(), routerRoot, lazyKey)
|
|
170
|
+
: null
|
|
171
|
+
if (!routeExported) {
|
|
172
|
+
console.warn(`[one/worker] no lazy route for ${cacheKey}`)
|
|
173
|
+
if (!disableModuleCache) loaderCache.set(cacheKey, null)
|
|
174
|
+
return null
|
|
175
|
+
}
|
|
176
|
+
if (!disableModuleCache) moduleImportCache.set(cacheKey, routeExported)
|
|
160
177
|
}
|
|
161
178
|
|
|
162
179
|
const loader = routeExported?.loader || null
|
|
@@ -797,6 +814,7 @@ export function createWorkerHandler(options: WorkerHandlerOptions) {
|
|
|
797
814
|
render = null
|
|
798
815
|
renderStream = null
|
|
799
816
|
renderLoading = null
|
|
817
|
+
entryLoading = null
|
|
800
818
|
}
|
|
801
819
|
|
|
802
820
|
return { handleRequest, updateRoutes }
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { useEffect } from 'react'
|
|
2
2
|
import { setLastAction } from '../router/lastAction'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
routeInfo,
|
|
5
|
+
subscribeToLoadingState,
|
|
6
|
+
subscribeToRootState,
|
|
7
|
+
} from '../router/router'
|
|
4
8
|
|
|
5
9
|
const KEY = 'one-sr'
|
|
6
10
|
const GROUP_KEY = 'one-sr-groups'
|
|
@@ -122,9 +122,10 @@ export function hasUserWranglerConfig(root: string): boolean {
|
|
|
122
122
|
return false
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
function parseUserWranglerFile(
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
function parseUserWranglerFile(configPath: string): {
|
|
126
|
+
path: string
|
|
127
|
+
config: Record<string, JsonValue>
|
|
128
|
+
} {
|
|
128
129
|
const contents = readFileSync(configPath, 'utf-8')
|
|
129
130
|
let parsed: unknown
|
|
130
131
|
try {
|
|
@@ -242,7 +243,10 @@ export function isExperimentalWorkerDevEnabled(): boolean {
|
|
|
242
243
|
|
|
243
244
|
export function shouldEnableWorkerdDev(deploy: unknown, root: string): boolean {
|
|
244
245
|
if (!isExperimentalWorkerDevEnabled()) return false
|
|
245
|
-
const target =
|
|
246
|
+
const target =
|
|
247
|
+
typeof deploy === 'string'
|
|
248
|
+
? deploy
|
|
249
|
+
: (deploy as { target?: string } | undefined)?.target
|
|
246
250
|
if (target === 'cloudflare') return true
|
|
247
251
|
return hasUserWranglerConfig(root)
|
|
248
252
|
}
|
package/src/vite/one.ts
CHANGED
|
@@ -34,7 +34,10 @@ import { SSRCSSPlugin } from './plugins/SSRCSSPlugin'
|
|
|
34
34
|
import { virtualEntryId } from './plugins/virtualEntryConstants'
|
|
35
35
|
import { createVirtualEntry } from './plugins/virtualEntryPlugin'
|
|
36
36
|
import { environmentGuardPlugin } from './plugins/environmentGuardPlugin'
|
|
37
|
-
import {
|
|
37
|
+
import {
|
|
38
|
+
createWorkerdDevPlugins,
|
|
39
|
+
shouldEnableWorkerdDev,
|
|
40
|
+
} from './plugins/workerdDevPlugin'
|
|
38
41
|
import type { One } from './types'
|
|
39
42
|
|
|
40
43
|
type MetroOptions = MetroPluginOptions
|
|
@@ -837,11 +840,13 @@ export function one(options: One.PluginOptions = {}): PluginOption {
|
|
|
837
840
|
] satisfies Plugin[]
|
|
838
841
|
|
|
839
842
|
// TODO move to single config and through environments
|
|
840
|
-
const nativeWebDevAndProdPlugsin: Plugin[] = [clientTreeShakePlugin()]
|
|
843
|
+
const nativeWebDevAndProdPlugsin: Plugin[] = [clientTreeShakePlugin({ routerRoot })]
|
|
841
844
|
|
|
842
845
|
// TODO make this passed into vxrn through real API
|
|
843
846
|
if (!nativeDisabled) {
|
|
844
|
-
globalThis.__vxrnAddNativePlugins = [
|
|
847
|
+
globalThis.__vxrnAddNativePlugins = [
|
|
848
|
+
clientTreeShakePlugin({ runtime: 'rolldown', routerRoot }),
|
|
849
|
+
]
|
|
845
850
|
}
|
|
846
851
|
globalThis.__vxrnAddWebPluginsProd = devAndProdPlugins
|
|
847
852
|
|
|
@@ -148,6 +148,34 @@ export default function Layout() {
|
|
|
148
148
|
expect(result!.code).not.toContain('__vxrn__loader__')
|
|
149
149
|
})
|
|
150
150
|
|
|
151
|
+
it('should strip a custom router root from the loader stub routeId', async () => {
|
|
152
|
+
const code = `
|
|
153
|
+
import { serverOnlyModule } from 'server-only-pkg'
|
|
154
|
+
import { useLoader } from 'one'
|
|
155
|
+
|
|
156
|
+
export const loader = async () => {
|
|
157
|
+
return serverOnlyModule()
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export default function Page() {
|
|
161
|
+
const data = useLoader(loader)
|
|
162
|
+
return data
|
|
163
|
+
}
|
|
164
|
+
`
|
|
165
|
+
const result = await transformTreeShakeClient(
|
|
166
|
+
code,
|
|
167
|
+
'/project/app-sootsim/(marketing)/changelog/index+ssg.tsx',
|
|
168
|
+
'/project',
|
|
169
|
+
'app-sootsim'
|
|
170
|
+
)
|
|
171
|
+
expect(result).toBeDefined()
|
|
172
|
+
// buildPage looks the stub up by the route contextKey, which is relative
|
|
173
|
+
// to the configured router root rather than to a hardcoded app/
|
|
174
|
+
expect(result!.code).toContain(
|
|
175
|
+
'export function loader() {return "./(marketing)/changelog/index+ssg.tsx"}'
|
|
176
|
+
)
|
|
177
|
+
})
|
|
178
|
+
|
|
151
179
|
it('should embed routeId with render mode suffix in loader stub', async () => {
|
|
152
180
|
const code = `
|
|
153
181
|
import { serverOnlyModule } from 'server-only-pkg'
|
|
@@ -54,8 +54,13 @@ function restoreTypeImports(ast: t.File, typeImports: t.ImportDeclaration[]) {
|
|
|
54
54
|
export const clientTreeShakePlugin = (opts?: {
|
|
55
55
|
// 'rolldown' when used in the native rolldown DevEngine (no vite environment context)
|
|
56
56
|
runtime?: 'vite' | 'rolldown'
|
|
57
|
+
// the configured router root (One.PluginOptions.router.root), relative to the
|
|
58
|
+
// project root. the loader stub's routeId is built off it, so it must be the
|
|
59
|
+
// real one or buildPage cannot match the stub back to the route.
|
|
60
|
+
routerRoot?: string
|
|
57
61
|
}): Plugin => {
|
|
58
62
|
const runtime = opts?.runtime ?? 'vite'
|
|
63
|
+
const routerRoot = opts?.routerRoot ?? 'app'
|
|
59
64
|
|
|
60
65
|
return {
|
|
61
66
|
name: 'one-client-tree-shake',
|
|
@@ -81,7 +86,7 @@ export const clientTreeShakePlugin = (opts?: {
|
|
|
81
86
|
return
|
|
82
87
|
}
|
|
83
88
|
|
|
84
|
-
const out = await transformTreeShakeClient(code, id, process.cwd())
|
|
89
|
+
const out = await transformTreeShakeClient(code, id, process.cwd(), routerRoot)
|
|
85
90
|
|
|
86
91
|
return out
|
|
87
92
|
},
|
|
@@ -89,7 +94,12 @@ export const clientTreeShakePlugin = (opts?: {
|
|
|
89
94
|
} satisfies Plugin
|
|
90
95
|
}
|
|
91
96
|
|
|
92
|
-
export async function transformTreeShakeClient(
|
|
97
|
+
export async function transformTreeShakeClient(
|
|
98
|
+
code: string,
|
|
99
|
+
id: string,
|
|
100
|
+
root?: string,
|
|
101
|
+
routerRoot = 'app'
|
|
102
|
+
) {
|
|
93
103
|
if (!/generateStaticParams|loader/.test(code)) {
|
|
94
104
|
return
|
|
95
105
|
}
|
|
@@ -199,10 +209,13 @@ export async function transformTreeShakeClient(code: string, id: string, root?:
|
|
|
199
209
|
.map((key) => {
|
|
200
210
|
if (key === 'loader') {
|
|
201
211
|
if (root) {
|
|
202
|
-
// compute routeId relative to the
|
|
212
|
+
// compute routeId relative to the router root so it matches the
|
|
213
|
+
// route contextKey format buildPage looks the stub up by.
|
|
203
214
|
// contextKeys are like "./_layout.tsx", "./matches-test/page1+ssg.tsx"
|
|
204
215
|
const fromRoot = relative(root, id).replace(/\\/g, '/')
|
|
205
|
-
const
|
|
216
|
+
const prefix = routerRoot.replace(/^\.\//, '').replace(/\/$/, '') + '/'
|
|
217
|
+
const routeId =
|
|
218
|
+
'./' + (fromRoot.startsWith(prefix) ? fromRoot.slice(prefix.length) : fromRoot)
|
|
206
219
|
return makeLoaderRouteIdStub(routeId)
|
|
207
220
|
}
|
|
208
221
|
return EMPTY_LOADER_STRING
|
|
@@ -18,7 +18,6 @@ import { promiseWithResolvers } from '../../utils/promiseWithResolvers'
|
|
|
18
18
|
import type { RouteIndex } from '../../utils/routeIndex'
|
|
19
19
|
import { isRouteFileWatchEvent } from '../../utils/routeFileWatch'
|
|
20
20
|
import { trackLoaderDependencies } from '../../utils/trackLoaderDependencies'
|
|
21
|
-
import { replaceLoader } from '../../vite/replaceLoader'
|
|
22
21
|
import type { One, RouteInfo } from '../../vite/types'
|
|
23
22
|
import { setServerContext } from '../one-server-only'
|
|
24
23
|
import { virtalEntryIdClient, virtualEntryId } from './virtualEntryConstants'
|
|
@@ -561,14 +560,6 @@ export function createFileSystemRouterPlugin(
|
|
|
561
560
|
}
|
|
562
561
|
}
|
|
563
562
|
|
|
564
|
-
if (loaderData) {
|
|
565
|
-
// add loader back in!
|
|
566
|
-
transformedJS = replaceLoader({
|
|
567
|
-
code: transformedJS,
|
|
568
|
-
loaderData,
|
|
569
|
-
})
|
|
570
|
-
}
|
|
571
|
-
|
|
572
563
|
const platform = url.searchParams.get('platform')
|
|
573
564
|
|
|
574
565
|
if (platform === 'ios' || platform === 'android' || platform === 'native') {
|
|
@@ -582,10 +573,13 @@ export function createFileSystemRouterPlugin(
|
|
|
582
573
|
)
|
|
583
574
|
}
|
|
584
575
|
|
|
585
|
-
|
|
586
|
-
|
|
576
|
+
return `exports.loader = () => (${JSON.stringify(loaderData)});`
|
|
577
|
+
}
|
|
587
578
|
|
|
588
|
-
|
|
579
|
+
if (loaderData) {
|
|
580
|
+
// the client only reads loader() off this module, so serve the data
|
|
581
|
+
// alone instead of the whole route module with its stub rewritten
|
|
582
|
+
return `export function loader(){return ${JSON.stringify(loaderData)}}`
|
|
589
583
|
}
|
|
590
584
|
|
|
591
585
|
return transformedJS
|
|
@@ -211,12 +211,12 @@ export function createVirtualEntry(options: {
|
|
|
211
211
|
const serverSpaBuildGlobs = serverSpaRouteFiles.map(
|
|
212
212
|
(file) => `/${options.root}/${file}`
|
|
213
213
|
)
|
|
214
|
+
const serverSpaExportGlob = (name: string) =>
|
|
215
|
+
` ${name}: import.meta.glob(${JSON.stringify(serverSpaBuildGlobs)}, { exhaustive: true, import: '${name}', query: '?one-spa-build' })`
|
|
214
216
|
const serverSpaBuildRoutes = serverSpaBuildGlobs.length
|
|
215
|
-
? `{
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
sitemap: import.meta.glob(${JSON.stringify(serverSpaBuildGlobs)}, { exhaustive: true, import: 'sitemap', query: '?one-spa-build' })
|
|
219
|
-
}`
|
|
217
|
+
? `{\n${['loader', 'loaderCache', 'generateStaticParams', 'sitemap']
|
|
218
|
+
.map(serverSpaExportGlob)
|
|
219
|
+
.join(',\n')}\n}`
|
|
220
220
|
: '{}'
|
|
221
221
|
const webRouteGlobs = [
|
|
222
222
|
...routeGlobs,
|
|
@@ -301,9 +301,11 @@ if (typeof window !== 'undefined') {
|
|
|
301
301
|
window.__oneRegisterPreloadedRoute = registerPreloadedRoute
|
|
302
302
|
}
|
|
303
303
|
|
|
304
|
-
//
|
|
305
|
-
//
|
|
306
|
-
export
|
|
304
|
+
// a route that declares spa by filename or parent directory is stubbed out of
|
|
305
|
+
// the route map below so the server never holds its page component. its
|
|
306
|
+
// server-side exports come from here instead, one glob per export so the page
|
|
307
|
+
// never comes with them.
|
|
308
|
+
export const oneServerSpaRouteExports = ${serverSpaBuildRoutes}
|
|
307
309
|
|
|
308
310
|
// globbing ${JSON.stringify(webRouteGlobs)}
|
|
309
311
|
export default createApp({
|