@tanstack/start-plugin-core 1.167.7 → 1.167.9

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.
@@ -1,4 +1,4 @@
1
- import { ManifestAssetLink, RouterManagedTag } from '@tanstack/router-core';
1
+ import { RouterManagedTag } from '@tanstack/router-core';
2
2
  import { Rollup } from 'vite';
3
3
  type RouteTreeRoute = {
4
4
  filePath?: string;
@@ -18,10 +18,6 @@ interface ManifestAssetResolvers {
18
18
  getChunkPreloads: (chunk: Rollup.OutputChunk) => Array<string>;
19
19
  getStylesheetAsset: (cssFile: string) => RouterManagedTag;
20
20
  }
21
- type DedupePreloadRoute = {
22
- preloads?: Array<ManifestAssetLink>;
23
- children?: Array<string>;
24
- };
25
21
  export declare function appendUniqueStrings(target: Array<string> | undefined, source: Array<string>): string[] | undefined;
26
22
  export declare function appendUniqueAssets(target: Array<RouterManagedTag> | undefined, source: Array<RouterManagedTag>): RouterManagedTag[] | undefined;
27
23
  export declare function buildStartManifest(options: {
@@ -52,5 +48,4 @@ export declare function buildRouteManifestRoutes(options: {
52
48
  entryChunk: Rollup.OutputChunk;
53
49
  assetResolvers: ManifestAssetResolvers;
54
50
  }): Record<string, RouteTreeRoute>;
55
- export declare function dedupeNestedRoutePreloads(route: DedupePreloadRoute, routesById: Record<string, DedupePreloadRoute>, seenPreloads?: Set<string>): void;
56
51
  export {};
@@ -66,7 +66,7 @@ function buildStartManifest(options) {
66
66
  entryChunk: scannedChunks.entryChunk,
67
67
  assetResolvers
68
68
  });
69
- dedupeNestedRoutePreloads(routes[rootRouteId], routes);
69
+ dedupeNestedRouteManifestEntries(rootRouteId, routes[rootRouteId], routes);
70
70
  for (const routeId of Object.keys(routes)) {
71
71
  const route = routes[routeId];
72
72
  const hasAssets = route.assets && route.assets.length > 0;
@@ -216,18 +216,25 @@ function createManifestAssetResolvers(options) {
216
216
  function createChunkCssAssetCollector(options) {
217
217
  const assetsByChunk = /* @__PURE__ */ new Map();
218
218
  const stateByChunk = /* @__PURE__ */ new Map();
219
+ const appendAsset = (assets, seenAssets, asset) => {
220
+ const identity = getAssetIdentity(asset);
221
+ if (seenAssets.has(identity)) return;
222
+ seenAssets.add(identity);
223
+ assets.push(asset);
224
+ };
219
225
  const getChunkCssAssets = (chunk) => {
220
226
  const cachedAssets = assetsByChunk.get(chunk);
221
227
  if (cachedAssets) return cachedAssets;
222
228
  if (stateByChunk.get(chunk) === VISITING_CHUNK) return [];
223
229
  stateByChunk.set(chunk, VISITING_CHUNK);
224
230
  const assets = [];
225
- for (const cssFile of chunk.viteMetadata?.importedCss ?? []) assets.push(options.getStylesheetAsset(cssFile));
231
+ const seenAssets = /* @__PURE__ */ new Set();
232
+ for (const cssFile of chunk.viteMetadata?.importedCss ?? []) appendAsset(assets, seenAssets, options.getStylesheetAsset(cssFile));
226
233
  for (let i = 0; i < chunk.imports.length; i++) {
227
234
  const importedChunk = options.chunksByFileName.get(chunk.imports[i]);
228
235
  if (!importedChunk) continue;
229
236
  const importedAssets = getChunkCssAssets(importedChunk);
230
- for (let j = 0; j < importedAssets.length; j++) assets.push(importedAssets[j]);
237
+ for (let j = 0; j < importedAssets.length; j++) appendAsset(assets, seenAssets, importedAssets[j]);
231
238
  }
232
239
  stateByChunk.delete(chunk);
233
240
  assetsByChunk.set(chunk, assets);
@@ -271,8 +278,9 @@ function buildRouteManifestRoutes(options) {
271
278
  });
272
279
  return routes;
273
280
  }
274
- function dedupeNestedRoutePreloads(route, routesById, seenPreloads = /* @__PURE__ */ new Set()) {
281
+ function dedupeNestedRouteManifestEntries(routeId, route, routesById, seenPreloads = /* @__PURE__ */ new Set(), seenAssets = /* @__PURE__ */ new Set()) {
275
282
  let routePreloads = route.preloads;
283
+ let routeAssets = route.assets;
276
284
  if (routePreloads && routePreloads.length > 0) {
277
285
  let dedupedPreloads;
278
286
  for (let i = 0; i < routePreloads.length; i++) {
@@ -290,8 +298,30 @@ function dedupeNestedRoutePreloads(route, routesById, seenPreloads = /* @__PURE_
290
298
  route.preloads = dedupedPreloads;
291
299
  }
292
300
  }
293
- if (route.children) for (const childRouteId of route.children) dedupeNestedRoutePreloads(routesById[childRouteId], routesById, seenPreloads);
301
+ if (routeAssets && routeAssets.length > 0) {
302
+ let dedupedAssets;
303
+ for (let i = 0; i < routeAssets.length; i++) {
304
+ const asset = routeAssets[i];
305
+ const identity = getAssetIdentity(asset);
306
+ if (seenAssets.has(identity)) {
307
+ if (dedupedAssets === void 0) dedupedAssets = routeAssets.slice(0, i);
308
+ continue;
309
+ }
310
+ seenAssets.add(identity);
311
+ if (dedupedAssets) dedupedAssets.push(asset);
312
+ }
313
+ if (dedupedAssets) {
314
+ routeAssets = dedupedAssets;
315
+ route.assets = dedupedAssets;
316
+ }
317
+ }
318
+ if (route.children) for (const childRouteId of route.children) {
319
+ const childRoute = routesById[childRouteId];
320
+ if (!childRoute) throw new Error(`Route tree references child route ${childRouteId} from ${routeId}, but no route entry was found`);
321
+ dedupeNestedRouteManifestEntries(childRouteId, childRoute, routesById, seenPreloads, seenAssets);
322
+ }
294
323
  if (routePreloads) for (let i = routePreloads.length - 1; i >= 0; i--) seenPreloads.delete(resolveManifestAssetLink(routePreloads[i]).href);
324
+ if (routeAssets) for (let i = routeAssets.length - 1; i >= 0; i--) seenAssets.delete(getAssetIdentity(routeAssets[i]));
295
325
  }
296
326
  //#endregion
297
327
  export { buildStartManifest };
@@ -1 +1 @@
1
- {"version":3,"file":"manifestBuilder.js","names":[],"sources":["../../../src/start-manifest-plugin/manifestBuilder.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/prefer-for-of */\nimport { joinURL } from 'ufo'\nimport { resolveManifestAssetLink, rootRouteId } from '@tanstack/router-core'\nimport { tsrSplit } from '@tanstack/router-plugin'\nimport type { ManifestAssetLink, RouterManagedTag } from '@tanstack/router-core'\nimport type { Rollup } from 'vite'\n\nconst ROUTER_MANAGED_MODE = 1\nconst NON_ROUTE_DYNAMIC_MODE = 2\nconst VISITING_CHUNK = 1\n\ntype RouteTreeRoute = {\n filePath?: string\n preloads?: Array<string>\n assets?: Array<RouterManagedTag>\n children?: Array<string>\n}\n\ntype RouteTreeRoutes = Record<string, RouteTreeRoute>\n\ninterface ScannedClientChunks {\n entryChunk: Rollup.OutputChunk\n chunksByFileName: Map<string, Rollup.OutputChunk>\n routeChunksByFilePath: Map<string, Array<Rollup.OutputChunk>>\n routeEntryChunks: Set<Rollup.OutputChunk>\n}\n\ninterface ManifestAssetResolvers {\n getAssetPath: (fileName: string) => string\n getChunkPreloads: (chunk: Rollup.OutputChunk) => Array<string>\n getStylesheetAsset: (cssFile: string) => RouterManagedTag\n}\n\ntype DedupePreloadRoute = {\n preloads?: Array<ManifestAssetLink>\n children?: Array<string>\n}\n\nexport function appendUniqueStrings(\n target: Array<string> | undefined,\n source: Array<string>,\n) {\n // Similar to Set.prototype.union, but for ordered arrays.\n // It preserves first-seen order and returns the original target array when\n // source contributes no new values, which avoids extra allocations.\n if (source.length === 0) {\n return target\n }\n\n if (!target || target.length === 0) {\n return source\n }\n\n const seen = new Set(target)\n let result: Array<string> | undefined\n\n for (const value of source) {\n if (seen.has(value)) {\n continue\n }\n\n seen.add(value)\n if (!result) {\n result = target.slice()\n }\n result.push(value)\n }\n\n return result ?? target\n}\n\nexport function appendUniqueAssets(\n target: Array<RouterManagedTag> | undefined,\n source: Array<RouterManagedTag>,\n) {\n // Same semantics as appendUniqueStrings, but uniqueness is based on the\n // serialized asset identity instead of object reference.\n if (source.length === 0) {\n return target\n }\n\n if (!target || target.length === 0) {\n return source\n }\n\n const seen = new Set(target.map(getAssetIdentity))\n let result: Array<RouterManagedTag> | undefined\n\n for (const asset of source) {\n const identity = getAssetIdentity(asset)\n if (seen.has(identity)) {\n continue\n }\n\n seen.add(identity)\n if (!result) {\n result = target.slice()\n }\n result.push(asset)\n }\n\n return result ?? target\n}\n\nfunction getAssetIdentity(asset: RouterManagedTag) {\n if (asset.tag === 'link' || asset.tag === 'script') {\n const attrs = asset.attrs ?? {}\n return [\n asset.tag,\n 'href' in attrs ? String(attrs.href) : '',\n 'src' in attrs ? String(attrs.src) : '',\n 'rel' in attrs ? String(attrs.rel) : '',\n 'type' in attrs ? String(attrs.type) : '',\n asset.children ?? '',\n ].join('|')\n }\n\n return JSON.stringify(asset)\n}\n\nfunction mergeRouteChunkData(options: {\n route: RouteTreeRoute\n chunk: Rollup.OutputChunk\n getChunkCssAssets: (chunk: Rollup.OutputChunk) => Array<RouterManagedTag>\n getChunkPreloads: (chunk: Rollup.OutputChunk) => Array<string>\n}) {\n const chunkAssets = options.getChunkCssAssets(options.chunk)\n const chunkPreloads = options.getChunkPreloads(options.chunk)\n\n options.route.assets = appendUniqueAssets(options.route.assets, chunkAssets)\n options.route.preloads = appendUniqueStrings(\n options.route.preloads,\n chunkPreloads,\n )\n}\n\nexport function buildStartManifest(options: {\n clientBundle: Rollup.OutputBundle\n routeTreeRoutes: RouteTreeRoutes\n basePath: string\n}) {\n const scannedChunks = scanClientChunks(options.clientBundle)\n const hashedCssFiles = collectDynamicImportCss(\n scannedChunks.routeEntryChunks,\n scannedChunks.chunksByFileName,\n scannedChunks.entryChunk,\n )\n const assetResolvers = createManifestAssetResolvers({\n basePath: options.basePath,\n hashedCssFiles,\n })\n\n const routes = buildRouteManifestRoutes({\n routeTreeRoutes: options.routeTreeRoutes,\n routeChunksByFilePath: scannedChunks.routeChunksByFilePath,\n chunksByFileName: scannedChunks.chunksByFileName,\n entryChunk: scannedChunks.entryChunk,\n assetResolvers,\n })\n\n dedupeNestedRoutePreloads(routes[rootRouteId]!, routes)\n\n // Prune routes with no assets or preloads from the manifest\n for (const routeId of Object.keys(routes)) {\n const route = routes[routeId]!\n const hasAssets = route.assets && route.assets.length > 0\n const hasPreloads = route.preloads && route.preloads.length > 0\n if (!hasAssets && !hasPreloads) {\n delete routes[routeId]\n }\n }\n\n return {\n routes,\n clientEntry: assetResolvers.getAssetPath(scannedChunks.entryChunk.fileName),\n }\n}\n\nexport function scanClientChunks(\n clientBundle: Rollup.OutputBundle,\n): ScannedClientChunks {\n let entryChunk: Rollup.OutputChunk | undefined\n const chunksByFileName = new Map<string, Rollup.OutputChunk>()\n const routeChunksByFilePath = new Map<string, Array<Rollup.OutputChunk>>()\n const routeEntryChunks = new Set<Rollup.OutputChunk>()\n\n for (const fileName in clientBundle) {\n const bundleEntry = clientBundle[fileName]!\n if (bundleEntry.type !== 'chunk') {\n continue\n }\n\n chunksByFileName.set(bundleEntry.fileName, bundleEntry)\n\n if (bundleEntry.isEntry) {\n if (entryChunk) {\n throw new Error(\n `multiple entries detected: ${entryChunk.fileName} ${bundleEntry.fileName}`,\n )\n }\n entryChunk = bundleEntry\n }\n\n const routeFilePaths = getRouteFilePathsFromModuleIds(bundleEntry.moduleIds)\n if (routeFilePaths.length === 0) {\n continue\n }\n\n routeEntryChunks.add(bundleEntry)\n\n for (let i = 0; i < routeFilePaths.length; i++) {\n const routeFilePath = routeFilePaths[i]!\n let chunks = routeChunksByFilePath.get(routeFilePath)\n if (chunks === undefined) {\n chunks = []\n routeChunksByFilePath.set(routeFilePath, chunks)\n }\n chunks.push(bundleEntry)\n }\n }\n\n if (!entryChunk) {\n throw new Error('No entry file found')\n }\n\n return {\n entryChunk,\n chunksByFileName,\n routeChunksByFilePath,\n routeEntryChunks,\n }\n}\n\nexport function getRouteFilePathsFromModuleIds(moduleIds: Array<string>) {\n let routeFilePaths: Array<string> | undefined\n let seenRouteFilePaths: Set<string> | undefined\n\n for (const moduleId of moduleIds) {\n const queryIndex = moduleId.indexOf('?')\n\n if (queryIndex < 0) {\n continue\n }\n\n const query = moduleId.slice(queryIndex + 1)\n\n // Fast check before allocating URLSearchParams\n if (!query.includes(tsrSplit)) {\n continue\n }\n\n if (!new URLSearchParams(query).has(tsrSplit)) {\n continue\n }\n\n const routeFilePath = moduleId.slice(0, queryIndex)\n\n if (seenRouteFilePaths?.has(routeFilePath)) {\n continue\n }\n\n if (routeFilePaths === undefined) {\n routeFilePaths = []\n seenRouteFilePaths = new Set<string>()\n }\n\n routeFilePaths.push(routeFilePath)\n seenRouteFilePaths!.add(routeFilePath)\n }\n\n return routeFilePaths ?? []\n}\n\nexport function collectDynamicImportCss(\n routeEntryChunks: Set<Rollup.OutputChunk>,\n chunksByFileName: Map<string, Rollup.OutputChunk>,\n entryChunk?: Rollup.OutputChunk,\n) {\n const routerManagedCssFiles = new Set<string>()\n const nonRouteDynamicCssFiles = new Set<string>()\n const hashedCssFiles = new Set<string>()\n const visitedByChunk = new Map<Rollup.OutputChunk, number>()\n const chunkStack: Array<Rollup.OutputChunk> = []\n const modeStack: Array<number> = []\n\n for (const routeEntryChunk of routeEntryChunks) {\n chunkStack.push(routeEntryChunk)\n modeStack.push(ROUTER_MANAGED_MODE)\n }\n\n if (entryChunk) {\n chunkStack.push(entryChunk)\n modeStack.push(ROUTER_MANAGED_MODE)\n }\n\n while (chunkStack.length > 0) {\n const chunk = chunkStack.pop()!\n const mode = modeStack.pop()!\n const previousMode = visitedByChunk.get(chunk) ?? 0\n\n if ((previousMode & mode) === mode) {\n continue\n }\n\n visitedByChunk.set(chunk, previousMode | mode)\n\n if ((mode & ROUTER_MANAGED_MODE) !== 0) {\n for (const cssFile of chunk.viteMetadata?.importedCss ?? []) {\n routerManagedCssFiles.add(cssFile)\n }\n }\n\n if ((mode & NON_ROUTE_DYNAMIC_MODE) !== 0) {\n for (const cssFile of chunk.viteMetadata?.importedCss ?? []) {\n nonRouteDynamicCssFiles.add(cssFile)\n }\n }\n\n for (let i = 0; i < chunk.imports.length; i++) {\n const importedChunk = chunksByFileName.get(chunk.imports[i]!)\n if (importedChunk) {\n chunkStack.push(importedChunk)\n modeStack.push(mode)\n }\n }\n\n for (let i = 0; i < chunk.dynamicImports.length; i++) {\n const dynamicImportedChunk = chunksByFileName.get(\n chunk.dynamicImports[i]!,\n )\n if (dynamicImportedChunk) {\n chunkStack.push(dynamicImportedChunk)\n modeStack.push(\n (mode & NON_ROUTE_DYNAMIC_MODE) !== 0 ||\n !routeEntryChunks.has(dynamicImportedChunk)\n ? NON_ROUTE_DYNAMIC_MODE\n : ROUTER_MANAGED_MODE,\n )\n }\n }\n }\n\n for (const cssFile of routerManagedCssFiles) {\n if (nonRouteDynamicCssFiles.has(cssFile)) {\n hashedCssFiles.add(cssFile)\n }\n }\n\n return hashedCssFiles\n}\n\nexport function createManifestAssetResolvers(options: {\n basePath: string\n hashedCssFiles?: Set<string>\n}): ManifestAssetResolvers {\n const assetPathByFileName = new Map<string, string>()\n const stylesheetAssetByFileName = new Map<string, RouterManagedTag>()\n const preloadsByChunk = new Map<Rollup.OutputChunk, Array<string>>()\n\n const getAssetPath = (fileName: string) => {\n const cachedPath = assetPathByFileName.get(fileName)\n if (cachedPath) {\n return cachedPath\n }\n\n const assetPath = joinURL(options.basePath, fileName)\n assetPathByFileName.set(fileName, assetPath)\n return assetPath\n }\n\n const getStylesheetAsset = (cssFile: string) => {\n const cachedAsset = stylesheetAssetByFileName.get(cssFile)\n if (cachedAsset) {\n return cachedAsset\n }\n\n const href = getAssetPath(cssFile)\n const asset = {\n tag: 'link',\n attrs: {\n rel: 'stylesheet',\n href: options.hashedCssFiles?.has(cssFile) ? `${href}#` : href,\n type: 'text/css',\n },\n } satisfies RouterManagedTag\n\n stylesheetAssetByFileName.set(cssFile, asset)\n return asset\n }\n\n const getChunkPreloads = (chunk: Rollup.OutputChunk) => {\n const cachedPreloads = preloadsByChunk.get(chunk)\n if (cachedPreloads) {\n return cachedPreloads\n }\n\n const preloads = [getAssetPath(chunk.fileName)]\n\n for (let i = 0; i < chunk.imports.length; i++) {\n preloads.push(getAssetPath(chunk.imports[i]!))\n }\n\n preloadsByChunk.set(chunk, preloads)\n return preloads\n }\n\n return {\n getAssetPath,\n getChunkPreloads,\n getStylesheetAsset,\n }\n}\n\nexport function createChunkCssAssetCollector(options: {\n chunksByFileName: Map<string, Rollup.OutputChunk>\n getStylesheetAsset: (cssFile: string) => RouterManagedTag\n}) {\n const assetsByChunk = new Map<Rollup.OutputChunk, Array<RouterManagedTag>>()\n const stateByChunk = new Map<Rollup.OutputChunk, number>()\n\n const getChunkCssAssets = (\n chunk: Rollup.OutputChunk,\n ): Array<RouterManagedTag> => {\n const cachedAssets = assetsByChunk.get(chunk)\n if (cachedAssets) {\n return cachedAssets\n }\n\n if (stateByChunk.get(chunk) === VISITING_CHUNK) {\n return []\n }\n stateByChunk.set(chunk, VISITING_CHUNK)\n\n const assets: Array<RouterManagedTag> = []\n\n for (const cssFile of chunk.viteMetadata?.importedCss ?? []) {\n assets.push(options.getStylesheetAsset(cssFile))\n }\n\n for (let i = 0; i < chunk.imports.length; i++) {\n const importedChunk = options.chunksByFileName.get(chunk.imports[i]!)\n if (!importedChunk) {\n continue\n }\n\n const importedAssets = getChunkCssAssets(importedChunk)\n for (let j = 0; j < importedAssets.length; j++) {\n assets.push(importedAssets[j]!)\n }\n }\n\n stateByChunk.delete(chunk)\n assetsByChunk.set(chunk, assets)\n return assets\n }\n\n return { getChunkCssAssets }\n}\n\nexport function buildRouteManifestRoutes(options: {\n routeTreeRoutes: RouteTreeRoutes\n routeChunksByFilePath: Map<string, Array<Rollup.OutputChunk>>\n chunksByFileName: Map<string, Rollup.OutputChunk>\n entryChunk: Rollup.OutputChunk\n assetResolvers: ManifestAssetResolvers\n}) {\n const routes: Record<string, RouteTreeRoute> = {}\n const getChunkCssAssets = createChunkCssAssetCollector({\n chunksByFileName: options.chunksByFileName,\n getStylesheetAsset: options.assetResolvers.getStylesheetAsset,\n }).getChunkCssAssets\n\n for (const [routeId, route] of Object.entries(options.routeTreeRoutes)) {\n if (!route.filePath) {\n if (routeId === rootRouteId) {\n routes[routeId] = route\n continue\n }\n\n throw new Error(`expected filePath to be set for ${routeId}`)\n }\n\n const chunks = options.routeChunksByFilePath.get(route.filePath)\n if (!chunks) {\n routes[routeId] = route\n continue\n }\n\n const existing = routes[routeId]\n const targetRoute = (routes[routeId] = existing ? existing : { ...route })\n\n for (const chunk of chunks) {\n mergeRouteChunkData({\n route: targetRoute,\n chunk,\n getChunkCssAssets,\n getChunkPreloads: options.assetResolvers.getChunkPreloads,\n })\n }\n }\n\n const rootRoute = (routes[rootRouteId] = routes[rootRouteId] || {})\n mergeRouteChunkData({\n route: rootRoute,\n chunk: options.entryChunk,\n getChunkCssAssets,\n getChunkPreloads: options.assetResolvers.getChunkPreloads,\n })\n\n return routes\n}\n\nexport function dedupeNestedRoutePreloads(\n route: DedupePreloadRoute,\n routesById: Record<string, DedupePreloadRoute>,\n seenPreloads = new Set<string>(),\n) {\n let routePreloads = route.preloads\n\n if (routePreloads && routePreloads.length > 0) {\n let dedupedPreloads: Array<ManifestAssetLink> | undefined\n\n for (let i = 0; i < routePreloads.length; i++) {\n const preload = routePreloads[i]!\n const preloadHref = resolveManifestAssetLink(preload).href\n\n if (seenPreloads.has(preloadHref)) {\n if (dedupedPreloads === undefined) {\n dedupedPreloads = routePreloads.slice(0, i)\n }\n continue\n }\n\n seenPreloads.add(preloadHref)\n\n if (dedupedPreloads) {\n dedupedPreloads.push(preload)\n }\n }\n\n if (dedupedPreloads) {\n routePreloads = dedupedPreloads\n route.preloads = dedupedPreloads\n }\n }\n\n if (route.children) {\n for (const childRouteId of route.children) {\n dedupeNestedRoutePreloads(\n routesById[childRouteId]!,\n routesById,\n seenPreloads,\n )\n }\n }\n\n if (routePreloads) {\n for (let i = routePreloads.length - 1; i >= 0; i--) {\n seenPreloads.delete(resolveManifestAssetLink(routePreloads[i]!).href)\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"manifestBuilder.js","names":[],"sources":["../../../src/start-manifest-plugin/manifestBuilder.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/prefer-for-of */\nimport { joinURL } from 'ufo'\nimport { resolveManifestAssetLink, rootRouteId } from '@tanstack/router-core'\nimport { tsrSplit } from '@tanstack/router-plugin'\nimport type { ManifestAssetLink, RouterManagedTag } from '@tanstack/router-core'\nimport type { Rollup } from 'vite'\n\nconst ROUTER_MANAGED_MODE = 1\nconst NON_ROUTE_DYNAMIC_MODE = 2\nconst VISITING_CHUNK = 1\n\ntype RouteTreeRoute = {\n filePath?: string\n preloads?: Array<string>\n assets?: Array<RouterManagedTag>\n children?: Array<string>\n}\n\ntype RouteTreeRoutes = Record<string, RouteTreeRoute>\n\ninterface ScannedClientChunks {\n entryChunk: Rollup.OutputChunk\n chunksByFileName: Map<string, Rollup.OutputChunk>\n routeChunksByFilePath: Map<string, Array<Rollup.OutputChunk>>\n routeEntryChunks: Set<Rollup.OutputChunk>\n}\n\ninterface ManifestAssetResolvers {\n getAssetPath: (fileName: string) => string\n getChunkPreloads: (chunk: Rollup.OutputChunk) => Array<string>\n getStylesheetAsset: (cssFile: string) => RouterManagedTag\n}\n\ntype DedupeRoute = {\n preloads?: Array<ManifestAssetLink>\n assets?: Array<RouterManagedTag>\n children?: Array<string>\n}\n\nexport function appendUniqueStrings(\n target: Array<string> | undefined,\n source: Array<string>,\n) {\n // Similar to Set.prototype.union, but for ordered arrays.\n // It preserves first-seen order and returns the original target array when\n // source contributes no new values, which avoids extra allocations.\n if (source.length === 0) {\n return target\n }\n\n if (!target || target.length === 0) {\n return source\n }\n\n const seen = new Set(target)\n let result: Array<string> | undefined\n\n for (const value of source) {\n if (seen.has(value)) {\n continue\n }\n\n seen.add(value)\n if (!result) {\n result = target.slice()\n }\n result.push(value)\n }\n\n return result ?? target\n}\n\nexport function appendUniqueAssets(\n target: Array<RouterManagedTag> | undefined,\n source: Array<RouterManagedTag>,\n) {\n // Same semantics as appendUniqueStrings, but uniqueness is based on the\n // serialized asset identity instead of object reference.\n if (source.length === 0) {\n return target\n }\n\n if (!target || target.length === 0) {\n return source\n }\n\n const seen = new Set(target.map(getAssetIdentity))\n let result: Array<RouterManagedTag> | undefined\n\n for (const asset of source) {\n const identity = getAssetIdentity(asset)\n if (seen.has(identity)) {\n continue\n }\n\n seen.add(identity)\n if (!result) {\n result = target.slice()\n }\n result.push(asset)\n }\n\n return result ?? target\n}\n\nfunction getAssetIdentity(asset: RouterManagedTag) {\n if (asset.tag === 'link' || asset.tag === 'script') {\n const attrs = asset.attrs ?? {}\n return [\n asset.tag,\n 'href' in attrs ? String(attrs.href) : '',\n 'src' in attrs ? String(attrs.src) : '',\n 'rel' in attrs ? String(attrs.rel) : '',\n 'type' in attrs ? String(attrs.type) : '',\n asset.children ?? '',\n ].join('|')\n }\n\n return JSON.stringify(asset)\n}\n\nfunction mergeRouteChunkData(options: {\n route: RouteTreeRoute\n chunk: Rollup.OutputChunk\n getChunkCssAssets: (chunk: Rollup.OutputChunk) => Array<RouterManagedTag>\n getChunkPreloads: (chunk: Rollup.OutputChunk) => Array<string>\n}) {\n const chunkAssets = options.getChunkCssAssets(options.chunk)\n const chunkPreloads = options.getChunkPreloads(options.chunk)\n\n options.route.assets = appendUniqueAssets(options.route.assets, chunkAssets)\n options.route.preloads = appendUniqueStrings(\n options.route.preloads,\n chunkPreloads,\n )\n}\n\nexport function buildStartManifest(options: {\n clientBundle: Rollup.OutputBundle\n routeTreeRoutes: RouteTreeRoutes\n basePath: string\n}) {\n const scannedChunks = scanClientChunks(options.clientBundle)\n const hashedCssFiles = collectDynamicImportCss(\n scannedChunks.routeEntryChunks,\n scannedChunks.chunksByFileName,\n scannedChunks.entryChunk,\n )\n const assetResolvers = createManifestAssetResolvers({\n basePath: options.basePath,\n hashedCssFiles,\n })\n\n const routes = buildRouteManifestRoutes({\n routeTreeRoutes: options.routeTreeRoutes,\n routeChunksByFilePath: scannedChunks.routeChunksByFilePath,\n chunksByFileName: scannedChunks.chunksByFileName,\n entryChunk: scannedChunks.entryChunk,\n assetResolvers,\n })\n\n dedupeNestedRouteManifestEntries(rootRouteId, routes[rootRouteId]!, routes)\n\n // Prune routes with no assets or preloads from the manifest\n for (const routeId of Object.keys(routes)) {\n const route = routes[routeId]!\n const hasAssets = route.assets && route.assets.length > 0\n const hasPreloads = route.preloads && route.preloads.length > 0\n if (!hasAssets && !hasPreloads) {\n delete routes[routeId]\n }\n }\n\n return {\n routes,\n clientEntry: assetResolvers.getAssetPath(scannedChunks.entryChunk.fileName),\n }\n}\n\nexport function scanClientChunks(\n clientBundle: Rollup.OutputBundle,\n): ScannedClientChunks {\n let entryChunk: Rollup.OutputChunk | undefined\n const chunksByFileName = new Map<string, Rollup.OutputChunk>()\n const routeChunksByFilePath = new Map<string, Array<Rollup.OutputChunk>>()\n const routeEntryChunks = new Set<Rollup.OutputChunk>()\n\n for (const fileName in clientBundle) {\n const bundleEntry = clientBundle[fileName]!\n if (bundleEntry.type !== 'chunk') {\n continue\n }\n\n chunksByFileName.set(bundleEntry.fileName, bundleEntry)\n\n if (bundleEntry.isEntry) {\n if (entryChunk) {\n throw new Error(\n `multiple entries detected: ${entryChunk.fileName} ${bundleEntry.fileName}`,\n )\n }\n entryChunk = bundleEntry\n }\n\n const routeFilePaths = getRouteFilePathsFromModuleIds(bundleEntry.moduleIds)\n if (routeFilePaths.length === 0) {\n continue\n }\n\n routeEntryChunks.add(bundleEntry)\n\n for (let i = 0; i < routeFilePaths.length; i++) {\n const routeFilePath = routeFilePaths[i]!\n let chunks = routeChunksByFilePath.get(routeFilePath)\n if (chunks === undefined) {\n chunks = []\n routeChunksByFilePath.set(routeFilePath, chunks)\n }\n chunks.push(bundleEntry)\n }\n }\n\n if (!entryChunk) {\n throw new Error('No entry file found')\n }\n\n return {\n entryChunk,\n chunksByFileName,\n routeChunksByFilePath,\n routeEntryChunks,\n }\n}\n\nexport function getRouteFilePathsFromModuleIds(moduleIds: Array<string>) {\n let routeFilePaths: Array<string> | undefined\n let seenRouteFilePaths: Set<string> | undefined\n\n for (const moduleId of moduleIds) {\n const queryIndex = moduleId.indexOf('?')\n\n if (queryIndex < 0) {\n continue\n }\n\n const query = moduleId.slice(queryIndex + 1)\n\n // Fast check before allocating URLSearchParams\n if (!query.includes(tsrSplit)) {\n continue\n }\n\n if (!new URLSearchParams(query).has(tsrSplit)) {\n continue\n }\n\n const routeFilePath = moduleId.slice(0, queryIndex)\n\n if (seenRouteFilePaths?.has(routeFilePath)) {\n continue\n }\n\n if (routeFilePaths === undefined) {\n routeFilePaths = []\n seenRouteFilePaths = new Set<string>()\n }\n\n routeFilePaths.push(routeFilePath)\n seenRouteFilePaths!.add(routeFilePath)\n }\n\n return routeFilePaths ?? []\n}\n\nexport function collectDynamicImportCss(\n routeEntryChunks: Set<Rollup.OutputChunk>,\n chunksByFileName: Map<string, Rollup.OutputChunk>,\n entryChunk?: Rollup.OutputChunk,\n) {\n const routerManagedCssFiles = new Set<string>()\n const nonRouteDynamicCssFiles = new Set<string>()\n const hashedCssFiles = new Set<string>()\n const visitedByChunk = new Map<Rollup.OutputChunk, number>()\n const chunkStack: Array<Rollup.OutputChunk> = []\n const modeStack: Array<number> = []\n\n for (const routeEntryChunk of routeEntryChunks) {\n chunkStack.push(routeEntryChunk)\n modeStack.push(ROUTER_MANAGED_MODE)\n }\n\n if (entryChunk) {\n chunkStack.push(entryChunk)\n modeStack.push(ROUTER_MANAGED_MODE)\n }\n\n while (chunkStack.length > 0) {\n const chunk = chunkStack.pop()!\n const mode = modeStack.pop()!\n const previousMode = visitedByChunk.get(chunk) ?? 0\n\n if ((previousMode & mode) === mode) {\n continue\n }\n\n visitedByChunk.set(chunk, previousMode | mode)\n\n if ((mode & ROUTER_MANAGED_MODE) !== 0) {\n for (const cssFile of chunk.viteMetadata?.importedCss ?? []) {\n routerManagedCssFiles.add(cssFile)\n }\n }\n\n if ((mode & NON_ROUTE_DYNAMIC_MODE) !== 0) {\n for (const cssFile of chunk.viteMetadata?.importedCss ?? []) {\n nonRouteDynamicCssFiles.add(cssFile)\n }\n }\n\n for (let i = 0; i < chunk.imports.length; i++) {\n const importedChunk = chunksByFileName.get(chunk.imports[i]!)\n if (importedChunk) {\n chunkStack.push(importedChunk)\n modeStack.push(mode)\n }\n }\n\n for (let i = 0; i < chunk.dynamicImports.length; i++) {\n const dynamicImportedChunk = chunksByFileName.get(\n chunk.dynamicImports[i]!,\n )\n if (dynamicImportedChunk) {\n chunkStack.push(dynamicImportedChunk)\n modeStack.push(\n (mode & NON_ROUTE_DYNAMIC_MODE) !== 0 ||\n !routeEntryChunks.has(dynamicImportedChunk)\n ? NON_ROUTE_DYNAMIC_MODE\n : ROUTER_MANAGED_MODE,\n )\n }\n }\n }\n\n for (const cssFile of routerManagedCssFiles) {\n if (nonRouteDynamicCssFiles.has(cssFile)) {\n hashedCssFiles.add(cssFile)\n }\n }\n\n return hashedCssFiles\n}\n\nexport function createManifestAssetResolvers(options: {\n basePath: string\n hashedCssFiles?: Set<string>\n}): ManifestAssetResolvers {\n const assetPathByFileName = new Map<string, string>()\n const stylesheetAssetByFileName = new Map<string, RouterManagedTag>()\n const preloadsByChunk = new Map<Rollup.OutputChunk, Array<string>>()\n\n const getAssetPath = (fileName: string) => {\n const cachedPath = assetPathByFileName.get(fileName)\n if (cachedPath) {\n return cachedPath\n }\n\n const assetPath = joinURL(options.basePath, fileName)\n assetPathByFileName.set(fileName, assetPath)\n return assetPath\n }\n\n const getStylesheetAsset = (cssFile: string) => {\n const cachedAsset = stylesheetAssetByFileName.get(cssFile)\n if (cachedAsset) {\n return cachedAsset\n }\n\n const href = getAssetPath(cssFile)\n const asset = {\n tag: 'link',\n attrs: {\n rel: 'stylesheet',\n href: options.hashedCssFiles?.has(cssFile) ? `${href}#` : href,\n type: 'text/css',\n },\n } satisfies RouterManagedTag\n\n stylesheetAssetByFileName.set(cssFile, asset)\n return asset\n }\n\n const getChunkPreloads = (chunk: Rollup.OutputChunk) => {\n const cachedPreloads = preloadsByChunk.get(chunk)\n if (cachedPreloads) {\n return cachedPreloads\n }\n\n const preloads = [getAssetPath(chunk.fileName)]\n\n for (let i = 0; i < chunk.imports.length; i++) {\n preloads.push(getAssetPath(chunk.imports[i]!))\n }\n\n preloadsByChunk.set(chunk, preloads)\n return preloads\n }\n\n return {\n getAssetPath,\n getChunkPreloads,\n getStylesheetAsset,\n }\n}\n\nexport function createChunkCssAssetCollector(options: {\n chunksByFileName: Map<string, Rollup.OutputChunk>\n getStylesheetAsset: (cssFile: string) => RouterManagedTag\n}) {\n const assetsByChunk = new Map<Rollup.OutputChunk, Array<RouterManagedTag>>()\n const stateByChunk = new Map<Rollup.OutputChunk, number>()\n\n const appendAsset = (\n assets: Array<RouterManagedTag>,\n seenAssets: Set<string>,\n asset: RouterManagedTag,\n ) => {\n const identity = getAssetIdentity(asset)\n if (seenAssets.has(identity)) {\n return\n }\n\n seenAssets.add(identity)\n assets.push(asset)\n }\n\n const getChunkCssAssets = (\n chunk: Rollup.OutputChunk,\n ): Array<RouterManagedTag> => {\n const cachedAssets = assetsByChunk.get(chunk)\n if (cachedAssets) {\n return cachedAssets\n }\n\n if (stateByChunk.get(chunk) === VISITING_CHUNK) {\n return []\n }\n stateByChunk.set(chunk, VISITING_CHUNK)\n\n const assets: Array<RouterManagedTag> = []\n const seenAssets = new Set<string>()\n\n for (const cssFile of chunk.viteMetadata?.importedCss ?? []) {\n appendAsset(assets, seenAssets, options.getStylesheetAsset(cssFile))\n }\n\n for (let i = 0; i < chunk.imports.length; i++) {\n const importedChunk = options.chunksByFileName.get(chunk.imports[i]!)\n if (!importedChunk) {\n continue\n }\n\n const importedAssets = getChunkCssAssets(importedChunk)\n for (let j = 0; j < importedAssets.length; j++) {\n appendAsset(assets, seenAssets, importedAssets[j]!)\n }\n }\n\n stateByChunk.delete(chunk)\n assetsByChunk.set(chunk, assets)\n return assets\n }\n\n return { getChunkCssAssets }\n}\n\nexport function buildRouteManifestRoutes(options: {\n routeTreeRoutes: RouteTreeRoutes\n routeChunksByFilePath: Map<string, Array<Rollup.OutputChunk>>\n chunksByFileName: Map<string, Rollup.OutputChunk>\n entryChunk: Rollup.OutputChunk\n assetResolvers: ManifestAssetResolvers\n}) {\n const routes: Record<string, RouteTreeRoute> = {}\n const getChunkCssAssets = createChunkCssAssetCollector({\n chunksByFileName: options.chunksByFileName,\n getStylesheetAsset: options.assetResolvers.getStylesheetAsset,\n }).getChunkCssAssets\n\n for (const [routeId, route] of Object.entries(options.routeTreeRoutes)) {\n if (!route.filePath) {\n if (routeId === rootRouteId) {\n routes[routeId] = route\n continue\n }\n\n throw new Error(`expected filePath to be set for ${routeId}`)\n }\n\n const chunks = options.routeChunksByFilePath.get(route.filePath)\n if (!chunks) {\n routes[routeId] = route\n continue\n }\n\n const existing = routes[routeId]\n const targetRoute = (routes[routeId] = existing ? existing : { ...route })\n\n for (const chunk of chunks) {\n mergeRouteChunkData({\n route: targetRoute,\n chunk,\n getChunkCssAssets,\n getChunkPreloads: options.assetResolvers.getChunkPreloads,\n })\n }\n }\n\n const rootRoute = (routes[rootRouteId] = routes[rootRouteId] || {})\n mergeRouteChunkData({\n route: rootRoute,\n chunk: options.entryChunk,\n getChunkCssAssets,\n getChunkPreloads: options.assetResolvers.getChunkPreloads,\n })\n\n return routes\n}\n\nfunction dedupeNestedRouteManifestEntries(\n routeId: string,\n route: DedupeRoute,\n routesById: Record<string, DedupeRoute>,\n seenPreloads = new Set<string>(),\n seenAssets = new Set<string>(),\n) {\n let routePreloads = route.preloads\n let routeAssets = route.assets\n\n if (routePreloads && routePreloads.length > 0) {\n let dedupedPreloads: Array<ManifestAssetLink> | undefined\n\n for (let i = 0; i < routePreloads.length; i++) {\n const preload = routePreloads[i]!\n const preloadHref = resolveManifestAssetLink(preload).href\n\n if (seenPreloads.has(preloadHref)) {\n if (dedupedPreloads === undefined) {\n dedupedPreloads = routePreloads.slice(0, i)\n }\n continue\n }\n\n seenPreloads.add(preloadHref)\n\n if (dedupedPreloads) {\n dedupedPreloads.push(preload)\n }\n }\n\n if (dedupedPreloads) {\n routePreloads = dedupedPreloads\n route.preloads = dedupedPreloads\n }\n }\n\n if (routeAssets && routeAssets.length > 0) {\n let dedupedAssets: Array<RouterManagedTag> | undefined\n\n for (let i = 0; i < routeAssets.length; i++) {\n const asset = routeAssets[i]!\n const identity = getAssetIdentity(asset)\n\n if (seenAssets.has(identity)) {\n if (dedupedAssets === undefined) {\n dedupedAssets = routeAssets.slice(0, i)\n }\n continue\n }\n\n seenAssets.add(identity)\n\n if (dedupedAssets) {\n dedupedAssets.push(asset)\n }\n }\n\n if (dedupedAssets) {\n routeAssets = dedupedAssets\n route.assets = dedupedAssets\n }\n }\n\n if (route.children) {\n for (const childRouteId of route.children) {\n const childRoute = routesById[childRouteId]\n\n if (!childRoute) {\n throw new Error(\n `Route tree references child route ${childRouteId} from ${routeId}, but no route entry was found`,\n )\n }\n\n dedupeNestedRouteManifestEntries(\n childRouteId,\n childRoute,\n routesById,\n seenPreloads,\n seenAssets,\n )\n }\n }\n\n if (routePreloads) {\n for (let i = routePreloads.length - 1; i >= 0; i--) {\n seenPreloads.delete(resolveManifestAssetLink(routePreloads[i]!).href)\n }\n }\n\n if (routeAssets) {\n for (let i = routeAssets.length - 1; i >= 0; i--) {\n seenAssets.delete(getAssetIdentity(routeAssets[i]!))\n }\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/start-plugin-core",
3
- "version": "1.167.7",
3
+ "version": "1.167.9",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -60,18 +60,19 @@
60
60
  "vitefu": "^1.1.1",
61
61
  "xmlbuilder2": "^4.0.3",
62
62
  "zod": "^3.24.2",
63
- "@tanstack/router-core": "1.168.2",
64
- "@tanstack/router-generator": "1.166.16",
65
- "@tanstack/router-plugin": "1.167.3",
63
+ "@tanstack/router-core": "1.168.3",
64
+ "@tanstack/router-generator": "1.166.17",
65
+ "@tanstack/router-plugin": "1.167.4",
66
66
  "@tanstack/router-utils": "1.161.6",
67
- "@tanstack/start-client-core": "1.167.2",
68
- "@tanstack/start-server-core": "1.167.2"
67
+ "@tanstack/start-client-core": "1.167.3",
68
+ "@tanstack/start-server-core": "1.167.3"
69
69
  },
70
70
  "devDependencies": {
71
71
  "@types/babel__code-frame": "^7.0.6",
72
72
  "@types/babel__core": "^7.20.5",
73
73
  "@types/picomatch": "^4.0.2",
74
- "vite": "*"
74
+ "vite": "*",
75
+ "@types/node": ">=20"
75
76
  },
76
77
  "peerDependencies": {
77
78
  "vite": ">=7.0.0"
@@ -83,12 +84,12 @@
83
84
  "test:unit": "vitest",
84
85
  "test:eslint": "eslint ./src",
85
86
  "test:types": "pnpm run \"/^test:types:ts[0-9]{2}$/\"",
86
- "test:types:ts54": "node ../../node_modules/typescript54/lib/tsc.js",
87
87
  "test:types:ts55": "node ../../node_modules/typescript55/lib/tsc.js",
88
88
  "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js",
89
89
  "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js",
90
90
  "test:types:ts58": "node ../../node_modules/typescript58/lib/tsc.js",
91
- "test:types:ts59": "tsc",
91
+ "test:types:ts59": "node ../../node_modules/typescript59/lib/tsc.js",
92
+ "test:types:ts60": "tsc",
92
93
  "test:build": "publint --strict && attw --ignore-rules no-resolution --pack .",
93
94
  "build": "vite build"
94
95
  }
@@ -31,8 +31,9 @@ interface ManifestAssetResolvers {
31
31
  getStylesheetAsset: (cssFile: string) => RouterManagedTag
32
32
  }
33
33
 
34
- type DedupePreloadRoute = {
34
+ type DedupeRoute = {
35
35
  preloads?: Array<ManifestAssetLink>
36
+ assets?: Array<RouterManagedTag>
36
37
  children?: Array<string>
37
38
  }
38
39
 
@@ -158,7 +159,7 @@ export function buildStartManifest(options: {
158
159
  assetResolvers,
159
160
  })
160
161
 
161
- dedupeNestedRoutePreloads(routes[rootRouteId]!, routes)
162
+ dedupeNestedRouteManifestEntries(rootRouteId, routes[rootRouteId]!, routes)
162
163
 
163
164
  // Prune routes with no assets or preloads from the manifest
164
165
  for (const routeId of Object.keys(routes)) {
@@ -418,6 +419,20 @@ export function createChunkCssAssetCollector(options: {
418
419
  const assetsByChunk = new Map<Rollup.OutputChunk, Array<RouterManagedTag>>()
419
420
  const stateByChunk = new Map<Rollup.OutputChunk, number>()
420
421
 
422
+ const appendAsset = (
423
+ assets: Array<RouterManagedTag>,
424
+ seenAssets: Set<string>,
425
+ asset: RouterManagedTag,
426
+ ) => {
427
+ const identity = getAssetIdentity(asset)
428
+ if (seenAssets.has(identity)) {
429
+ return
430
+ }
431
+
432
+ seenAssets.add(identity)
433
+ assets.push(asset)
434
+ }
435
+
421
436
  const getChunkCssAssets = (
422
437
  chunk: Rollup.OutputChunk,
423
438
  ): Array<RouterManagedTag> => {
@@ -432,9 +447,10 @@ export function createChunkCssAssetCollector(options: {
432
447
  stateByChunk.set(chunk, VISITING_CHUNK)
433
448
 
434
449
  const assets: Array<RouterManagedTag> = []
450
+ const seenAssets = new Set<string>()
435
451
 
436
452
  for (const cssFile of chunk.viteMetadata?.importedCss ?? []) {
437
- assets.push(options.getStylesheetAsset(cssFile))
453
+ appendAsset(assets, seenAssets, options.getStylesheetAsset(cssFile))
438
454
  }
439
455
 
440
456
  for (let i = 0; i < chunk.imports.length; i++) {
@@ -445,7 +461,7 @@ export function createChunkCssAssetCollector(options: {
445
461
 
446
462
  const importedAssets = getChunkCssAssets(importedChunk)
447
463
  for (let j = 0; j < importedAssets.length; j++) {
448
- assets.push(importedAssets[j]!)
464
+ appendAsset(assets, seenAssets, importedAssets[j]!)
449
465
  }
450
466
  }
451
467
 
@@ -510,12 +526,15 @@ export function buildRouteManifestRoutes(options: {
510
526
  return routes
511
527
  }
512
528
 
513
- export function dedupeNestedRoutePreloads(
514
- route: DedupePreloadRoute,
515
- routesById: Record<string, DedupePreloadRoute>,
529
+ function dedupeNestedRouteManifestEntries(
530
+ routeId: string,
531
+ route: DedupeRoute,
532
+ routesById: Record<string, DedupeRoute>,
516
533
  seenPreloads = new Set<string>(),
534
+ seenAssets = new Set<string>(),
517
535
  ) {
518
536
  let routePreloads = route.preloads
537
+ let routeAssets = route.assets
519
538
 
520
539
  if (routePreloads && routePreloads.length > 0) {
521
540
  let dedupedPreloads: Array<ManifestAssetLink> | undefined
@@ -544,12 +563,49 @@ export function dedupeNestedRoutePreloads(
544
563
  }
545
564
  }
546
565
 
566
+ if (routeAssets && routeAssets.length > 0) {
567
+ let dedupedAssets: Array<RouterManagedTag> | undefined
568
+
569
+ for (let i = 0; i < routeAssets.length; i++) {
570
+ const asset = routeAssets[i]!
571
+ const identity = getAssetIdentity(asset)
572
+
573
+ if (seenAssets.has(identity)) {
574
+ if (dedupedAssets === undefined) {
575
+ dedupedAssets = routeAssets.slice(0, i)
576
+ }
577
+ continue
578
+ }
579
+
580
+ seenAssets.add(identity)
581
+
582
+ if (dedupedAssets) {
583
+ dedupedAssets.push(asset)
584
+ }
585
+ }
586
+
587
+ if (dedupedAssets) {
588
+ routeAssets = dedupedAssets
589
+ route.assets = dedupedAssets
590
+ }
591
+ }
592
+
547
593
  if (route.children) {
548
594
  for (const childRouteId of route.children) {
549
- dedupeNestedRoutePreloads(
550
- routesById[childRouteId]!,
595
+ const childRoute = routesById[childRouteId]
596
+
597
+ if (!childRoute) {
598
+ throw new Error(
599
+ `Route tree references child route ${childRouteId} from ${routeId}, but no route entry was found`,
600
+ )
601
+ }
602
+
603
+ dedupeNestedRouteManifestEntries(
604
+ childRouteId,
605
+ childRoute,
551
606
  routesById,
552
607
  seenPreloads,
608
+ seenAssets,
553
609
  )
554
610
  }
555
611
  }
@@ -559,4 +615,10 @@ export function dedupeNestedRoutePreloads(
559
615
  seenPreloads.delete(resolveManifestAssetLink(routePreloads[i]!).href)
560
616
  }
561
617
  }
618
+
619
+ if (routeAssets) {
620
+ for (let i = routeAssets.length - 1; i >= 0; i--) {
621
+ seenAssets.delete(getAssetIdentity(routeAssets[i]!))
622
+ }
623
+ }
562
624
  }