@tanstack/start-plugin-core 1.131.7 → 1.132.0-alpha.0
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/esm/{nitro-plugin/build-sitemap.d.ts → build-sitemap.d.ts} +3 -3
- package/dist/esm/{nitro-plugin/build-sitemap.js → build-sitemap.js} +19 -24
- package/dist/esm/build-sitemap.js.map +1 -0
- package/dist/esm/compilers.js +7 -10
- package/dist/esm/compilers.js.map +1 -1
- package/dist/esm/constants.d.ts +6 -2
- package/dist/esm/constants.js +7 -10
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/debug.js.map +1 -1
- package/dist/esm/dev-server-plugin/extract-html-scripts.js.map +1 -1
- package/dist/esm/dev-server-plugin/plugin.d.ts +5 -5
- package/dist/esm/dev-server-plugin/plugin.js +117 -79
- package/dist/esm/dev-server-plugin/plugin.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +0 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/load-env-plugin/plugin.d.ts +2 -3
- package/dist/esm/load-env-plugin/plugin.js +5 -8
- package/dist/esm/load-env-plugin/plugin.js.map +1 -1
- package/dist/esm/output-directory.d.ts +3 -0
- package/dist/esm/output-directory.js +14 -0
- package/dist/esm/output-directory.js.map +1 -0
- package/dist/esm/plugin.d.ts +6 -290
- package/dist/esm/plugin.js +123 -76
- package/dist/esm/plugin.js.map +1 -1
- package/dist/esm/post-server-build.d.ts +7 -0
- package/dist/esm/post-server-build.js +55 -0
- package/dist/esm/post-server-build.js.map +1 -0
- package/dist/esm/prerender.d.ts +11 -0
- package/dist/esm/{nitro-plugin/prerender.js → prerender.js} +85 -73
- package/dist/esm/prerender.js.map +1 -0
- package/dist/esm/{nitro-plugin/queue.js → queue.js} +7 -10
- package/dist/esm/queue.js.map +1 -0
- package/dist/esm/resolve-entries.d.ts +8 -0
- package/dist/esm/resolve-entries.js +37 -0
- package/dist/esm/resolve-entries.js.map +1 -0
- package/dist/esm/schema.d.ts +1369 -6719
- package/dist/esm/schema.js +52 -85
- package/dist/esm/schema.js.map +1 -1
- package/dist/esm/start-compiler-plugin.js +2 -2
- package/dist/esm/start-compiler-plugin.js.map +1 -1
- package/dist/esm/start-manifest-plugin/plugin.d.ts +1 -1
- package/dist/esm/start-manifest-plugin/plugin.js +8 -13
- package/dist/esm/start-manifest-plugin/plugin.js.map +1 -1
- package/dist/esm/start-router-plugin/generator-plugins/routes-manifest-plugin.js +2 -3
- package/dist/esm/start-router-plugin/generator-plugins/routes-manifest-plugin.js.map +1 -1
- package/dist/esm/start-router-plugin/generator-plugins/server-routes-plugin.js +2 -4
- package/dist/esm/start-router-plugin/generator-plugins/server-routes-plugin.js.map +1 -1
- package/dist/esm/start-router-plugin/plugin.js.map +1 -1
- package/dist/esm/start-router-plugin/route-tree-client-plugin.js.map +1 -1
- package/dist/esm/start-router-plugin/virtual-route-tree-plugin.js.map +1 -1
- package/dist/esm/utils.js.map +1 -1
- package/package.json +13 -18
- package/src/{nitro-plugin/build-sitemap.ts → build-sitemap.ts} +8 -8
- package/src/constants.ts +12 -9
- package/src/dev-server-plugin/plugin.ts +140 -99
- package/src/global.d.ts +0 -2
- package/src/index.ts +1 -5
- package/src/load-env-plugin/plugin.ts +6 -11
- package/src/output-directory.ts +18 -0
- package/src/plugin.ts +160 -98
- package/src/post-server-build.ts +73 -0
- package/src/{nitro-plugin/prerender.ts → prerender.ts} +93 -86
- package/src/resolve-entries.ts +52 -0
- package/src/schema.ts +88 -121
- package/src/start-manifest-plugin/plugin.ts +8 -14
- package/dist/cjs/compilers.cjs +0 -416
- package/dist/cjs/compilers.cjs.map +0 -1
- package/dist/cjs/compilers.d.cts +0 -21
- package/dist/cjs/constants.cjs +0 -20
- package/dist/cjs/constants.cjs.map +0 -1
- package/dist/cjs/constants.d.cts +0 -6
- package/dist/cjs/debug.cjs +0 -5
- package/dist/cjs/debug.cjs.map +0 -1
- package/dist/cjs/debug.d.cts +0 -1
- package/dist/cjs/dev-server-plugin/extract-html-scripts.cjs +0 -35
- package/dist/cjs/dev-server-plugin/extract-html-scripts.cjs.map +0 -1
- package/dist/cjs/dev-server-plugin/extract-html-scripts.d.cts +0 -4
- package/dist/cjs/dev-server-plugin/plugin.cjs +0 -121
- package/dist/cjs/dev-server-plugin/plugin.cjs.map +0 -1
- package/dist/cjs/dev-server-plugin/plugin.d.cts +0 -5
- package/dist/cjs/index.cjs +0 -11
- package/dist/cjs/index.cjs.map +0 -1
- package/dist/cjs/index.d.cts +0 -3
- package/dist/cjs/load-env-plugin/plugin.cjs +0 -34
- package/dist/cjs/load-env-plugin/plugin.cjs.map +0 -1
- package/dist/cjs/load-env-plugin/plugin.d.cts +0 -3
- package/dist/cjs/nitro-plugin/build-sitemap.cjs +0 -138
- package/dist/cjs/nitro-plugin/build-sitemap.cjs.map +0 -1
- package/dist/cjs/nitro-plugin/build-sitemap.d.cts +0 -31
- package/dist/cjs/nitro-plugin/plugin.cjs +0 -187
- package/dist/cjs/nitro-plugin/plugin.cjs.map +0 -1
- package/dist/cjs/nitro-plugin/plugin.d.cts +0 -3
- package/dist/cjs/nitro-plugin/prerender.cjs +0 -178
- package/dist/cjs/nitro-plugin/prerender.cjs.map +0 -1
- package/dist/cjs/nitro-plugin/prerender.d.cts +0 -8
- package/dist/cjs/nitro-plugin/queue.cjs +0 -131
- package/dist/cjs/nitro-plugin/queue.cjs.map +0 -1
- package/dist/cjs/nitro-plugin/queue.d.cts +0 -32
- package/dist/cjs/plugin.cjs +0 -227
- package/dist/cjs/plugin.cjs.map +0 -1
- package/dist/cjs/plugin.d.cts +0 -300
- package/dist/cjs/resolve-virtual-entries-plugin/plugin.cjs +0 -80
- package/dist/cjs/resolve-virtual-entries-plugin/plugin.cjs.map +0 -1
- package/dist/cjs/resolve-virtual-entries-plugin/plugin.d.cts +0 -3
- package/dist/cjs/schema.cjs +0 -158
- package/dist/cjs/schema.cjs.map +0 -1
- package/dist/cjs/schema.d.cts +0 -8878
- package/dist/cjs/start-compiler-plugin.cjs +0 -78
- package/dist/cjs/start-compiler-plugin.cjs.map +0 -1
- package/dist/cjs/start-compiler-plugin.d.cts +0 -13
- package/dist/cjs/start-manifest-plugin/plugin.cjs +0 -182
- package/dist/cjs/start-manifest-plugin/plugin.cjs.map +0 -1
- package/dist/cjs/start-manifest-plugin/plugin.d.cts +0 -6
- package/dist/cjs/start-router-plugin/generator-plugins/routes-manifest-plugin.cjs +0 -39
- package/dist/cjs/start-router-plugin/generator-plugins/routes-manifest-plugin.cjs.map +0 -1
- package/dist/cjs/start-router-plugin/generator-plugins/routes-manifest-plugin.d.cts +0 -6
- package/dist/cjs/start-router-plugin/generator-plugins/server-routes-plugin.cjs +0 -121
- package/dist/cjs/start-router-plugin/generator-plugins/server-routes-plugin.cjs.map +0 -1
- package/dist/cjs/start-router-plugin/generator-plugins/server-routes-plugin.d.cts +0 -2
- package/dist/cjs/start-router-plugin/plugin.cjs +0 -45
- package/dist/cjs/start-router-plugin/plugin.cjs.map +0 -1
- package/dist/cjs/start-router-plugin/plugin.d.cts +0 -3
- package/dist/cjs/start-router-plugin/route-tree-client-plugin.cjs +0 -73
- package/dist/cjs/start-router-plugin/route-tree-client-plugin.cjs.map +0 -1
- package/dist/cjs/start-router-plugin/route-tree-client-plugin.d.cts +0 -6
- package/dist/cjs/start-router-plugin/virtual-route-tree-plugin.cjs +0 -29
- package/dist/cjs/start-router-plugin/virtual-route-tree-plugin.cjs.map +0 -1
- package/dist/cjs/start-router-plugin/virtual-route-tree-plugin.d.cts +0 -3
- package/dist/cjs/utils.cjs +0 -18
- package/dist/cjs/utils.cjs.map +0 -1
- package/dist/cjs/utils.d.cts +0 -8
- package/dist/esm/nitro-plugin/build-sitemap.js.map +0 -1
- package/dist/esm/nitro-plugin/plugin.d.ts +0 -3
- package/dist/esm/nitro-plugin/plugin.js +0 -187
- package/dist/esm/nitro-plugin/plugin.js.map +0 -1
- package/dist/esm/nitro-plugin/prerender.d.ts +0 -8
- package/dist/esm/nitro-plugin/prerender.js.map +0 -1
- package/dist/esm/nitro-plugin/queue.js.map +0 -1
- package/dist/esm/resolve-virtual-entries-plugin/plugin.d.ts +0 -3
- package/dist/esm/resolve-virtual-entries-plugin/plugin.js +0 -63
- package/dist/esm/resolve-virtual-entries-plugin/plugin.js.map +0 -1
- package/src/nitro-plugin/plugin.ts +0 -252
- package/src/resolve-virtual-entries-plugin/plugin.ts +0 -77
- /package/dist/esm/{nitro-plugin/queue.d.ts → queue.d.ts} +0 -0
- /package/src/{nitro-plugin/queue.ts → queue.ts} +0 -0
|
@@ -1,33 +1,29 @@
|
|
|
1
|
-
import { promises as fsp } from 'node:fs'
|
|
1
|
+
import { existsSync, promises as fsp, rmSync } from 'node:fs'
|
|
2
2
|
import { pathToFileURL } from 'node:url'
|
|
3
3
|
import os from 'node:os'
|
|
4
|
-
import path from '
|
|
5
|
-
import { getRollupConfig } from 'nitropack/rollup'
|
|
6
|
-
import { build as buildNitro, createNitro } from 'nitropack'
|
|
4
|
+
import path from 'pathe'
|
|
7
5
|
import { joinURL, withBase, withoutBase } from 'ufo'
|
|
8
|
-
import { VITE_ENVIRONMENT_NAMES } from '
|
|
9
|
-
import { createLogger } from '
|
|
6
|
+
import { VITE_ENVIRONMENT_NAMES } from './constants'
|
|
7
|
+
import { createLogger } from './utils'
|
|
10
8
|
import { Queue } from './queue'
|
|
11
|
-
import type { ViteBuilder } from 'vite'
|
|
12
|
-
import type {
|
|
13
|
-
import type { TanStackStartOutputConfig } from '../plugin'
|
|
14
|
-
import type { Page } from '../schema'
|
|
9
|
+
import type { Rollup, ViteBuilder } from 'vite'
|
|
10
|
+
import type { Page, TanStackStartOutputConfig } from './schema'
|
|
15
11
|
|
|
16
12
|
export async function prerender({
|
|
17
|
-
|
|
18
|
-
nitro,
|
|
13
|
+
startConfig,
|
|
19
14
|
builder,
|
|
15
|
+
serverBundle,
|
|
20
16
|
}: {
|
|
21
|
-
|
|
22
|
-
nitro: Nitro
|
|
17
|
+
startConfig: TanStackStartOutputConfig
|
|
23
18
|
builder: ViteBuilder
|
|
19
|
+
serverBundle: Rollup.OutputBundle
|
|
24
20
|
}) {
|
|
25
21
|
const logger = createLogger('prerender')
|
|
26
22
|
logger.info('Prerendering pages...')
|
|
27
23
|
|
|
28
24
|
// If prerender is enabled but no pages are provided, default to prerendering the root page
|
|
29
|
-
if (
|
|
30
|
-
|
|
25
|
+
if (startConfig.prerender?.enabled && !startConfig.pages.length) {
|
|
26
|
+
startConfig.pages = [
|
|
31
27
|
{
|
|
32
28
|
path: '/',
|
|
33
29
|
},
|
|
@@ -42,76 +38,52 @@ export async function prerender({
|
|
|
42
38
|
)
|
|
43
39
|
}
|
|
44
40
|
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
'prerenderer',
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
const nodeNitro = await createNitro({
|
|
54
|
-
...nitro.options._config,
|
|
55
|
-
preset: 'nitro-prerender',
|
|
56
|
-
logLevel: 0,
|
|
57
|
-
output: {
|
|
58
|
-
dir: prerenderOutputDir,
|
|
59
|
-
serverDir: path.resolve(prerenderOutputDir, 'server'),
|
|
60
|
-
publicDir: path.resolve(prerenderOutputDir, 'public'),
|
|
61
|
-
},
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
const nodeNitroRollupOptions = getRollupConfig(nodeNitro)
|
|
65
|
-
|
|
66
|
-
const build = serverEnv.config.build
|
|
67
|
-
|
|
68
|
-
build.outDir = prerenderOutputDir
|
|
69
|
-
|
|
70
|
-
build.rollupOptions = {
|
|
71
|
-
...build.rollupOptions,
|
|
72
|
-
...nodeNitroRollupOptions,
|
|
73
|
-
output: {
|
|
74
|
-
...build.rollupOptions.output,
|
|
75
|
-
...nodeNitroRollupOptions.output,
|
|
76
|
-
sourcemap: undefined,
|
|
77
|
-
},
|
|
41
|
+
const clientEnv = builder.environments[VITE_ENVIRONMENT_NAMES.client]
|
|
42
|
+
if (!clientEnv) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
`Vite's "${VITE_ENVIRONMENT_NAMES.client}" environment not found`,
|
|
45
|
+
)
|
|
78
46
|
}
|
|
79
47
|
|
|
80
|
-
|
|
48
|
+
const outputDir = clientEnv.config.build.outDir
|
|
81
49
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
? nodeNitroRollupOptions.output.entryFileNames
|
|
86
|
-
: 'index.mjs'
|
|
50
|
+
const entryFile = findEntryFileInBundle(serverBundle)
|
|
51
|
+
let fullEntryFilePath = path.join(serverEnv.config.build.outDir, entryFile)
|
|
52
|
+
process.env.TSS_PRERENDERING = 'true'
|
|
87
53
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
54
|
+
if (!existsSync(fullEntryFilePath)) {
|
|
55
|
+
// if the file does not exist, we need to write the bundle to a temporary directory
|
|
56
|
+
// this can happen e.g. with nitro that postprocesses the bundle and thus does not write SSR build to disk
|
|
57
|
+
const bundleOutputDir = path.resolve(
|
|
58
|
+
serverEnv.config.root,
|
|
59
|
+
'.tanstack',
|
|
60
|
+
'start',
|
|
61
|
+
'prerender',
|
|
62
|
+
)
|
|
63
|
+
rmSync(bundleOutputDir, { recursive: true, force: true })
|
|
64
|
+
await writeBundleToDisk({ bundle: serverBundle, outDir: bundleOutputDir })
|
|
65
|
+
fullEntryFilePath = path.join(bundleOutputDir, entryFile)
|
|
66
|
+
}
|
|
91
67
|
|
|
92
|
-
|
|
68
|
+
const { default: serverEntrypoint } = await import(
|
|
69
|
+
pathToFileURL(fullEntryFilePath).toString()
|
|
70
|
+
)
|
|
93
71
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
72
|
+
function localFetch(path: string, options?: RequestInit): Promise<Response> {
|
|
73
|
+
const url = new URL(`http://localhost${path}`)
|
|
74
|
+
return serverEntrypoint.fetch(new Request(url, options))
|
|
97
75
|
}
|
|
98
76
|
|
|
99
77
|
try {
|
|
100
78
|
// Crawl all pages
|
|
101
|
-
const pages = await prerenderPages()
|
|
79
|
+
const pages = await prerenderPages({ outputDir })
|
|
102
80
|
|
|
103
81
|
logger.info(`Prerendered ${pages.length} pages:`)
|
|
104
82
|
pages.forEach((page) => {
|
|
105
83
|
logger.info(`- ${page}`)
|
|
106
84
|
})
|
|
107
|
-
|
|
108
|
-
// TODO: Write the prerendered pages to the output directory
|
|
109
85
|
} catch (error) {
|
|
110
86
|
logger.error(error)
|
|
111
|
-
} finally {
|
|
112
|
-
// Ensure server is always closed
|
|
113
|
-
// server.process.kill()
|
|
114
|
-
closePrerenderer()
|
|
115
87
|
}
|
|
116
88
|
|
|
117
89
|
function extractLinks(html: string): Array<string> {
|
|
@@ -129,14 +101,14 @@ export async function prerender({
|
|
|
129
101
|
return links
|
|
130
102
|
}
|
|
131
103
|
|
|
132
|
-
async function prerenderPages() {
|
|
104
|
+
async function prerenderPages({ outputDir }: { outputDir: string }) {
|
|
133
105
|
const seen = new Set<string>()
|
|
134
106
|
const retriesByPath = new Map<string, number>()
|
|
135
|
-
const concurrency =
|
|
107
|
+
const concurrency = startConfig.prerender?.concurrency ?? os.cpus().length
|
|
136
108
|
logger.info(`Concurrency: ${concurrency}`)
|
|
137
109
|
const queue = new Queue({ concurrency })
|
|
138
110
|
|
|
139
|
-
|
|
111
|
+
startConfig.pages.forEach((page) => addCrawlPageTask(page))
|
|
140
112
|
|
|
141
113
|
await queue.start()
|
|
142
114
|
|
|
@@ -150,18 +122,19 @@ export async function prerender({
|
|
|
150
122
|
seen.add(page.path)
|
|
151
123
|
|
|
152
124
|
if (page.fromCrawl) {
|
|
153
|
-
|
|
125
|
+
startConfig.pages.push(page)
|
|
154
126
|
}
|
|
155
127
|
|
|
156
128
|
// If not enabled, skip
|
|
157
129
|
if (!(page.prerender?.enabled ?? true)) return
|
|
158
130
|
|
|
159
131
|
// If there is a filter link, check if the page should be prerendered
|
|
160
|
-
if (
|
|
132
|
+
if (startConfig.prerender?.filter && !startConfig.prerender.filter(page))
|
|
133
|
+
return
|
|
161
134
|
|
|
162
135
|
// Resolve the merged default and page-specific prerender options
|
|
163
136
|
const prerenderOptions = {
|
|
164
|
-
...
|
|
137
|
+
...startConfig.prerender,
|
|
165
138
|
...page.prerender,
|
|
166
139
|
}
|
|
167
140
|
|
|
@@ -173,15 +146,11 @@ export async function prerender({
|
|
|
173
146
|
// Fetch the route
|
|
174
147
|
const encodedRoute = encodeURI(page.path)
|
|
175
148
|
|
|
176
|
-
const res = await localFetch
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
headers: {
|
|
180
|
-
...prerenderOptions.headers,
|
|
181
|
-
'x-nitro-prerender': encodedRoute,
|
|
182
|
-
},
|
|
149
|
+
const res = await localFetch(withBase(encodedRoute, TSS_APP_BASE), {
|
|
150
|
+
headers: {
|
|
151
|
+
...prerenderOptions.headers,
|
|
183
152
|
},
|
|
184
|
-
)
|
|
153
|
+
})
|
|
185
154
|
|
|
186
155
|
if (!res.ok) {
|
|
187
156
|
throw new Error(`Failed to fetch ${page.path}: ${res.statusText}`, {
|
|
@@ -210,12 +179,12 @@ export async function prerender({
|
|
|
210
179
|
|
|
211
180
|
const filename = withoutBase(
|
|
212
181
|
isImplicitHTML ? htmlPath : routeWithIndex,
|
|
213
|
-
|
|
182
|
+
TSS_APP_BASE,
|
|
214
183
|
)
|
|
215
184
|
|
|
216
185
|
const html = await res.text()
|
|
217
186
|
|
|
218
|
-
const filepath = path.join(
|
|
187
|
+
const filepath = path.join(outputDir, filename)
|
|
219
188
|
|
|
220
189
|
await fsp.mkdir(path.dirname(filepath), {
|
|
221
190
|
recursive: true,
|
|
@@ -245,10 +214,48 @@ export async function prerender({
|
|
|
245
214
|
retriesByPath.set(page.path, retries + 1)
|
|
246
215
|
addCrawlPageTask(page)
|
|
247
216
|
} else {
|
|
248
|
-
|
|
217
|
+
if (prerenderOptions.failOnError ?? true) {
|
|
218
|
+
throw error
|
|
219
|
+
}
|
|
249
220
|
}
|
|
250
221
|
}
|
|
251
222
|
})
|
|
252
223
|
}
|
|
253
224
|
}
|
|
254
225
|
}
|
|
226
|
+
|
|
227
|
+
function findEntryFileInBundle(bundle: Rollup.OutputBundle): string {
|
|
228
|
+
let entryFile: string | undefined
|
|
229
|
+
|
|
230
|
+
for (const [_name, file] of Object.entries(bundle)) {
|
|
231
|
+
if (file.type === 'chunk') {
|
|
232
|
+
if (file.isEntry) {
|
|
233
|
+
if (entryFile !== undefined) {
|
|
234
|
+
throw new Error(
|
|
235
|
+
`Multiple entry points found. Only one entry point is allowed.`,
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
entryFile = file.fileName
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (entryFile === undefined) {
|
|
243
|
+
throw new Error(`No entry point found in the bundle.`)
|
|
244
|
+
}
|
|
245
|
+
return entryFile
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export async function writeBundleToDisk({
|
|
249
|
+
bundle,
|
|
250
|
+
outDir,
|
|
251
|
+
}: {
|
|
252
|
+
bundle: Rollup.OutputBundle
|
|
253
|
+
outDir: string
|
|
254
|
+
}) {
|
|
255
|
+
for (const [fileName, asset] of Object.entries(bundle)) {
|
|
256
|
+
const fullPath = path.join(outDir, fileName)
|
|
257
|
+
const content = asset.type === 'asset' ? asset.source : asset.code
|
|
258
|
+
await fsp.mkdir(path.dirname(fullPath), { recursive: true })
|
|
259
|
+
await fsp.writeFile(fullPath, content)
|
|
260
|
+
}
|
|
261
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { resolveModulePath } from 'exsolve'
|
|
2
|
+
|
|
3
|
+
interface ResolveModuleOptions {
|
|
4
|
+
baseName: string
|
|
5
|
+
from: string
|
|
6
|
+
}
|
|
7
|
+
function resolveModule(opts: ResolveModuleOptions): string | undefined {
|
|
8
|
+
let baseName = opts.baseName
|
|
9
|
+
if (!baseName.startsWith('./')) {
|
|
10
|
+
baseName = `./${baseName}`
|
|
11
|
+
}
|
|
12
|
+
return resolveModulePath(baseName, {
|
|
13
|
+
from: opts.from,
|
|
14
|
+
extensions: ['.ts', '.js', '.mts', '.mjs', '.tsx', '.jsx'],
|
|
15
|
+
try: true,
|
|
16
|
+
})
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function resolveEntry<
|
|
20
|
+
TRequired extends boolean,
|
|
21
|
+
TReturn = TRequired extends true ? string : string | undefined,
|
|
22
|
+
>(opts: {
|
|
23
|
+
type: string
|
|
24
|
+
configuredEntry?: string
|
|
25
|
+
defaultEntry: string
|
|
26
|
+
resolvedSrcDirectory: string
|
|
27
|
+
root: string
|
|
28
|
+
required: TRequired
|
|
29
|
+
}): TReturn {
|
|
30
|
+
let resolveOptions: ResolveModuleOptions
|
|
31
|
+
|
|
32
|
+
// if entry was not configured, use default relative to srcDirectory
|
|
33
|
+
if (!opts.configuredEntry) {
|
|
34
|
+
resolveOptions = {
|
|
35
|
+
baseName: opts.defaultEntry,
|
|
36
|
+
from: opts.resolvedSrcDirectory,
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
resolveOptions = {
|
|
40
|
+
baseName: opts.configuredEntry,
|
|
41
|
+
from: opts.root,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const resolvedEntry = resolveModule(resolveOptions)
|
|
46
|
+
if (opts.required && !resolvedEntry) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
`Could not resolve entry for ${opts.type}: ${resolveOptions.baseName} in ${resolveOptions.from}`,
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
return resolvedEntry as TReturn
|
|
52
|
+
}
|
package/src/schema.ts
CHANGED
|
@@ -1,142 +1,43 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
-
import { existsSync } from 'node:fs'
|
|
3
2
|
import { z } from 'zod'
|
|
4
3
|
import { configSchema, getConfig } from '@tanstack/router-generator'
|
|
5
|
-
import type { NitroConfig } from 'nitropack'
|
|
6
4
|
|
|
7
5
|
const tsrConfig = configSchema
|
|
8
6
|
.omit({ autoCodeSplitting: true })
|
|
9
7
|
.partial()
|
|
10
8
|
.extend({
|
|
9
|
+
// this is relative to vite root
|
|
10
|
+
// TODO why is this nested under tsr?
|
|
11
11
|
srcDirectory: z.string().optional().default('src'),
|
|
12
12
|
})
|
|
13
13
|
|
|
14
|
-
export function
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
return {
|
|
20
|
-
schema,
|
|
21
|
-
parse: (opts?: z.input<typeof schema>) => {
|
|
22
|
-
const options = schema.parse(opts)
|
|
23
|
-
|
|
24
|
-
const srcDirectory = options.tsr.srcDirectory
|
|
25
|
-
|
|
26
|
-
const routesDirectory =
|
|
27
|
-
options.tsr.routesDirectory ?? path.join(srcDirectory, 'routes')
|
|
28
|
-
|
|
29
|
-
const generatedRouteTree =
|
|
30
|
-
options.tsr.generatedRouteTree ??
|
|
31
|
-
path.join(srcDirectory, 'routeTree.gen.ts')
|
|
32
|
-
|
|
33
|
-
const clientEntryPath = (() => {
|
|
34
|
-
if (options.client.entry) {
|
|
35
|
-
return path.join(srcDirectory, options.client.entry)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (existsSync(path.join(srcDirectory, 'client.tsx'))) {
|
|
39
|
-
return path.join(srcDirectory, 'client.tsx')
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return '/~start/default-client-entry'
|
|
43
|
-
})()
|
|
44
|
-
|
|
45
|
-
const serverEntryPath = (() => {
|
|
46
|
-
if (options.server.entry) {
|
|
47
|
-
return path.join(srcDirectory, options.server.entry)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (existsSync(path.join(srcDirectory, 'server.tsx'))) {
|
|
51
|
-
return path.join(srcDirectory, 'server.tsx')
|
|
52
|
-
}
|
|
14
|
+
export function parseStartConfig(
|
|
15
|
+
opts?: z.input<typeof tanstackStartOptionsSchema>,
|
|
16
|
+
) {
|
|
17
|
+
const options = tanstackStartOptionsSchema.parse(opts)
|
|
53
18
|
|
|
54
|
-
|
|
55
|
-
return path.join(srcDirectory, 'server.ts')
|
|
56
|
-
}
|
|
19
|
+
const srcDirectory = options.tsr.srcDirectory
|
|
57
20
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
21
|
+
const routesDirectory =
|
|
22
|
+
options.tsr.routesDirectory ?? path.join(srcDirectory, 'routes')
|
|
61
23
|
|
|
62
|
-
|
|
63
|
-
|
|
24
|
+
const generatedRouteTree =
|
|
25
|
+
options.tsr.generatedRouteTree ??
|
|
26
|
+
path.join(srcDirectory, 'routeTree.gen.ts')
|
|
64
27
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
},
|
|
75
|
-
clientEntryPath,
|
|
76
|
-
serverEntryPath,
|
|
77
|
-
}
|
|
28
|
+
return {
|
|
29
|
+
...options,
|
|
30
|
+
tsr: {
|
|
31
|
+
...options.tsr,
|
|
32
|
+
...getConfig({
|
|
33
|
+
...options.tsr,
|
|
34
|
+
routesDirectory,
|
|
35
|
+
generatedRouteTree,
|
|
36
|
+
}),
|
|
78
37
|
},
|
|
79
38
|
}
|
|
80
39
|
}
|
|
81
40
|
|
|
82
|
-
export function createTanStackStartOptionsSchema(
|
|
83
|
-
frameworkPlugin: Record<string, unknown> = {},
|
|
84
|
-
) {
|
|
85
|
-
return z
|
|
86
|
-
.object({
|
|
87
|
-
root: z.string().optional().default(process.cwd()),
|
|
88
|
-
target: z.custom<NitroConfig['preset']>().optional(),
|
|
89
|
-
...frameworkPlugin,
|
|
90
|
-
tsr: tsrConfig.optional().default({}),
|
|
91
|
-
client: z
|
|
92
|
-
.object({
|
|
93
|
-
entry: z.string().optional(),
|
|
94
|
-
base: z.string().optional().default('/_build'),
|
|
95
|
-
})
|
|
96
|
-
.optional()
|
|
97
|
-
.default({}),
|
|
98
|
-
server: z
|
|
99
|
-
.object({
|
|
100
|
-
entry: z.string().optional(),
|
|
101
|
-
})
|
|
102
|
-
.optional()
|
|
103
|
-
.default({}),
|
|
104
|
-
serverFns: z
|
|
105
|
-
.object({
|
|
106
|
-
base: z.string().optional().default('/_serverFn'),
|
|
107
|
-
})
|
|
108
|
-
.optional()
|
|
109
|
-
.default({}),
|
|
110
|
-
public: z
|
|
111
|
-
.object({
|
|
112
|
-
dir: z.string().optional().default('public'),
|
|
113
|
-
base: z.string().optional().default('/'),
|
|
114
|
-
})
|
|
115
|
-
.optional()
|
|
116
|
-
.default({}),
|
|
117
|
-
pages: z.array(pageSchema).optional().default([]),
|
|
118
|
-
sitemap: z
|
|
119
|
-
.object({
|
|
120
|
-
enabled: z.boolean().optional().default(true),
|
|
121
|
-
host: z.string().optional(),
|
|
122
|
-
outputPath: z.string().optional().default('sitemap.xml'),
|
|
123
|
-
})
|
|
124
|
-
.optional(),
|
|
125
|
-
prerender: z
|
|
126
|
-
.object({
|
|
127
|
-
enabled: z.boolean().optional(),
|
|
128
|
-
concurrency: z.number().optional(),
|
|
129
|
-
filter: z.function().args(pageSchema).returns(z.any()).optional(),
|
|
130
|
-
failOnError: z.boolean().optional(),
|
|
131
|
-
})
|
|
132
|
-
.and(pagePrerenderOptionsSchema.optional())
|
|
133
|
-
.optional(),
|
|
134
|
-
spa: spaSchema.optional(),
|
|
135
|
-
})
|
|
136
|
-
.optional()
|
|
137
|
-
.default({})
|
|
138
|
-
}
|
|
139
|
-
|
|
140
41
|
const pageSitemapOptionsSchema = z.object({
|
|
141
42
|
exclude: z.boolean().optional(),
|
|
142
43
|
priority: z.number().min(0).max(1).optional(),
|
|
@@ -214,8 +115,74 @@ const spaSchema = z.object({
|
|
|
214
115
|
})),
|
|
215
116
|
})
|
|
216
117
|
|
|
217
|
-
|
|
118
|
+
const pageSchema = pageBaseSchema.extend({
|
|
218
119
|
prerender: pagePrerenderOptionsSchema.optional(),
|
|
219
120
|
})
|
|
220
121
|
|
|
122
|
+
const tanstackStartOptionsSchema = z
|
|
123
|
+
.object({
|
|
124
|
+
tsr: tsrConfig.optional().default({}),
|
|
125
|
+
router: z
|
|
126
|
+
.object({
|
|
127
|
+
// TODO naming?
|
|
128
|
+
entry: z.string().optional(),
|
|
129
|
+
})
|
|
130
|
+
.optional()
|
|
131
|
+
.default({}),
|
|
132
|
+
client: z
|
|
133
|
+
.object({
|
|
134
|
+
entry: z.string().optional(),
|
|
135
|
+
base: z.string().optional().default('/_build'),
|
|
136
|
+
})
|
|
137
|
+
.optional()
|
|
138
|
+
.default({}),
|
|
139
|
+
server: z
|
|
140
|
+
.object({
|
|
141
|
+
entry: z.string().optional(),
|
|
142
|
+
})
|
|
143
|
+
.optional()
|
|
144
|
+
.default({}),
|
|
145
|
+
serverFns: z
|
|
146
|
+
.object({
|
|
147
|
+
base: z.string().optional().default('/_serverFn'),
|
|
148
|
+
})
|
|
149
|
+
.optional()
|
|
150
|
+
.default({}),
|
|
151
|
+
public: z
|
|
152
|
+
.object({
|
|
153
|
+
dir: z.string().optional().default('public'),
|
|
154
|
+
base: z.string().optional().default('/'),
|
|
155
|
+
})
|
|
156
|
+
.optional()
|
|
157
|
+
.default({}),
|
|
158
|
+
pages: z.array(pageSchema).optional().default([]),
|
|
159
|
+
sitemap: z
|
|
160
|
+
.object({
|
|
161
|
+
enabled: z.boolean().optional().default(true),
|
|
162
|
+
host: z.string().optional(),
|
|
163
|
+
outputPath: z.string().optional().default('sitemap.xml'),
|
|
164
|
+
})
|
|
165
|
+
.optional(),
|
|
166
|
+
prerender: z
|
|
167
|
+
.object({
|
|
168
|
+
enabled: z.boolean().optional(),
|
|
169
|
+
concurrency: z.number().optional(),
|
|
170
|
+
filter: z.function().args(pageSchema).returns(z.any()).optional(),
|
|
171
|
+
failOnError: z.boolean().optional(),
|
|
172
|
+
})
|
|
173
|
+
.and(pagePrerenderOptionsSchema.optional())
|
|
174
|
+
.optional(),
|
|
175
|
+
spa: spaSchema.optional(),
|
|
176
|
+
vite: z
|
|
177
|
+
.object({ installDevServerMiddleware: z.boolean().optional() })
|
|
178
|
+
.optional(),
|
|
179
|
+
})
|
|
180
|
+
.optional()
|
|
181
|
+
.default({})
|
|
182
|
+
|
|
221
183
|
export type Page = z.infer<typeof pageSchema>
|
|
184
|
+
|
|
185
|
+
export type TanStackStartInputConfig = z.input<
|
|
186
|
+
typeof tanstackStartOptionsSchema
|
|
187
|
+
>
|
|
188
|
+
export type TanStackStartOutputConfig = ReturnType<typeof parseStartConfig>
|
|
@@ -3,7 +3,8 @@ import { rootRouteId } from '@tanstack/router-core'
|
|
|
3
3
|
import { VIRTUAL_MODULES } from '@tanstack/start-server-core'
|
|
4
4
|
import { tsrSplit } from '@tanstack/router-plugin'
|
|
5
5
|
import { resolveViteId } from '../utils'
|
|
6
|
-
import
|
|
6
|
+
import { ENTRY_POINTS } from '../constants'
|
|
7
|
+
import type { PluginOption, Rollup } from 'vite'
|
|
7
8
|
import type { RouterManagedTag } from '@tanstack/router-core'
|
|
8
9
|
|
|
9
10
|
export const getCSSRecursively = (
|
|
@@ -40,17 +41,11 @@ export const getCSSRecursively = (
|
|
|
40
41
|
|
|
41
42
|
const resolvedModuleId = resolveViteId(VIRTUAL_MODULES.startManifest)
|
|
42
43
|
export function startManifestPlugin(opts: {
|
|
43
|
-
|
|
44
|
+
getClientBundle: () => Rollup.OutputBundle
|
|
44
45
|
}): PluginOption {
|
|
45
|
-
let config: ResolvedConfig
|
|
46
|
-
|
|
47
46
|
return {
|
|
48
47
|
name: 'tanstack-start:start-manifest-plugin',
|
|
49
48
|
enforce: 'pre',
|
|
50
|
-
|
|
51
|
-
configResolved(resolvedConfig) {
|
|
52
|
-
config = resolvedConfig
|
|
53
|
-
},
|
|
54
49
|
resolveId: {
|
|
55
50
|
filter: { id: new RegExp(VIRTUAL_MODULES.startManifest) },
|
|
56
51
|
handler(id) {
|
|
@@ -76,10 +71,10 @@ export function startManifestPlugin(opts: {
|
|
|
76
71
|
const APP_BASE = globalThis.TSS_APP_BASE
|
|
77
72
|
|
|
78
73
|
// If we're in development, return a dummy manifest
|
|
79
|
-
if (config.command === 'serve') {
|
|
74
|
+
if (this.environment.config.command === 'serve') {
|
|
80
75
|
return `export const tsrStartManifest = () => ({
|
|
81
76
|
routes: {},
|
|
82
|
-
clientEntry: '${joinURL(APP_BASE,
|
|
77
|
+
clientEntry: '${joinURL(APP_BASE, '@id', ENTRY_POINTS.client)}',
|
|
83
78
|
})`
|
|
84
79
|
}
|
|
85
80
|
|
|
@@ -88,10 +83,9 @@ export function startManifestPlugin(opts: {
|
|
|
88
83
|
const routeTreeRoutes = globalThis.TSS_ROUTES_MANIFEST.routes
|
|
89
84
|
|
|
90
85
|
// This is where hydration will start, from when the SSR'd page reaches the browser.
|
|
91
|
-
// By default, this'd be the virtual entry of `/~start/default-client-entry.tsx`, unless a custom entry is provided.
|
|
92
86
|
let entryFile: Rollup.OutputChunk | undefined
|
|
93
87
|
|
|
94
|
-
const clientBundle =
|
|
88
|
+
const clientBundle = opts.getClientBundle()
|
|
95
89
|
const chunksByFileName = new Map<string, Rollup.OutputChunk>()
|
|
96
90
|
|
|
97
91
|
const routeChunks: Record<
|
|
@@ -222,12 +216,12 @@ export function startManifestPlugin(opts: {
|
|
|
222
216
|
|
|
223
217
|
recurseRoute(routeTreeRoutes[rootRouteId]!)
|
|
224
218
|
|
|
225
|
-
const
|
|
219
|
+
const startManifest = {
|
|
226
220
|
routes: routeTreeRoutes,
|
|
227
221
|
clientEntry: joinURL(APP_BASE, entryFile.fileName),
|
|
228
222
|
}
|
|
229
223
|
|
|
230
|
-
return `export const tsrStartManifest = () => (${JSON.stringify(
|
|
224
|
+
return `export const tsrStartManifest = () => (${JSON.stringify(startManifest)})`
|
|
231
225
|
}
|
|
232
226
|
|
|
233
227
|
return undefined
|