@tanstack/start-plugin-core 1.166.7 → 1.166.8
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/start-manifest-plugin/manifestBuilder.d.ts +55 -0
- package/dist/esm/start-manifest-plugin/manifestBuilder.js +404 -0
- package/dist/esm/start-manifest-plugin/manifestBuilder.js.map +1 -0
- package/dist/esm/start-manifest-plugin/plugin.js +5 -169
- package/dist/esm/start-manifest-plugin/plugin.js.map +1 -1
- package/package.json +4 -4
- package/src/start-manifest-plugin/manifestBuilder.ts +555 -0
- package/src/start-manifest-plugin/plugin.ts +6 -227
|
@@ -1,63 +1,13 @@
|
|
|
1
1
|
import { joinURL } from 'ufo'
|
|
2
|
-
import { rootRouteId } from '@tanstack/router-core'
|
|
3
2
|
import { VIRTUAL_MODULES } from '@tanstack/start-server-core'
|
|
4
|
-
import { tsrSplit } from '@tanstack/router-plugin'
|
|
5
3
|
import { resolveViteId } from '../utils'
|
|
6
4
|
import { ENTRY_POINTS } from '../constants'
|
|
5
|
+
import { buildStartManifest } from './manifestBuilder'
|
|
7
6
|
import type { GetConfigFn } from '../types'
|
|
8
7
|
import type { PluginOption, Rollup } from 'vite'
|
|
9
|
-
import type { Manifest, RouterManagedTag } from '@tanstack/router-core'
|
|
10
|
-
|
|
11
|
-
const getCSSRecursively = (
|
|
12
|
-
chunk: Rollup.OutputChunk,
|
|
13
|
-
chunksByFileName: Map<string, Rollup.OutputChunk>,
|
|
14
|
-
basePath: string,
|
|
15
|
-
cache: Map<Rollup.OutputChunk, Array<RouterManagedTag>>,
|
|
16
|
-
visited = new Set<Rollup.OutputChunk>(),
|
|
17
|
-
) => {
|
|
18
|
-
if (visited.has(chunk)) {
|
|
19
|
-
return []
|
|
20
|
-
}
|
|
21
|
-
visited.add(chunk)
|
|
22
|
-
const cachedResult = cache.get(chunk)
|
|
23
|
-
if (cachedResult) {
|
|
24
|
-
return cachedResult
|
|
25
|
-
}
|
|
26
|
-
const result: Array<RouterManagedTag> = []
|
|
27
|
-
|
|
28
|
-
// Get all css imports from the file
|
|
29
|
-
for (const cssFile of chunk.viteMetadata?.importedCss ?? []) {
|
|
30
|
-
result.push({
|
|
31
|
-
tag: 'link',
|
|
32
|
-
attrs: {
|
|
33
|
-
rel: 'stylesheet',
|
|
34
|
-
href: joinURL(basePath, cssFile),
|
|
35
|
-
type: 'text/css',
|
|
36
|
-
},
|
|
37
|
-
})
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Recursively get CSS from imports
|
|
41
|
-
for (const importedFileName of chunk.imports) {
|
|
42
|
-
const importedChunk = chunksByFileName.get(importedFileName)
|
|
43
|
-
if (importedChunk) {
|
|
44
|
-
result.push(
|
|
45
|
-
...getCSSRecursively(
|
|
46
|
-
importedChunk,
|
|
47
|
-
chunksByFileName,
|
|
48
|
-
basePath,
|
|
49
|
-
cache,
|
|
50
|
-
visited,
|
|
51
|
-
),
|
|
52
|
-
)
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
cache.set(chunk, result)
|
|
57
|
-
return result
|
|
58
|
-
}
|
|
59
8
|
|
|
60
9
|
const resolvedModuleId = resolveViteId(VIRTUAL_MODULES.startManifest)
|
|
10
|
+
|
|
61
11
|
export function startManifestPlugin(opts: {
|
|
62
12
|
getClientBundle: () => Rollup.OutputBundle
|
|
63
13
|
getConfig: GetConfigFn
|
|
@@ -84,12 +34,9 @@ export function startManifestPlugin(opts: {
|
|
|
84
34
|
if (
|
|
85
35
|
this.environment.name !== resolvedStartConfig.serverFnProviderEnv
|
|
86
36
|
) {
|
|
87
|
-
// this will ultimately fail the build if the plugin is used outside the provider environment
|
|
88
|
-
// TODO: do we need special handling for `serve`?
|
|
89
37
|
return `export default {}`
|
|
90
38
|
}
|
|
91
39
|
|
|
92
|
-
// If we're in development, return a dummy manifest
|
|
93
40
|
if (this.environment.config.command === 'serve') {
|
|
94
41
|
return `export const tsrStartManifest = () => ({
|
|
95
42
|
routes: {},
|
|
@@ -97,181 +44,13 @@ export function startManifestPlugin(opts: {
|
|
|
97
44
|
})`
|
|
98
45
|
}
|
|
99
46
|
|
|
100
|
-
// This the manifest pulled from the generated route tree and later used by the Router.
|
|
101
|
-
// i.e what's located in `src/routeTree.gen.ts`
|
|
102
47
|
const routeTreeRoutes = globalThis.TSS_ROUTES_MANIFEST
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
>()
|
|
108
|
-
|
|
109
|
-
// This is where hydration will start, from when the SSR'd page reaches the browser.
|
|
110
|
-
let entryFile: Rollup.OutputChunk | undefined
|
|
111
|
-
|
|
112
|
-
const clientBundle = opts.getClientBundle()
|
|
113
|
-
const chunksByFileName = new Map<string, Rollup.OutputChunk>()
|
|
114
|
-
|
|
115
|
-
const routeChunks: Record<
|
|
116
|
-
string /** fullPath of route file **/,
|
|
117
|
-
Array<Rollup.OutputChunk>
|
|
118
|
-
> = {}
|
|
119
|
-
for (const bundleEntry of Object.values(clientBundle)) {
|
|
120
|
-
if (bundleEntry.type === 'chunk') {
|
|
121
|
-
chunksByFileName.set(bundleEntry.fileName, bundleEntry)
|
|
122
|
-
if (bundleEntry.isEntry) {
|
|
123
|
-
if (entryFile) {
|
|
124
|
-
throw new Error(
|
|
125
|
-
`multiple entries detected: ${entryFile.fileName} ${bundleEntry.fileName}`,
|
|
126
|
-
)
|
|
127
|
-
}
|
|
128
|
-
entryFile = bundleEntry
|
|
129
|
-
}
|
|
130
|
-
const routePieces = bundleEntry.moduleIds.flatMap((m) => {
|
|
131
|
-
const [id, query] = m.split('?')
|
|
132
|
-
if (id === undefined) {
|
|
133
|
-
throw new Error('expected id to be defined')
|
|
134
|
-
}
|
|
135
|
-
if (query === undefined) {
|
|
136
|
-
return []
|
|
137
|
-
}
|
|
138
|
-
const searchParams = new URLSearchParams(query)
|
|
139
|
-
const split = searchParams.get(tsrSplit)
|
|
140
|
-
|
|
141
|
-
if (split !== null) {
|
|
142
|
-
return {
|
|
143
|
-
id,
|
|
144
|
-
split,
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
return []
|
|
148
|
-
})
|
|
149
|
-
if (routePieces.length > 0) {
|
|
150
|
-
routePieces.forEach((r) => {
|
|
151
|
-
let array = routeChunks[r.id]
|
|
152
|
-
if (array === undefined) {
|
|
153
|
-
array = []
|
|
154
|
-
routeChunks[r.id] = array
|
|
155
|
-
}
|
|
156
|
-
array.push(bundleEntry)
|
|
157
|
-
})
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const manifest: Manifest = { routes: {} }
|
|
163
|
-
// Add preloads to the routes from the vite manifest
|
|
164
|
-
Object.entries(routeTreeRoutes).forEach(([routeId, v]) => {
|
|
165
|
-
if (!v.filePath) {
|
|
166
|
-
throw new Error(`expected filePath to be set for ${routeId}`)
|
|
167
|
-
}
|
|
168
|
-
const chunks = routeChunks[v.filePath]
|
|
169
|
-
if (chunks) {
|
|
170
|
-
chunks.forEach((chunk) => {
|
|
171
|
-
// Map the relevant imports to their route paths,
|
|
172
|
-
// so that it can be imported in the browser.
|
|
173
|
-
const preloads = chunk.imports.map((d) => {
|
|
174
|
-
const preloadPath = joinURL(
|
|
175
|
-
resolvedStartConfig.viteAppBase,
|
|
176
|
-
d,
|
|
177
|
-
)
|
|
178
|
-
return preloadPath
|
|
179
|
-
})
|
|
180
|
-
|
|
181
|
-
// Since this is the most important JS entry for the route,
|
|
182
|
-
// it should be moved to the front of the preloads so that
|
|
183
|
-
// it has the best chance of being loaded first.
|
|
184
|
-
preloads.unshift(
|
|
185
|
-
joinURL(resolvedStartConfig.viteAppBase, chunk.fileName),
|
|
186
|
-
)
|
|
187
|
-
|
|
188
|
-
const assets = getCSSRecursively(
|
|
189
|
-
chunk,
|
|
190
|
-
chunksByFileName,
|
|
191
|
-
resolvedStartConfig.viteAppBase,
|
|
192
|
-
cssPerChunkCache,
|
|
193
|
-
)
|
|
194
|
-
|
|
195
|
-
manifest.routes[routeId] = {
|
|
196
|
-
...v,
|
|
197
|
-
assets,
|
|
198
|
-
preloads,
|
|
199
|
-
}
|
|
200
|
-
})
|
|
201
|
-
} else {
|
|
202
|
-
manifest.routes[routeId] = v
|
|
203
|
-
}
|
|
48
|
+
const startManifest = buildStartManifest({
|
|
49
|
+
clientBundle: opts.getClientBundle(),
|
|
50
|
+
routeTreeRoutes,
|
|
51
|
+
basePath: resolvedStartConfig.viteAppBase,
|
|
204
52
|
})
|
|
205
53
|
|
|
206
|
-
if (!entryFile) {
|
|
207
|
-
throw new Error('No entry file found')
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
manifest.routes[rootRouteId] = manifest.routes[rootRouteId] || {}
|
|
211
|
-
manifest.routes[rootRouteId].preloads = [
|
|
212
|
-
joinURL(resolvedStartConfig.viteAppBase, entryFile.fileName),
|
|
213
|
-
...entryFile.imports.map((d) =>
|
|
214
|
-
joinURL(resolvedStartConfig.viteAppBase, d),
|
|
215
|
-
),
|
|
216
|
-
]
|
|
217
|
-
|
|
218
|
-
// Gather all the CSS files from the entry file in
|
|
219
|
-
// the `css` key and add them to the root route
|
|
220
|
-
const entryCssAssetsList = getCSSRecursively(
|
|
221
|
-
entryFile,
|
|
222
|
-
chunksByFileName,
|
|
223
|
-
resolvedStartConfig.viteAppBase,
|
|
224
|
-
cssPerChunkCache,
|
|
225
|
-
)
|
|
226
|
-
|
|
227
|
-
manifest.routes[rootRouteId].assets = [
|
|
228
|
-
...(manifest.routes[rootRouteId].assets || []),
|
|
229
|
-
...entryCssAssetsList,
|
|
230
|
-
]
|
|
231
|
-
|
|
232
|
-
const recurseRoute = (
|
|
233
|
-
route: {
|
|
234
|
-
preloads?: Array<string>
|
|
235
|
-
children?: Array<any>
|
|
236
|
-
},
|
|
237
|
-
seenPreloads = {} as Record<string, true>,
|
|
238
|
-
) => {
|
|
239
|
-
route.preloads = route.preloads?.filter((preload) => {
|
|
240
|
-
if (seenPreloads[preload]) {
|
|
241
|
-
return false
|
|
242
|
-
}
|
|
243
|
-
seenPreloads[preload] = true
|
|
244
|
-
return true
|
|
245
|
-
})
|
|
246
|
-
|
|
247
|
-
if (route.children) {
|
|
248
|
-
route.children.forEach((child) => {
|
|
249
|
-
const childRoute = manifest.routes[child]!
|
|
250
|
-
recurseRoute(childRoute, { ...seenPreloads })
|
|
251
|
-
})
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
recurseRoute(manifest.routes[rootRouteId])
|
|
256
|
-
|
|
257
|
-
// Filter out routes that have neither assets nor preloads
|
|
258
|
-
Object.keys(manifest.routes).forEach((routeId) => {
|
|
259
|
-
const route = manifest.routes[routeId]!
|
|
260
|
-
const hasAssets = route.assets && route.assets.length > 0
|
|
261
|
-
const hasPreloads = route.preloads && route.preloads.length > 0
|
|
262
|
-
if (!hasAssets && !hasPreloads) {
|
|
263
|
-
delete routeTreeRoutes[routeId]
|
|
264
|
-
}
|
|
265
|
-
})
|
|
266
|
-
|
|
267
|
-
const startManifest = {
|
|
268
|
-
routes: manifest.routes,
|
|
269
|
-
clientEntry: joinURL(
|
|
270
|
-
resolvedStartConfig.viteAppBase,
|
|
271
|
-
entryFile.fileName,
|
|
272
|
-
),
|
|
273
|
-
}
|
|
274
|
-
|
|
275
54
|
return `export const tsrStartManifest = () => (${JSON.stringify(startManifest)})`
|
|
276
55
|
}
|
|
277
56
|
|