@tanstack/start-plugin-core 1.167.33 → 1.167.35
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/schema.js +1 -1
- package/dist/esm/start-manifest-plugin/manifestBuilder.d.ts +3 -6
- package/dist/esm/start-manifest-plugin/manifestBuilder.js +34 -81
- package/dist/esm/start-manifest-plugin/manifestBuilder.js.map +1 -1
- package/dist/esm/vite/plugin.js +3 -11
- package/dist/esm/vite/plugin.js.map +1 -1
- package/dist/esm/vite/plugins.d.ts +1 -5
- package/dist/esm/vite/plugins.js +2 -17
- package/dist/esm/vite/plugins.js.map +1 -1
- package/dist/esm/vite/start-manifest-plugin/normalized-client-build.js +2 -2
- package/dist/esm/vite/start-manifest-plugin/normalized-client-build.js.map +1 -1
- package/dist/esm/vite/start-manifest-plugin/plugin.d.ts +1 -2
- package/dist/esm/vite/start-manifest-plugin/plugin.js +48 -14
- package/dist/esm/vite/start-manifest-plugin/plugin.js.map +1 -1
- package/package.json +6 -6
- package/src/start-manifest-plugin/manifestBuilder.ts +53 -116
- package/src/vite/plugin.ts +0 -17
- package/src/vite/plugins.ts +2 -33
- package/src/vite/start-manifest-plugin/normalized-client-build.ts +15 -16
- package/src/vite/start-manifest-plugin/plugin.ts +121 -38
|
@@ -1,34 +1,68 @@
|
|
|
1
1
|
import { ENTRY_POINTS, START_ENVIRONMENT_NAMES } from "../../constants.js";
|
|
2
2
|
import { createVirtualModule } from "../createVirtualModule.js";
|
|
3
|
-
import {
|
|
3
|
+
import { normalizeViteClientBuild } from "./normalized-client-build.js";
|
|
4
|
+
import { buildStartManifest, createManifestAssetResolvers, serializeStartManifest } from "../../start-manifest-plugin/manifestBuilder.js";
|
|
5
|
+
import { rootRouteId } from "@tanstack/router-core";
|
|
4
6
|
import { VIRTUAL_MODULES } from "@tanstack/start-server-core";
|
|
5
7
|
import { joinURL } from "ufo";
|
|
6
8
|
//#region src/vite/start-manifest-plugin/plugin.ts
|
|
7
9
|
function startManifestPlugin(opts) {
|
|
8
|
-
|
|
10
|
+
let clientBuild;
|
|
11
|
+
let cssCodeSplitDisabledFileName;
|
|
12
|
+
return [{
|
|
13
|
+
name: "tanstack-start:start-manifest-capture-client-build",
|
|
14
|
+
applyToEnvironment(environment) {
|
|
15
|
+
return environment.name === START_ENVIRONMENT_NAMES.client;
|
|
16
|
+
},
|
|
17
|
+
enforce: "post",
|
|
18
|
+
generateBundle(_options, bundle) {
|
|
19
|
+
if (this.environment.name !== START_ENVIRONMENT_NAMES.client) throw new Error(`Unexpected environment for client build capture: ${this.environment.name}`);
|
|
20
|
+
clientBuild = normalizeViteClientBuild(bundle);
|
|
21
|
+
cssCodeSplitDisabledFileName = getAssetFileNameByName(bundle, "style.css");
|
|
22
|
+
}
|
|
23
|
+
}, createVirtualModule({
|
|
9
24
|
name: "tanstack-start:start-manifest-plugin",
|
|
10
25
|
moduleId: VIRTUAL_MODULES.startManifest,
|
|
11
26
|
enforce: "pre",
|
|
12
27
|
load() {
|
|
13
28
|
const { resolvedStartConfig } = opts.getConfig();
|
|
14
|
-
|
|
15
|
-
if (this.environment.
|
|
16
|
-
|
|
17
|
-
clientEntry: '${joinURL(resolvedStartConfig.basePaths.publicBase, "@id", ENTRY_POINTS.client)}',
|
|
18
|
-
})`;
|
|
29
|
+
const clientEntry = joinURL(resolvedStartConfig.basePaths.publicBase, "@id", ENTRY_POINTS.client);
|
|
30
|
+
if (this.environment.name !== START_ENVIRONMENT_NAMES.server) return getEmptyStartManifestModule(clientEntry);
|
|
31
|
+
if (this.environment.config.command === "serve") return getEmptyStartManifestModule(clientEntry);
|
|
19
32
|
const routeTreeRoutes = globalThis.TSS_ROUTES_MANIFEST;
|
|
20
|
-
|
|
21
|
-
if (!clientBuild) return `export const tsrStartManifest = () => ({
|
|
22
|
-
routes: {},
|
|
23
|
-
clientEntry: '${joinURL(resolvedStartConfig.basePaths.publicBase, "@id", ENTRY_POINTS.client)}',
|
|
24
|
-
})`;
|
|
33
|
+
if (!clientBuild) return getEmptyStartManifestModule(clientEntry);
|
|
25
34
|
return `export const tsrStartManifest = () => (${serializeStartManifest(buildStartManifest({
|
|
26
35
|
clientBuild,
|
|
27
36
|
routeTreeRoutes,
|
|
28
|
-
basePath: resolvedStartConfig.basePaths.publicBase
|
|
37
|
+
basePath: resolvedStartConfig.basePaths.publicBase,
|
|
38
|
+
additionalRouteAssets: getViteAdditionalRouteAssets({
|
|
39
|
+
cssCodeSplitDisabledFileName,
|
|
40
|
+
basePath: resolvedStartConfig.basePaths.publicBase,
|
|
41
|
+
cssCodeSplit: this.environment.config.build.cssCodeSplit
|
|
42
|
+
})
|
|
29
43
|
}))})`;
|
|
30
44
|
}
|
|
31
|
-
});
|
|
45
|
+
})];
|
|
46
|
+
}
|
|
47
|
+
function getViteAdditionalRouteAssets(options) {
|
|
48
|
+
if (options.cssCodeSplit !== false) return;
|
|
49
|
+
if (!options.cssCodeSplitDisabledFileName) throw new Error("TanStack Start could not find Vite's generated `style.css` manifest entry while `build.cssCodeSplit` is disabled");
|
|
50
|
+
const { getStylesheetAsset } = createManifestAssetResolvers(options.basePath);
|
|
51
|
+
return { [rootRouteId]: [getStylesheetAsset(options.cssCodeSplitDisabledFileName)] };
|
|
52
|
+
}
|
|
53
|
+
function getAssetFileNameByName(bundle, assetName) {
|
|
54
|
+
for (const fileName in bundle) {
|
|
55
|
+
const bundleEntry = bundle[fileName];
|
|
56
|
+
if (bundleEntry.type !== "asset") continue;
|
|
57
|
+
if (bundleEntry.name === assetName) return fileName;
|
|
58
|
+
if ("names" in bundleEntry && bundleEntry.names.includes(assetName)) return fileName;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function getEmptyStartManifestModule(clientEntry) {
|
|
62
|
+
return `export const tsrStartManifest = () => ({
|
|
63
|
+
routes: {},
|
|
64
|
+
clientEntry: '${clientEntry}',
|
|
65
|
+
})`;
|
|
32
66
|
}
|
|
33
67
|
//#endregion
|
|
34
68
|
export { startManifestPlugin };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","names":[],"sources":["../../../../src/vite/start-manifest-plugin/plugin.ts"],"sourcesContent":["import { joinURL } from 'ufo'\nimport { VIRTUAL_MODULES } from '@tanstack/start-server-core'\nimport { ENTRY_POINTS, START_ENVIRONMENT_NAMES } from '../../constants'\nimport {\n buildStartManifest,\n serializeStartManifest,\n} from '../../start-manifest-plugin/manifestBuilder'\nimport { createVirtualModule } from '../createVirtualModule'\nimport type { GetConfigFn, NormalizedClientBuild } from '../../types'\nimport type { PluginOption } from 'vite'\n\nexport function startManifestPlugin(opts: {\n
|
|
1
|
+
{"version":3,"file":"plugin.js","names":[],"sources":["../../../../src/vite/start-manifest-plugin/plugin.ts"],"sourcesContent":["import { joinURL } from 'ufo'\nimport { VIRTUAL_MODULES } from '@tanstack/start-server-core'\nimport { rootRouteId } from '@tanstack/router-core'\nimport { ENTRY_POINTS, START_ENVIRONMENT_NAMES } from '../../constants'\nimport {\n buildStartManifest,\n createManifestAssetResolvers,\n normalizeViteClientBuild,\n serializeStartManifest,\n} from '../../start-manifest-plugin/manifestBuilder'\nimport { createVirtualModule } from '../createVirtualModule'\nimport type { GetConfigFn, NormalizedClientBuild } from '../../types'\nimport type { PluginOption, Rollup } from 'vite'\n\nexport function startManifestPlugin(opts: {\n getConfig: GetConfigFn\n}): PluginOption {\n let clientBuild: NormalizedClientBuild | undefined\n let cssCodeSplitDisabledFileName: string | undefined\n\n return [\n {\n name: 'tanstack-start:start-manifest-capture-client-build',\n applyToEnvironment(environment) {\n return environment.name === START_ENVIRONMENT_NAMES.client\n },\n enforce: 'post',\n generateBundle(_options, bundle) {\n if (this.environment.name !== START_ENVIRONMENT_NAMES.client) {\n throw new Error(\n `Unexpected environment for client build capture: ${this.environment.name}`,\n )\n }\n\n clientBuild = normalizeViteClientBuild(bundle)\n cssCodeSplitDisabledFileName = getAssetFileNameByName(\n bundle,\n 'style.css',\n )\n },\n },\n createVirtualModule({\n name: 'tanstack-start:start-manifest-plugin',\n moduleId: VIRTUAL_MODULES.startManifest,\n enforce: 'pre',\n load() {\n const { resolvedStartConfig } = opts.getConfig()\n const clientEntry = joinURL(\n resolvedStartConfig.basePaths.publicBase,\n '@id',\n ENTRY_POINTS.client,\n )\n\n if (this.environment.name !== START_ENVIRONMENT_NAMES.server) {\n return getEmptyStartManifestModule(clientEntry)\n }\n\n if (this.environment.config.command === 'serve') {\n return getEmptyStartManifestModule(clientEntry)\n }\n\n const routeTreeRoutes = globalThis.TSS_ROUTES_MANIFEST\n // TODO this needs further discussion with vite-rsc, this is a temporary workaround\n // If the client bundle isn't available yet (e.g., during RSC scan builds),\n // return a dummy manifest. The real manifest will be generated in the actual build.\n if (!clientBuild) {\n return getEmptyStartManifestModule(clientEntry)\n }\n const startManifest = buildStartManifest({\n clientBuild,\n routeTreeRoutes,\n basePath: resolvedStartConfig.basePaths.publicBase,\n additionalRouteAssets: getViteAdditionalRouteAssets({\n cssCodeSplitDisabledFileName,\n basePath: resolvedStartConfig.basePaths.publicBase,\n cssCodeSplit: this.environment.config.build.cssCodeSplit,\n }),\n })\n\n return `export const tsrStartManifest = () => (${serializeStartManifest(startManifest)})`\n },\n }),\n ]\n}\n\nfunction getViteAdditionalRouteAssets(options: {\n cssCodeSplitDisabledFileName: string | undefined\n basePath: string\n cssCodeSplit: boolean | undefined\n}) {\n if (options.cssCodeSplit !== false) {\n return undefined\n }\n\n if (!options.cssCodeSplitDisabledFileName) {\n throw new Error(\n \"TanStack Start could not find Vite's generated `style.css` manifest entry while `build.cssCodeSplit` is disabled\",\n )\n }\n\n const { getStylesheetAsset } = createManifestAssetResolvers(options.basePath)\n\n return {\n [rootRouteId]: [getStylesheetAsset(options.cssCodeSplitDisabledFileName)],\n }\n}\n\nfunction getAssetFileNameByName(\n bundle: Rollup.OutputBundle,\n assetName: string,\n) {\n for (const fileName in bundle) {\n const bundleEntry = bundle[fileName]!\n\n if (bundleEntry.type !== 'asset') {\n continue\n }\n\n if (bundleEntry.name === assetName) {\n return fileName\n }\n\n if ('names' in bundleEntry && bundleEntry.names.includes(assetName)) {\n return fileName\n }\n }\n\n return undefined\n}\n\nfunction getEmptyStartManifestModule(clientEntry: string) {\n return `export const tsrStartManifest = () => ({\n routes: {},\n clientEntry: '${clientEntry}',\n })`\n}\n"],"mappings":";;;;;;;;AAcA,SAAgB,oBAAoB,MAEnB;CACf,IAAI;CACJ,IAAI;AAEJ,QAAO,CACL;EACE,MAAM;EACN,mBAAmB,aAAa;AAC9B,UAAO,YAAY,SAAS,wBAAwB;;EAEtD,SAAS;EACT,eAAe,UAAU,QAAQ;AAC/B,OAAI,KAAK,YAAY,SAAS,wBAAwB,OACpD,OAAM,IAAI,MACR,oDAAoD,KAAK,YAAY,OACtE;AAGH,iBAAc,yBAAyB,OAAO;AAC9C,kCAA+B,uBAC7B,QACA,YACD;;EAEJ,EACD,oBAAoB;EAClB,MAAM;EACN,UAAU,gBAAgB;EAC1B,SAAS;EACT,OAAO;GACL,MAAM,EAAE,wBAAwB,KAAK,WAAW;GAChD,MAAM,cAAc,QAClB,oBAAoB,UAAU,YAC9B,OACA,aAAa,OACd;AAED,OAAI,KAAK,YAAY,SAAS,wBAAwB,OACpD,QAAO,4BAA4B,YAAY;AAGjD,OAAI,KAAK,YAAY,OAAO,YAAY,QACtC,QAAO,4BAA4B,YAAY;GAGjD,MAAM,kBAAkB,WAAW;AAInC,OAAI,CAAC,YACH,QAAO,4BAA4B,YAAY;AAajD,UAAO,0CAA0C,uBAX3B,mBAAmB;IACvC;IACA;IACA,UAAU,oBAAoB,UAAU;IACxC,uBAAuB,6BAA6B;KAClD;KACA,UAAU,oBAAoB,UAAU;KACxC,cAAc,KAAK,YAAY,OAAO,MAAM;KAC7C,CAAC;IACH,CAAC,CAEoF,CAAC;;EAE1F,CAAC,CACH;;AAGH,SAAS,6BAA6B,SAInC;AACD,KAAI,QAAQ,iBAAiB,MAC3B;AAGF,KAAI,CAAC,QAAQ,6BACX,OAAM,IAAI,MACR,mHACD;CAGH,MAAM,EAAE,uBAAuB,6BAA6B,QAAQ,SAAS;AAE7E,QAAO,GACJ,cAAc,CAAC,mBAAmB,QAAQ,6BAA6B,CAAC,EAC1E;;AAGH,SAAS,uBACP,QACA,WACA;AACA,MAAK,MAAM,YAAY,QAAQ;EAC7B,MAAM,cAAc,OAAO;AAE3B,MAAI,YAAY,SAAS,QACvB;AAGF,MAAI,YAAY,SAAS,UACvB,QAAO;AAGT,MAAI,WAAW,eAAe,YAAY,MAAM,SAAS,UAAU,CACjE,QAAO;;;AAOb,SAAS,4BAA4B,aAAqB;AACxD,QAAO;;sBAEa,YAAY"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/start-plugin-core",
|
|
3
|
-
"version": "1.167.
|
|
3
|
+
"version": "1.167.35",
|
|
4
4
|
"description": "Modern and scalable routing for React applications",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -67,12 +67,12 @@
|
|
|
67
67
|
"vitefu": "^1.1.1",
|
|
68
68
|
"xmlbuilder2": "^4.0.3",
|
|
69
69
|
"zod": "^3.24.2",
|
|
70
|
-
"@tanstack/router-core": "1.168.
|
|
71
|
-
"@tanstack/router-generator": "1.166.
|
|
72
|
-
"@tanstack/router-plugin": "1.167.
|
|
70
|
+
"@tanstack/router-core": "1.168.15",
|
|
71
|
+
"@tanstack/router-generator": "1.166.32",
|
|
72
|
+
"@tanstack/router-plugin": "1.167.22",
|
|
73
73
|
"@tanstack/router-utils": "1.161.6",
|
|
74
|
-
"@tanstack/start-client-core": "1.167.
|
|
75
|
-
"@tanstack/start-server-core": "1.167.
|
|
74
|
+
"@tanstack/start-client-core": "1.167.17",
|
|
75
|
+
"@tanstack/start-server-core": "1.167.19"
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
78
|
"@types/babel__code-frame": "^7.0.6",
|
|
@@ -10,8 +10,6 @@ import {
|
|
|
10
10
|
import type { ManifestAssetLink, RouterManagedTag } from '@tanstack/router-core'
|
|
11
11
|
import type { NormalizedClientBuild, NormalizedClientChunk } from '../types'
|
|
12
12
|
|
|
13
|
-
const ROUTER_MANAGED_MODE = 1
|
|
14
|
-
const NON_ROUTE_DYNAMIC_MODE = 2
|
|
15
13
|
const VISITING_CHUNK = 1
|
|
16
14
|
|
|
17
15
|
type RouteTreeRoute = {
|
|
@@ -27,7 +25,6 @@ interface ScannedClientChunks {
|
|
|
27
25
|
entryChunk: NormalizedClientChunk
|
|
28
26
|
chunksByFileName: ReadonlyMap<string, NormalizedClientChunk>
|
|
29
27
|
routeChunksByFilePath: ReadonlyMap<string, Array<NormalizedClientChunk>>
|
|
30
|
-
routeEntryChunks: ReadonlySet<NormalizedClientChunk>
|
|
31
28
|
}
|
|
32
29
|
|
|
33
30
|
interface ManifestAssetResolvers {
|
|
@@ -114,19 +111,25 @@ export function appendUniqueAssets(
|
|
|
114
111
|
}
|
|
115
112
|
|
|
116
113
|
function getAssetIdentity(asset: RouterManagedTag) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
114
|
+
return JSON.stringify({
|
|
115
|
+
tag: asset.tag,
|
|
116
|
+
attrs: normalizeAssetAttrs(asset.attrs),
|
|
117
|
+
children: 'children' in asset ? (asset.children ?? null) : null,
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function normalizeAssetAttrs(attrs: Record<string, any> | undefined) {
|
|
122
|
+
if (!attrs) {
|
|
123
|
+
return null
|
|
127
124
|
}
|
|
128
125
|
|
|
129
|
-
|
|
126
|
+
const entries = Object.entries(attrs)
|
|
127
|
+
if (entries.length === 0) {
|
|
128
|
+
return null
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
entries.sort(([left], [right]) => left.localeCompare(right))
|
|
132
|
+
return Object.fromEntries(entries)
|
|
130
133
|
}
|
|
131
134
|
|
|
132
135
|
function mergeRouteChunkData(options: {
|
|
@@ -149,17 +152,12 @@ export function buildStartManifest(options: {
|
|
|
149
152
|
clientBuild: NormalizedClientBuild
|
|
150
153
|
routeTreeRoutes: RouteTreeRoutes
|
|
151
154
|
basePath: string
|
|
155
|
+
additionalRouteAssets?: Partial<
|
|
156
|
+
Record<string, ReadonlyArray<RouterManagedTag>>
|
|
157
|
+
>
|
|
152
158
|
}): StartManifest {
|
|
153
159
|
const scannedChunks = scanClientChunks(options.clientBuild)
|
|
154
|
-
const
|
|
155
|
-
scannedChunks.routeEntryChunks,
|
|
156
|
-
scannedChunks.chunksByFileName,
|
|
157
|
-
scannedChunks.entryChunk,
|
|
158
|
-
)
|
|
159
|
-
const assetResolvers = createManifestAssetResolvers({
|
|
160
|
-
basePath: options.basePath,
|
|
161
|
-
hashedCssFiles,
|
|
162
|
-
})
|
|
160
|
+
const assetResolvers = createManifestAssetResolvers(options.basePath)
|
|
163
161
|
|
|
164
162
|
const routes = buildRouteManifestRoutes({
|
|
165
163
|
routeTreeRoutes: options.routeTreeRoutes,
|
|
@@ -167,6 +165,7 @@ export function buildStartManifest(options: {
|
|
|
167
165
|
chunksByFileName: scannedChunks.chunksByFileName,
|
|
168
166
|
entryChunk: scannedChunks.entryChunk,
|
|
169
167
|
assetResolvers,
|
|
168
|
+
additionalRouteAssets: options.additionalRouteAssets,
|
|
170
169
|
})
|
|
171
170
|
|
|
172
171
|
dedupeNestedRouteManifestEntries(rootRouteId, routes[rootRouteId]!, routes)
|
|
@@ -202,13 +201,10 @@ export function scanClientChunks(
|
|
|
202
201
|
throw new Error(`Missing entry chunk: ${clientBuild.entryChunkFileName}`)
|
|
203
202
|
}
|
|
204
203
|
|
|
205
|
-
const routeEntryChunks = new Set<NormalizedClientChunk>()
|
|
206
204
|
const routeChunksByFilePath = new Map<string, Array<NormalizedClientChunk>>()
|
|
207
205
|
|
|
208
206
|
for (const chunk of clientBuild.chunksByFileName.values()) {
|
|
209
207
|
if (chunk.routeFilePaths.length > 0) {
|
|
210
|
-
routeEntryChunks.add(chunk)
|
|
211
|
-
|
|
212
208
|
for (const routeFilePath of chunk.routeFilePaths) {
|
|
213
209
|
let chunks = routeChunksByFilePath.get(routeFilePath)
|
|
214
210
|
if (chunks === undefined) {
|
|
@@ -224,92 +220,12 @@ export function scanClientChunks(
|
|
|
224
220
|
entryChunk,
|
|
225
221
|
chunksByFileName: clientBuild.chunksByFileName,
|
|
226
222
|
routeChunksByFilePath,
|
|
227
|
-
routeEntryChunks,
|
|
228
223
|
}
|
|
229
224
|
}
|
|
230
225
|
|
|
231
|
-
export function
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
entryChunk?: NormalizedClientChunk,
|
|
235
|
-
) {
|
|
236
|
-
const routerManagedCssFiles = new Set<string>()
|
|
237
|
-
const nonRouteDynamicCssFiles = new Set<string>()
|
|
238
|
-
const hashedCssFiles = new Set<string>()
|
|
239
|
-
const visitedByChunk = new Map<NormalizedClientChunk, number>()
|
|
240
|
-
const chunkStack: Array<NormalizedClientChunk> = []
|
|
241
|
-
const modeStack: Array<number> = []
|
|
242
|
-
|
|
243
|
-
for (const routeEntryChunk of routeEntryChunks) {
|
|
244
|
-
chunkStack.push(routeEntryChunk)
|
|
245
|
-
modeStack.push(ROUTER_MANAGED_MODE)
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
if (entryChunk) {
|
|
249
|
-
chunkStack.push(entryChunk)
|
|
250
|
-
modeStack.push(ROUTER_MANAGED_MODE)
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
while (chunkStack.length > 0) {
|
|
254
|
-
const chunk = chunkStack.pop()!
|
|
255
|
-
const mode = modeStack.pop()!
|
|
256
|
-
const previousMode = visitedByChunk.get(chunk) ?? 0
|
|
257
|
-
|
|
258
|
-
if ((previousMode & mode) === mode) {
|
|
259
|
-
continue
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
visitedByChunk.set(chunk, previousMode | mode)
|
|
263
|
-
|
|
264
|
-
if ((mode & ROUTER_MANAGED_MODE) !== 0) {
|
|
265
|
-
for (const cssFile of chunk.css) {
|
|
266
|
-
routerManagedCssFiles.add(cssFile)
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
if ((mode & NON_ROUTE_DYNAMIC_MODE) !== 0) {
|
|
271
|
-
for (const cssFile of chunk.css) {
|
|
272
|
-
nonRouteDynamicCssFiles.add(cssFile)
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
for (let i = 0; i < chunk.imports.length; i++) {
|
|
277
|
-
const importedChunk = chunksByFileName.get(chunk.imports[i]!)
|
|
278
|
-
if (importedChunk) {
|
|
279
|
-
chunkStack.push(importedChunk)
|
|
280
|
-
modeStack.push(mode)
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
for (let i = 0; i < chunk.dynamicImports.length; i++) {
|
|
285
|
-
const dynamicImportedChunk = chunksByFileName.get(
|
|
286
|
-
chunk.dynamicImports[i]!,
|
|
287
|
-
)
|
|
288
|
-
if (dynamicImportedChunk) {
|
|
289
|
-
chunkStack.push(dynamicImportedChunk)
|
|
290
|
-
modeStack.push(
|
|
291
|
-
(mode & NON_ROUTE_DYNAMIC_MODE) !== 0 ||
|
|
292
|
-
!routeEntryChunks.has(dynamicImportedChunk)
|
|
293
|
-
? NON_ROUTE_DYNAMIC_MODE
|
|
294
|
-
: ROUTER_MANAGED_MODE,
|
|
295
|
-
)
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
for (const cssFile of routerManagedCssFiles) {
|
|
301
|
-
if (nonRouteDynamicCssFiles.has(cssFile)) {
|
|
302
|
-
hashedCssFiles.add(cssFile)
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
return hashedCssFiles
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
export function createManifestAssetResolvers(options: {
|
|
310
|
-
basePath: string
|
|
311
|
-
hashedCssFiles?: Set<string>
|
|
312
|
-
}): ManifestAssetResolvers {
|
|
226
|
+
export function createManifestAssetResolvers(
|
|
227
|
+
basePath: string,
|
|
228
|
+
): ManifestAssetResolvers {
|
|
313
229
|
const assetPathByFileName = new Map<string, string>()
|
|
314
230
|
const stylesheetAssetByFileName = new Map<string, RouterManagedTag>()
|
|
315
231
|
const preloadsByChunk = new Map<NormalizedClientChunk, Array<string>>()
|
|
@@ -320,7 +236,7 @@ export function createManifestAssetResolvers(options: {
|
|
|
320
236
|
return cachedPath
|
|
321
237
|
}
|
|
322
238
|
|
|
323
|
-
const assetPath = joinURL(
|
|
239
|
+
const assetPath = joinURL(basePath, fileName)
|
|
324
240
|
assetPathByFileName.set(fileName, assetPath)
|
|
325
241
|
return assetPath
|
|
326
242
|
}
|
|
@@ -336,7 +252,7 @@ export function createManifestAssetResolvers(options: {
|
|
|
336
252
|
tag: 'link',
|
|
337
253
|
attrs: {
|
|
338
254
|
rel: 'stylesheet',
|
|
339
|
-
href
|
|
255
|
+
href,
|
|
340
256
|
type: 'text/css',
|
|
341
257
|
},
|
|
342
258
|
} satisfies RouterManagedTag
|
|
@@ -380,15 +296,14 @@ export function createChunkCssAssetCollector(options: {
|
|
|
380
296
|
|
|
381
297
|
const appendAsset = (
|
|
382
298
|
assets: Array<RouterManagedTag>,
|
|
383
|
-
seenAssets: Set<
|
|
299
|
+
seenAssets: Set<RouterManagedTag>,
|
|
384
300
|
asset: RouterManagedTag,
|
|
385
301
|
) => {
|
|
386
|
-
|
|
387
|
-
if (seenAssets.has(identity)) {
|
|
302
|
+
if (seenAssets.has(asset)) {
|
|
388
303
|
return
|
|
389
304
|
}
|
|
390
305
|
|
|
391
|
-
seenAssets.add(
|
|
306
|
+
seenAssets.add(asset)
|
|
392
307
|
assets.push(asset)
|
|
393
308
|
}
|
|
394
309
|
|
|
@@ -406,7 +321,7 @@ export function createChunkCssAssetCollector(options: {
|
|
|
406
321
|
stateByChunk.set(chunk, VISITING_CHUNK)
|
|
407
322
|
|
|
408
323
|
const assets: Array<RouterManagedTag> = []
|
|
409
|
-
const seenAssets = new Set<
|
|
324
|
+
const seenAssets = new Set<RouterManagedTag>()
|
|
410
325
|
|
|
411
326
|
for (const cssFile of chunk.css) {
|
|
412
327
|
appendAsset(assets, seenAssets, options.getStylesheetAsset(cssFile))
|
|
@@ -441,6 +356,9 @@ export function buildRouteManifestRoutes(options: {
|
|
|
441
356
|
chunksByFileName: ReadonlyMap<string, NormalizedClientChunk>
|
|
442
357
|
entryChunk: NormalizedClientChunk
|
|
443
358
|
assetResolvers: ManifestAssetResolvers
|
|
359
|
+
additionalRouteAssets?: Partial<
|
|
360
|
+
Record<string, ReadonlyArray<RouterManagedTag>>
|
|
361
|
+
>
|
|
444
362
|
}) {
|
|
445
363
|
const routes: Record<string, RouteTreeRoute> = {}
|
|
446
364
|
const getChunkCssAssets = createChunkCssAssetCollector({
|
|
@@ -485,6 +403,25 @@ export function buildRouteManifestRoutes(options: {
|
|
|
485
403
|
getChunkPreloads: options.assetResolvers.getChunkPreloads,
|
|
486
404
|
})
|
|
487
405
|
|
|
406
|
+
if (options.additionalRouteAssets) {
|
|
407
|
+
for (const [routeId, assets] of Object.entries(
|
|
408
|
+
options.additionalRouteAssets,
|
|
409
|
+
)) {
|
|
410
|
+
if (!assets || assets.length === 0) {
|
|
411
|
+
continue
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (!(routeId in options.routeTreeRoutes)) {
|
|
415
|
+
throw new Error(
|
|
416
|
+
`expected additionalRouteAssets routeId to exist in routeTreeRoutes: ${routeId}`,
|
|
417
|
+
)
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const route = (routes[routeId] = routes[routeId] || {})
|
|
421
|
+
route.assets = appendUniqueAssets(route.assets, [...assets])
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
488
425
|
return routes
|
|
489
426
|
}
|
|
490
427
|
|
package/src/vite/plugin.ts
CHANGED
|
@@ -22,7 +22,6 @@ import {
|
|
|
22
22
|
import { devServerPlugin } from './dev-server-plugin/plugin'
|
|
23
23
|
import { previewServerPlugin } from './preview-server-plugin/plugin'
|
|
24
24
|
import {
|
|
25
|
-
createCaptureClientBuildPlugin,
|
|
26
25
|
createDevBaseRewritePlugin,
|
|
27
26
|
createPostBuildPlugin,
|
|
28
27
|
createVirtualClientEntryPlugin,
|
|
@@ -36,12 +35,10 @@ import {
|
|
|
36
35
|
} from './output-directory'
|
|
37
36
|
import { postServerBuild } from './post-server-build'
|
|
38
37
|
import { serializationAdaptersPlugin } from './serialization-adapters-plugin'
|
|
39
|
-
import type { NormalizedClientBuild } from '../types'
|
|
40
38
|
import type {
|
|
41
39
|
TanStackStartVitePluginCoreOptions,
|
|
42
40
|
ViteRscForwardSsrResolverStrategy,
|
|
43
41
|
} from './types'
|
|
44
|
-
import type { StartEnvironmentName } from '../constants'
|
|
45
42
|
import type { TanStackStartViteInputConfig } from './schema'
|
|
46
43
|
import type { PluginOption } from 'vite'
|
|
47
44
|
|
|
@@ -64,16 +61,6 @@ export function tanStackStartVite(
|
|
|
64
61
|
// we install a URL rewrite middleware instead of erroring.
|
|
65
62
|
let needsDevBaseRewrite = false
|
|
66
63
|
|
|
67
|
-
const capturedClientBuild: Partial<
|
|
68
|
-
Record<StartEnvironmentName, NormalizedClientBuild>
|
|
69
|
-
> = {}
|
|
70
|
-
|
|
71
|
-
function getClientBuild(
|
|
72
|
-
envName: StartEnvironmentName,
|
|
73
|
-
): NormalizedClientBuild | undefined {
|
|
74
|
-
return capturedClientBuild[envName]
|
|
75
|
-
}
|
|
76
|
-
|
|
77
64
|
const environments: Array<{
|
|
78
65
|
name: string
|
|
79
66
|
type: 'client' | 'server'
|
|
@@ -242,7 +229,6 @@ export function tanStackStartVite(
|
|
|
242
229
|
getClientEntry: () => configContext.resolveEntries().entryPaths.client,
|
|
243
230
|
}),
|
|
244
231
|
startManifestPlugin({
|
|
245
|
-
getClientBuild: () => getClientBuild(START_ENVIRONMENT_NAMES.client),
|
|
246
232
|
getConfig,
|
|
247
233
|
}),
|
|
248
234
|
// When the vite base and router basepath are misaligned (e.g. base: '/_ui/', basepath: '/'),
|
|
@@ -266,9 +252,6 @@ export function tanStackStartVite(
|
|
|
266
252
|
serializationAdaptersPlugin({
|
|
267
253
|
adapters: corePluginOpts.serializationAdapters,
|
|
268
254
|
}),
|
|
269
|
-
createCaptureClientBuildPlugin({
|
|
270
|
-
capturedClientBuild,
|
|
271
|
-
}),
|
|
272
255
|
]
|
|
273
256
|
}
|
|
274
257
|
|
package/src/vite/plugins.ts
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import { normalizePath } from 'vite'
|
|
2
|
-
import { ENTRY_POINTS
|
|
2
|
+
import { ENTRY_POINTS } from '../constants'
|
|
3
3
|
import { createVirtualModule } from './createVirtualModule'
|
|
4
|
-
import {
|
|
5
|
-
import type {
|
|
6
|
-
GetConfigFn,
|
|
7
|
-
NormalizedClientBuild,
|
|
8
|
-
ResolvedStartConfig,
|
|
9
|
-
} from '../types'
|
|
10
|
-
import type { StartEnvironmentName } from '../constants'
|
|
4
|
+
import type { GetConfigFn, ResolvedStartConfig } from '../types'
|
|
11
5
|
import type { PluginOption, ViteBuilder } from 'vite'
|
|
12
6
|
|
|
13
7
|
export function createVirtualClientEntryPlugin(opts: {
|
|
@@ -69,28 +63,3 @@ export function createDevBaseRewritePlugin(opts: {
|
|
|
69
63
|
},
|
|
70
64
|
}
|
|
71
65
|
}
|
|
72
|
-
|
|
73
|
-
export function createCaptureClientBuildPlugin(opts: {
|
|
74
|
-
capturedClientBuild: Partial<
|
|
75
|
-
Record<StartEnvironmentName, NormalizedClientBuild>
|
|
76
|
-
>
|
|
77
|
-
}): PluginOption {
|
|
78
|
-
return {
|
|
79
|
-
name: 'tanstack-start:core:capture-bundle',
|
|
80
|
-
applyToEnvironment(environment) {
|
|
81
|
-
return environment.name === START_ENVIRONMENT_NAMES.client
|
|
82
|
-
},
|
|
83
|
-
enforce: 'post',
|
|
84
|
-
generateBundle(_options, bundle) {
|
|
85
|
-
const environment = this.environment.name as StartEnvironmentName
|
|
86
|
-
|
|
87
|
-
if (environment !== START_ENVIRONMENT_NAMES.client) {
|
|
88
|
-
throw new Error(
|
|
89
|
-
`Unexpected environment for client build capture: ${environment}`,
|
|
90
|
-
)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
opts.capturedClientBuild[environment] = normalizeViteClientBuild(bundle)
|
|
94
|
-
},
|
|
95
|
-
}
|
|
96
|
-
}
|
|
@@ -42,6 +42,8 @@ export function normalizeViteClientBuild(
|
|
|
42
42
|
const cssFilesBySourcePath = new Map<string, Array<string>>()
|
|
43
43
|
|
|
44
44
|
for (const chunk of chunksByFileName.values()) {
|
|
45
|
+
const bundleEntry = clientBundle[chunk.fileName] as Rollup.OutputChunk
|
|
46
|
+
|
|
45
47
|
if (chunk.isEntry) {
|
|
46
48
|
if (entryChunkFileName) {
|
|
47
49
|
throw new Error(
|
|
@@ -60,22 +62,19 @@ export function normalizeViteClientBuild(
|
|
|
60
62
|
chunkFileNames.push(chunk.fileName)
|
|
61
63
|
}
|
|
62
64
|
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
: chunk.css.slice(),
|
|
77
|
-
)
|
|
78
|
-
}
|
|
65
|
+
for (const moduleId of bundleEntry.moduleIds) {
|
|
66
|
+
const queryIndex = moduleId.indexOf('?')
|
|
67
|
+
const sourcePath =
|
|
68
|
+
queryIndex >= 0 ? moduleId.slice(0, queryIndex) : moduleId
|
|
69
|
+
if (!sourcePath) continue
|
|
70
|
+
|
|
71
|
+
const existing = cssFilesBySourcePath.get(sourcePath)
|
|
72
|
+
cssFilesBySourcePath.set(
|
|
73
|
+
sourcePath,
|
|
74
|
+
existing
|
|
75
|
+
? Array.from(new Set([...existing, ...chunk.css]))
|
|
76
|
+
: chunk.css.slice(),
|
|
77
|
+
)
|
|
79
78
|
}
|
|
80
79
|
}
|
|
81
80
|
|