@tanstack/start-plugin-core 1.136.8 → 1.136.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.
@@ -71,7 +71,7 @@ function startManifestPlugin(opts) {
71
71
  clientEntry: '${joinURL(resolvedStartConfig.viteAppBase, "@id", ENTRY_POINTS.client)}',
72
72
  })`;
73
73
  }
74
- const routeTreeRoutes = globalThis.TSS_ROUTES_MANIFEST.routes;
74
+ const routeTreeRoutes = globalThis.TSS_ROUTES_MANIFEST;
75
75
  const cssPerChunkCache = /* @__PURE__ */ new Map();
76
76
  let entryFile;
77
77
  const clientBundle = opts.getClientBundle();
@@ -118,6 +118,7 @@ function startManifestPlugin(opts) {
118
118
  }
119
119
  }
120
120
  }
121
+ const manifest = { routes: {} };
121
122
  Object.entries(routeTreeRoutes).forEach(([routeId, v]) => {
122
123
  if (!v.filePath) {
123
124
  throw new Error(`expected filePath to be set for ${routeId}`);
@@ -126,30 +127,36 @@ function startManifestPlugin(opts) {
126
127
  if (chunks) {
127
128
  chunks.forEach((chunk) => {
128
129
  const preloads = chunk.imports.map((d) => {
129
- const assetPath = joinURL(resolvedStartConfig.viteAppBase, d);
130
- return assetPath;
130
+ const preloadPath = joinURL(
131
+ resolvedStartConfig.viteAppBase,
132
+ d
133
+ );
134
+ return preloadPath;
131
135
  });
132
136
  preloads.unshift(
133
137
  joinURL(resolvedStartConfig.viteAppBase, chunk.fileName)
134
138
  );
135
- const cssAssetsList = getCSSRecursively(
139
+ const assets = getCSSRecursively(
136
140
  chunk,
137
141
  chunksByFileName,
138
142
  resolvedStartConfig.viteAppBase,
139
143
  cssPerChunkCache
140
144
  );
141
- routeTreeRoutes[routeId] = {
145
+ manifest.routes[routeId] = {
142
146
  ...v,
143
- assets: [...v.assets || [], ...cssAssetsList],
144
- preloads: [...v.preloads || [], ...preloads]
147
+ assets,
148
+ preloads
145
149
  };
146
150
  });
151
+ } else {
152
+ manifest.routes[routeId] = v;
147
153
  }
148
154
  });
149
155
  if (!entryFile) {
150
156
  throw new Error("No entry file found");
151
157
  }
152
- routeTreeRoutes[rootRouteId].preloads = [
158
+ manifest.routes[rootRouteId] = manifest.routes[rootRouteId] || {};
159
+ manifest.routes[rootRouteId].preloads = [
153
160
  joinURL(resolvedStartConfig.viteAppBase, entryFile.fileName),
154
161
  ...entryFile.imports.map(
155
162
  (d) => joinURL(resolvedStartConfig.viteAppBase, d)
@@ -161,8 +168,8 @@ function startManifestPlugin(opts) {
161
168
  resolvedStartConfig.viteAppBase,
162
169
  cssPerChunkCache
163
170
  );
164
- routeTreeRoutes[rootRouteId].assets = [
165
- ...routeTreeRoutes[rootRouteId].assets || [],
171
+ manifest.routes[rootRouteId].assets = [
172
+ ...manifest.routes[rootRouteId].assets || [],
166
173
  ...entryCssAssetsList
167
174
  ];
168
175
  const recurseRoute = (route, seenPreloads = {}) => {
@@ -175,14 +182,14 @@ function startManifestPlugin(opts) {
175
182
  });
176
183
  if (route.children) {
177
184
  route.children.forEach((child) => {
178
- const childRoute = routeTreeRoutes[child];
185
+ const childRoute = manifest.routes[child];
179
186
  recurseRoute(childRoute, { ...seenPreloads });
180
187
  });
181
188
  }
182
189
  };
183
- recurseRoute(routeTreeRoutes[rootRouteId]);
184
- Object.keys(routeTreeRoutes).forEach((routeId) => {
185
- const route = routeTreeRoutes[routeId];
190
+ recurseRoute(manifest.routes[rootRouteId]);
191
+ Object.keys(manifest.routes).forEach((routeId) => {
192
+ const route = manifest.routes[routeId];
186
193
  const hasAssets = route.assets && route.assets.length > 0;
187
194
  const hasPreloads = route.preloads && route.preloads.length > 0;
188
195
  if (!hasAssets && !hasPreloads) {
@@ -190,7 +197,7 @@ function startManifestPlugin(opts) {
190
197
  }
191
198
  });
192
199
  const startManifest = {
193
- routes: routeTreeRoutes,
200
+ routes: manifest.routes,
194
201
  clientEntry: joinURL(
195
202
  resolvedStartConfig.viteAppBase,
196
203
  entryFile.fileName
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sources":["../../../src/start-manifest-plugin/plugin.ts"],"sourcesContent":["import { joinURL } from 'ufo'\nimport { rootRouteId } from '@tanstack/router-core'\nimport { VIRTUAL_MODULES } from '@tanstack/start-server-core'\nimport { tsrSplit } from '@tanstack/router-plugin'\nimport { resolveViteId } from '../utils'\nimport { ENTRY_POINTS } from '../constants'\nimport type { GetConfigFn } from '../plugin'\nimport type { PluginOption, Rollup } from 'vite'\nimport type { RouterManagedTag } from '@tanstack/router-core'\n\nconst getCSSRecursively = (\n chunk: Rollup.OutputChunk,\n chunksByFileName: Map<string, Rollup.OutputChunk>,\n basePath: string,\n cache: Map<Rollup.OutputChunk, Array<RouterManagedTag>>,\n visited = new Set<Rollup.OutputChunk>(),\n) => {\n if (visited.has(chunk)) {\n return []\n }\n visited.add(chunk)\n const cachedResult = cache.get(chunk)\n if (cachedResult) {\n return cachedResult\n }\n const result: Array<RouterManagedTag> = []\n\n // Get all css imports from the file\n for (const cssFile of chunk.viteMetadata?.importedCss ?? []) {\n result.push({\n tag: 'link',\n attrs: {\n rel: 'stylesheet',\n href: joinURL(basePath, cssFile),\n type: 'text/css',\n },\n })\n }\n\n // Recursively get CSS from imports\n for (const importedFileName of chunk.imports) {\n const importedChunk = chunksByFileName.get(importedFileName)\n if (importedChunk) {\n result.push(\n ...getCSSRecursively(\n importedChunk,\n chunksByFileName,\n basePath,\n cache,\n visited,\n ),\n )\n }\n }\n\n cache.set(chunk, result)\n return result\n}\n\nconst resolvedModuleId = resolveViteId(VIRTUAL_MODULES.startManifest)\nexport function startManifestPlugin(opts: {\n getClientBundle: () => Rollup.OutputBundle\n getConfig: GetConfigFn\n}): PluginOption {\n return {\n name: 'tanstack-start:start-manifest-plugin',\n enforce: 'pre',\n resolveId: {\n filter: { id: new RegExp(VIRTUAL_MODULES.startManifest) },\n handler(id) {\n if (id === VIRTUAL_MODULES.startManifest) {\n return resolvedModuleId\n }\n return undefined\n },\n },\n load: {\n filter: {\n id: new RegExp(resolvedModuleId),\n },\n handler(id) {\n const { resolvedStartConfig } = opts.getConfig()\n if (id === resolvedModuleId) {\n if (this.environment.config.consumer !== 'server') {\n // this will ultimately fail the build if the plugin is used outside the server environment\n // TODO: do we need special handling for `serve`?\n return `export default {}`\n }\n\n // If we're in development, return a dummy manifest\n if (this.environment.config.command === 'serve') {\n return `export const tsrStartManifest = () => ({\n routes: {},\n clientEntry: '${joinURL(resolvedStartConfig.viteAppBase, '@id', ENTRY_POINTS.client)}',\n })`\n }\n\n // This the manifest pulled from the generated route tree and later used by the Router.\n // i.e what's located in `src/routeTree.gen.ts`\n const routeTreeRoutes = globalThis.TSS_ROUTES_MANIFEST.routes\n\n const cssPerChunkCache = new Map<\n Rollup.OutputChunk,\n Array<RouterManagedTag>\n >()\n\n // This is where hydration will start, from when the SSR'd page reaches the browser.\n let entryFile: Rollup.OutputChunk | undefined\n\n const clientBundle = opts.getClientBundle()\n const chunksByFileName = new Map<string, Rollup.OutputChunk>()\n\n const routeChunks: Record<\n string /** fullPath of route file **/,\n Array<Rollup.OutputChunk>\n > = {}\n for (const bundleEntry of Object.values(clientBundle)) {\n if (bundleEntry.type === 'chunk') {\n chunksByFileName.set(bundleEntry.fileName, bundleEntry)\n if (bundleEntry.isEntry) {\n if (entryFile) {\n throw new Error(\n `multiple entries detected: ${entryFile.fileName} ${bundleEntry.fileName}`,\n )\n }\n entryFile = bundleEntry\n }\n const routePieces = bundleEntry.moduleIds.flatMap((m) => {\n const [id, query] = m.split('?')\n if (id === undefined) {\n throw new Error('expected id to be defined')\n }\n if (query === undefined) {\n return []\n }\n const searchParams = new URLSearchParams(query)\n const split = searchParams.get(tsrSplit)\n\n if (split !== null) {\n return {\n id,\n split,\n }\n }\n return []\n })\n if (routePieces.length > 0) {\n routePieces.forEach((r) => {\n let array = routeChunks[r.id]\n if (array === undefined) {\n array = []\n routeChunks[r.id] = array\n }\n array.push(bundleEntry)\n })\n }\n }\n }\n\n // Add preloads to the routes from the vite manifest\n Object.entries(routeTreeRoutes).forEach(([routeId, v]) => {\n if (!v.filePath) {\n throw new Error(`expected filePath to be set for ${routeId}`)\n }\n const chunks = routeChunks[v.filePath]\n if (chunks) {\n chunks.forEach((chunk) => {\n // Map the relevant imports to their route paths,\n // so that it can be imported in the browser.\n const preloads = chunk.imports.map((d) => {\n const assetPath = joinURL(resolvedStartConfig.viteAppBase, d)\n return assetPath\n })\n\n // Since this is the most important JS entry for the route,\n // it should be moved to the front of the preloads so that\n // it has the best chance of being loaded first.\n preloads.unshift(\n joinURL(resolvedStartConfig.viteAppBase, chunk.fileName),\n )\n\n const cssAssetsList = getCSSRecursively(\n chunk,\n chunksByFileName,\n resolvedStartConfig.viteAppBase,\n cssPerChunkCache,\n )\n\n routeTreeRoutes[routeId] = {\n ...v,\n assets: [...(v.assets || []), ...cssAssetsList],\n preloads: [...(v.preloads || []), ...preloads],\n }\n })\n }\n })\n\n if (!entryFile) {\n throw new Error('No entry file found')\n }\n routeTreeRoutes[rootRouteId]!.preloads = [\n joinURL(resolvedStartConfig.viteAppBase, entryFile.fileName),\n ...entryFile.imports.map((d) =>\n joinURL(resolvedStartConfig.viteAppBase, d),\n ),\n ]\n\n // Gather all the CSS files from the entry file in\n // the `css` key and add them to the root route\n const entryCssAssetsList = getCSSRecursively(\n entryFile,\n chunksByFileName,\n resolvedStartConfig.viteAppBase,\n cssPerChunkCache,\n )\n\n routeTreeRoutes[rootRouteId]!.assets = [\n ...(routeTreeRoutes[rootRouteId]!.assets || []),\n ...entryCssAssetsList,\n ]\n\n const recurseRoute = (\n route: {\n preloads?: Array<string>\n children?: Array<any>\n },\n seenPreloads = {} as Record<string, true>,\n ) => {\n route.preloads = route.preloads?.filter((preload) => {\n if (seenPreloads[preload]) {\n return false\n }\n seenPreloads[preload] = true\n return true\n })\n\n if (route.children) {\n route.children.forEach((child) => {\n const childRoute = routeTreeRoutes[child]!\n recurseRoute(childRoute, { ...seenPreloads })\n })\n }\n }\n\n recurseRoute(routeTreeRoutes[rootRouteId]!)\n\n // Filter out routes that have neither assets nor preloads\n Object.keys(routeTreeRoutes).forEach((routeId) => {\n const route = routeTreeRoutes[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 routeTreeRoutes[routeId]\n }\n })\n\n const startManifest = {\n routes: routeTreeRoutes,\n clientEntry: joinURL(\n resolvedStartConfig.viteAppBase,\n entryFile.fileName,\n ),\n }\n\n return `export const tsrStartManifest = () => (${JSON.stringify(startManifest)})`\n }\n\n return undefined\n },\n },\n }\n}\n"],"names":["id"],"mappings":"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"}
1
+ {"version":3,"file":"plugin.js","sources":["../../../src/start-manifest-plugin/plugin.ts"],"sourcesContent":["import { joinURL } from 'ufo'\nimport { rootRouteId } from '@tanstack/router-core'\nimport { VIRTUAL_MODULES } from '@tanstack/start-server-core'\nimport { tsrSplit } from '@tanstack/router-plugin'\nimport { resolveViteId } from '../utils'\nimport { ENTRY_POINTS } from '../constants'\nimport type { GetConfigFn } from '../plugin'\nimport type { PluginOption, Rollup } from 'vite'\nimport type { Manifest, RouterManagedTag } from '@tanstack/router-core'\n\nconst getCSSRecursively = (\n chunk: Rollup.OutputChunk,\n chunksByFileName: Map<string, Rollup.OutputChunk>,\n basePath: string,\n cache: Map<Rollup.OutputChunk, Array<RouterManagedTag>>,\n visited = new Set<Rollup.OutputChunk>(),\n) => {\n if (visited.has(chunk)) {\n return []\n }\n visited.add(chunk)\n const cachedResult = cache.get(chunk)\n if (cachedResult) {\n return cachedResult\n }\n const result: Array<RouterManagedTag> = []\n\n // Get all css imports from the file\n for (const cssFile of chunk.viteMetadata?.importedCss ?? []) {\n result.push({\n tag: 'link',\n attrs: {\n rel: 'stylesheet',\n href: joinURL(basePath, cssFile),\n type: 'text/css',\n },\n })\n }\n\n // Recursively get CSS from imports\n for (const importedFileName of chunk.imports) {\n const importedChunk = chunksByFileName.get(importedFileName)\n if (importedChunk) {\n result.push(\n ...getCSSRecursively(\n importedChunk,\n chunksByFileName,\n basePath,\n cache,\n visited,\n ),\n )\n }\n }\n\n cache.set(chunk, result)\n return result\n}\n\nconst resolvedModuleId = resolveViteId(VIRTUAL_MODULES.startManifest)\nexport function startManifestPlugin(opts: {\n getClientBundle: () => Rollup.OutputBundle\n getConfig: GetConfigFn\n}): PluginOption {\n return {\n name: 'tanstack-start:start-manifest-plugin',\n enforce: 'pre',\n resolveId: {\n filter: { id: new RegExp(VIRTUAL_MODULES.startManifest) },\n handler(id) {\n if (id === VIRTUAL_MODULES.startManifest) {\n return resolvedModuleId\n }\n return undefined\n },\n },\n load: {\n filter: {\n id: new RegExp(resolvedModuleId),\n },\n handler(id) {\n const { resolvedStartConfig } = opts.getConfig()\n if (id === resolvedModuleId) {\n if (this.environment.config.consumer !== 'server') {\n // this will ultimately fail the build if the plugin is used outside the server environment\n // TODO: do we need special handling for `serve`?\n return `export default {}`\n }\n\n // If we're in development, return a dummy manifest\n if (this.environment.config.command === 'serve') {\n return `export const tsrStartManifest = () => ({\n routes: {},\n clientEntry: '${joinURL(resolvedStartConfig.viteAppBase, '@id', ENTRY_POINTS.client)}',\n })`\n }\n\n // This the manifest pulled from the generated route tree and later used by the Router.\n // i.e what's located in `src/routeTree.gen.ts`\n const routeTreeRoutes = globalThis.TSS_ROUTES_MANIFEST\n\n const cssPerChunkCache = new Map<\n Rollup.OutputChunk,\n Array<RouterManagedTag>\n >()\n\n // This is where hydration will start, from when the SSR'd page reaches the browser.\n let entryFile: Rollup.OutputChunk | undefined\n\n const clientBundle = opts.getClientBundle()\n const chunksByFileName = new Map<string, Rollup.OutputChunk>()\n\n const routeChunks: Record<\n string /** fullPath of route file **/,\n Array<Rollup.OutputChunk>\n > = {}\n for (const bundleEntry of Object.values(clientBundle)) {\n if (bundleEntry.type === 'chunk') {\n chunksByFileName.set(bundleEntry.fileName, bundleEntry)\n if (bundleEntry.isEntry) {\n if (entryFile) {\n throw new Error(\n `multiple entries detected: ${entryFile.fileName} ${bundleEntry.fileName}`,\n )\n }\n entryFile = bundleEntry\n }\n const routePieces = bundleEntry.moduleIds.flatMap((m) => {\n const [id, query] = m.split('?')\n if (id === undefined) {\n throw new Error('expected id to be defined')\n }\n if (query === undefined) {\n return []\n }\n const searchParams = new URLSearchParams(query)\n const split = searchParams.get(tsrSplit)\n\n if (split !== null) {\n return {\n id,\n split,\n }\n }\n return []\n })\n if (routePieces.length > 0) {\n routePieces.forEach((r) => {\n let array = routeChunks[r.id]\n if (array === undefined) {\n array = []\n routeChunks[r.id] = array\n }\n array.push(bundleEntry)\n })\n }\n }\n }\n\n const manifest: Manifest = { routes: {} }\n // Add preloads to the routes from the vite manifest\n Object.entries(routeTreeRoutes).forEach(([routeId, v]) => {\n if (!v.filePath) {\n throw new Error(`expected filePath to be set for ${routeId}`)\n }\n const chunks = routeChunks[v.filePath]\n if (chunks) {\n chunks.forEach((chunk) => {\n // Map the relevant imports to their route paths,\n // so that it can be imported in the browser.\n const preloads = chunk.imports.map((d) => {\n const preloadPath = joinURL(\n resolvedStartConfig.viteAppBase,\n d,\n )\n return preloadPath\n })\n\n // Since this is the most important JS entry for the route,\n // it should be moved to the front of the preloads so that\n // it has the best chance of being loaded first.\n preloads.unshift(\n joinURL(resolvedStartConfig.viteAppBase, chunk.fileName),\n )\n\n const assets = getCSSRecursively(\n chunk,\n chunksByFileName,\n resolvedStartConfig.viteAppBase,\n cssPerChunkCache,\n )\n\n manifest.routes[routeId] = {\n ...v,\n assets,\n preloads,\n }\n })\n } else {\n manifest.routes[routeId] = v\n }\n })\n\n if (!entryFile) {\n throw new Error('No entry file found')\n }\n\n manifest.routes[rootRouteId] = manifest.routes[rootRouteId] || {}\n manifest.routes[rootRouteId].preloads = [\n joinURL(resolvedStartConfig.viteAppBase, entryFile.fileName),\n ...entryFile.imports.map((d) =>\n joinURL(resolvedStartConfig.viteAppBase, d),\n ),\n ]\n\n // Gather all the CSS files from the entry file in\n // the `css` key and add them to the root route\n const entryCssAssetsList = getCSSRecursively(\n entryFile,\n chunksByFileName,\n resolvedStartConfig.viteAppBase,\n cssPerChunkCache,\n )\n\n manifest.routes[rootRouteId].assets = [\n ...(manifest.routes[rootRouteId].assets || []),\n ...entryCssAssetsList,\n ]\n\n const recurseRoute = (\n route: {\n preloads?: Array<string>\n children?: Array<any>\n },\n seenPreloads = {} as Record<string, true>,\n ) => {\n route.preloads = route.preloads?.filter((preload) => {\n if (seenPreloads[preload]) {\n return false\n }\n seenPreloads[preload] = true\n return true\n })\n\n if (route.children) {\n route.children.forEach((child) => {\n const childRoute = manifest.routes[child]!\n recurseRoute(childRoute, { ...seenPreloads })\n })\n }\n }\n\n recurseRoute(manifest.routes[rootRouteId])\n\n // Filter out routes that have neither assets nor preloads\n Object.keys(manifest.routes).forEach((routeId) => {\n const route = manifest.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 routeTreeRoutes[routeId]\n }\n })\n\n const startManifest = {\n routes: manifest.routes,\n clientEntry: joinURL(\n resolvedStartConfig.viteAppBase,\n entryFile.fileName,\n ),\n }\n\n return `export const tsrStartManifest = () => (${JSON.stringify(startManifest)})`\n }\n\n return undefined\n },\n },\n }\n}\n"],"names":["id"],"mappings":"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"}
@@ -3,10 +3,11 @@ function routesManifestPlugin() {
3
3
  return {
4
4
  name: "routes-manifest-plugin",
5
5
  onRouteTreeChanged: ({ routeTree, rootRouteNode, routeNodes }) => {
6
- const routesManifest = {
6
+ const allChildren = routeTree.map((d) => d.routePath);
7
+ const routes = {
7
8
  [rootRouteId]: {
8
9
  filePath: rootRouteNode.fullPath,
9
- children: routeTree.map((d) => d.routePath)
10
+ children: allChildren
10
11
  },
11
12
  ...Object.fromEntries(
12
13
  routeNodes.map((d) => {
@@ -15,14 +16,13 @@ function routesManifestPlugin() {
15
16
  filePathId,
16
17
  {
17
18
  filePath: d.fullPath,
18
- parent: d.parent?.routePath ? d.parent.routePath : void 0,
19
19
  children: d.children?.map((childRoute) => childRoute.routePath)
20
20
  }
21
21
  ];
22
22
  })
23
23
  )
24
24
  };
25
- globalThis.TSS_ROUTES_MANIFEST = { routes: routesManifest };
25
+ globalThis.TSS_ROUTES_MANIFEST = routes;
26
26
  }
27
27
  };
28
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"routes-manifest-plugin.js","sources":["../../../../src/start-router-plugin/generator-plugins/routes-manifest-plugin.ts"],"sourcesContent":["import { rootRouteId } from '@tanstack/router-core'\n\nimport type { GeneratorPlugin } from '@tanstack/router-generator'\n\n/**\n * this plugin builds the routes manifest and stores it on globalThis\n * so that it can be accessed later (e.g. from a vite plugin)\n */\nexport function routesManifestPlugin(): GeneratorPlugin {\n return {\n name: 'routes-manifest-plugin',\n onRouteTreeChanged: ({ routeTree, rootRouteNode, routeNodes }) => {\n const routesManifest = {\n [rootRouteId]: {\n filePath: rootRouteNode.fullPath,\n children: routeTree.map((d) => d.routePath),\n },\n ...Object.fromEntries(\n routeNodes.map((d) => {\n const filePathId = d.routePath\n\n return [\n filePathId,\n {\n filePath: d.fullPath,\n parent: d.parent?.routePath ? d.parent.routePath : undefined,\n children: d.children?.map((childRoute) => childRoute.routePath),\n },\n ]\n }),\n ),\n }\n\n globalThis.TSS_ROUTES_MANIFEST = { routes: routesManifest }\n },\n }\n}\n"],"names":[],"mappings":";AAQO,SAAS,uBAAwC;AACtD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,oBAAoB,CAAC,EAAE,WAAW,eAAe,iBAAiB;AAChE,YAAM,iBAAiB;AAAA,QACrB,CAAC,WAAW,GAAG;AAAA,UACb,UAAU,cAAc;AAAA,UACxB,UAAU,UAAU,IAAI,CAAC,MAAM,EAAE,SAAS;AAAA,QAAA;AAAA,QAE5C,GAAG,OAAO;AAAA,UACR,WAAW,IAAI,CAAC,MAAM;AACpB,kBAAM,aAAa,EAAE;AAErB,mBAAO;AAAA,cACL;AAAA,cACA;AAAA,gBACE,UAAU,EAAE;AAAA,gBACZ,QAAQ,EAAE,QAAQ,YAAY,EAAE,OAAO,YAAY;AAAA,gBACnD,UAAU,EAAE,UAAU,IAAI,CAAC,eAAe,WAAW,SAAS;AAAA,cAAA;AAAA,YAChE;AAAA,UAEJ,CAAC;AAAA,QAAA;AAAA,MACH;AAGF,iBAAW,sBAAsB,EAAE,QAAQ,eAAA;AAAA,IAC7C;AAAA,EAAA;AAEJ;"}
1
+ {"version":3,"file":"routes-manifest-plugin.js","sources":["../../../../src/start-router-plugin/generator-plugins/routes-manifest-plugin.ts"],"sourcesContent":["import { rootRouteId } from '@tanstack/router-core'\n\nimport type { GeneratorPlugin } from '@tanstack/router-generator'\n\n/**\n * this plugin builds the routes manifest and stores it on globalThis\n * so that it can be accessed later (e.g. from a vite plugin)\n */\nexport function routesManifestPlugin(): GeneratorPlugin {\n return {\n name: 'routes-manifest-plugin',\n onRouteTreeChanged: ({ routeTree, rootRouteNode, routeNodes }) => {\n const allChildren = routeTree.map((d) => d.routePath)\n const routes: Record<\n string,\n {\n filePath: string\n children: Array<string>\n }\n > = {\n [rootRouteId]: {\n filePath: rootRouteNode.fullPath,\n children: allChildren,\n },\n ...Object.fromEntries(\n routeNodes.map((d) => {\n const filePathId = d.routePath\n\n return [\n filePathId,\n {\n filePath: d.fullPath,\n children: d.children?.map((childRoute) => childRoute.routePath),\n },\n ]\n }),\n ),\n }\n\n globalThis.TSS_ROUTES_MANIFEST = routes\n },\n }\n}\n"],"names":[],"mappings":";AAQO,SAAS,uBAAwC;AACtD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,oBAAoB,CAAC,EAAE,WAAW,eAAe,iBAAiB;AAChE,YAAM,cAAc,UAAU,IAAI,CAAC,MAAM,EAAE,SAAS;AACpD,YAAM,SAMF;AAAA,QACF,CAAC,WAAW,GAAG;AAAA,UACb,UAAU,cAAc;AAAA,UACxB,UAAU;AAAA,QAAA;AAAA,QAEZ,GAAG,OAAO;AAAA,UACR,WAAW,IAAI,CAAC,MAAM;AACpB,kBAAM,aAAa,EAAE;AAErB,mBAAO;AAAA,cACL;AAAA,cACA;AAAA,gBACE,UAAU,EAAE;AAAA,gBACZ,UAAU,EAAE,UAAU,IAAI,CAAC,eAAe,WAAW,SAAS;AAAA,cAAA;AAAA,YAChE;AAAA,UAEJ,CAAC;AAAA,QAAA;AAAA,MACH;AAGF,iBAAW,sBAAsB;AAAA,IACnC;AAAA,EAAA;AAEJ;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/start-plugin-core",
3
- "version": "1.136.8",
3
+ "version": "1.136.9",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -59,13 +59,13 @@
59
59
  "vitefu": "^1.1.1",
60
60
  "xmlbuilder2": "^3.1.1",
61
61
  "zod": "^3.24.2",
62
- "@tanstack/router-generator": "1.136.8",
63
- "@tanstack/router-core": "1.136.8",
64
- "@tanstack/router-plugin": "1.136.8",
62
+ "@tanstack/router-core": "1.136.9",
63
+ "@tanstack/router-generator": "1.136.9",
64
+ "@tanstack/router-plugin": "1.136.9",
65
65
  "@tanstack/router-utils": "1.133.19",
66
66
  "@tanstack/server-functions-plugin": "1.134.5",
67
- "@tanstack/start-client-core": "1.136.8",
68
- "@tanstack/start-server-core": "1.136.8"
67
+ "@tanstack/start-client-core": "1.136.9",
68
+ "@tanstack/start-server-core": "1.136.9"
69
69
  },
70
70
  "devDependencies": {
71
71
  "@types/babel__code-frame": "^7.0.6",
package/src/global.d.ts CHANGED
@@ -1,8 +1,12 @@
1
- import type { Manifest } from '@tanstack/router-core'
2
-
3
1
  /* eslint-disable no-var */
4
2
  declare global {
5
- var TSS_ROUTES_MANIFEST: Manifest
3
+ var TSS_ROUTES_MANIFEST: Record<
4
+ string,
5
+ {
6
+ filePath: string
7
+ children?: Array<string>
8
+ }
9
+ >
6
10
  var TSS_PRERENDABLE_PATHS: Array<{ path: string }> | undefined
7
11
  }
8
12
  export {}
@@ -6,7 +6,7 @@ import { resolveViteId } from '../utils'
6
6
  import { ENTRY_POINTS } from '../constants'
7
7
  import type { GetConfigFn } from '../plugin'
8
8
  import type { PluginOption, Rollup } from 'vite'
9
- import type { RouterManagedTag } from '@tanstack/router-core'
9
+ import type { Manifest, RouterManagedTag } from '@tanstack/router-core'
10
10
 
11
11
  const getCSSRecursively = (
12
12
  chunk: Rollup.OutputChunk,
@@ -97,7 +97,7 @@ export function startManifestPlugin(opts: {
97
97
 
98
98
  // This the manifest pulled from the generated route tree and later used by the Router.
99
99
  // i.e what's located in `src/routeTree.gen.ts`
100
- const routeTreeRoutes = globalThis.TSS_ROUTES_MANIFEST.routes
100
+ const routeTreeRoutes = globalThis.TSS_ROUTES_MANIFEST
101
101
 
102
102
  const cssPerChunkCache = new Map<
103
103
  Rollup.OutputChunk,
@@ -157,6 +157,7 @@ export function startManifestPlugin(opts: {
157
157
  }
158
158
  }
159
159
 
160
+ const manifest: Manifest = { routes: {} }
160
161
  // Add preloads to the routes from the vite manifest
161
162
  Object.entries(routeTreeRoutes).forEach(([routeId, v]) => {
162
163
  if (!v.filePath) {
@@ -168,8 +169,11 @@ export function startManifestPlugin(opts: {
168
169
  // Map the relevant imports to their route paths,
169
170
  // so that it can be imported in the browser.
170
171
  const preloads = chunk.imports.map((d) => {
171
- const assetPath = joinURL(resolvedStartConfig.viteAppBase, d)
172
- return assetPath
172
+ const preloadPath = joinURL(
173
+ resolvedStartConfig.viteAppBase,
174
+ d,
175
+ )
176
+ return preloadPath
173
177
  })
174
178
 
175
179
  // Since this is the most important JS entry for the route,
@@ -179,26 +183,30 @@ export function startManifestPlugin(opts: {
179
183
  joinURL(resolvedStartConfig.viteAppBase, chunk.fileName),
180
184
  )
181
185
 
182
- const cssAssetsList = getCSSRecursively(
186
+ const assets = getCSSRecursively(
183
187
  chunk,
184
188
  chunksByFileName,
185
189
  resolvedStartConfig.viteAppBase,
186
190
  cssPerChunkCache,
187
191
  )
188
192
 
189
- routeTreeRoutes[routeId] = {
193
+ manifest.routes[routeId] = {
190
194
  ...v,
191
- assets: [...(v.assets || []), ...cssAssetsList],
192
- preloads: [...(v.preloads || []), ...preloads],
195
+ assets,
196
+ preloads,
193
197
  }
194
198
  })
199
+ } else {
200
+ manifest.routes[routeId] = v
195
201
  }
196
202
  })
197
203
 
198
204
  if (!entryFile) {
199
205
  throw new Error('No entry file found')
200
206
  }
201
- routeTreeRoutes[rootRouteId]!.preloads = [
207
+
208
+ manifest.routes[rootRouteId] = manifest.routes[rootRouteId] || {}
209
+ manifest.routes[rootRouteId].preloads = [
202
210
  joinURL(resolvedStartConfig.viteAppBase, entryFile.fileName),
203
211
  ...entryFile.imports.map((d) =>
204
212
  joinURL(resolvedStartConfig.viteAppBase, d),
@@ -214,8 +222,8 @@ export function startManifestPlugin(opts: {
214
222
  cssPerChunkCache,
215
223
  )
216
224
 
217
- routeTreeRoutes[rootRouteId]!.assets = [
218
- ...(routeTreeRoutes[rootRouteId]!.assets || []),
225
+ manifest.routes[rootRouteId].assets = [
226
+ ...(manifest.routes[rootRouteId].assets || []),
219
227
  ...entryCssAssetsList,
220
228
  ]
221
229
 
@@ -236,17 +244,17 @@ export function startManifestPlugin(opts: {
236
244
 
237
245
  if (route.children) {
238
246
  route.children.forEach((child) => {
239
- const childRoute = routeTreeRoutes[child]!
247
+ const childRoute = manifest.routes[child]!
240
248
  recurseRoute(childRoute, { ...seenPreloads })
241
249
  })
242
250
  }
243
251
  }
244
252
 
245
- recurseRoute(routeTreeRoutes[rootRouteId]!)
253
+ recurseRoute(manifest.routes[rootRouteId])
246
254
 
247
255
  // Filter out routes that have neither assets nor preloads
248
- Object.keys(routeTreeRoutes).forEach((routeId) => {
249
- const route = routeTreeRoutes[routeId]!
256
+ Object.keys(manifest.routes).forEach((routeId) => {
257
+ const route = manifest.routes[routeId]!
250
258
  const hasAssets = route.assets && route.assets.length > 0
251
259
  const hasPreloads = route.preloads && route.preloads.length > 0
252
260
  if (!hasAssets && !hasPreloads) {
@@ -255,7 +263,7 @@ export function startManifestPlugin(opts: {
255
263
  })
256
264
 
257
265
  const startManifest = {
258
- routes: routeTreeRoutes,
266
+ routes: manifest.routes,
259
267
  clientEntry: joinURL(
260
268
  resolvedStartConfig.viteAppBase,
261
269
  entryFile.fileName,
@@ -10,10 +10,17 @@ export function routesManifestPlugin(): GeneratorPlugin {
10
10
  return {
11
11
  name: 'routes-manifest-plugin',
12
12
  onRouteTreeChanged: ({ routeTree, rootRouteNode, routeNodes }) => {
13
- const routesManifest = {
13
+ const allChildren = routeTree.map((d) => d.routePath)
14
+ const routes: Record<
15
+ string,
16
+ {
17
+ filePath: string
18
+ children: Array<string>
19
+ }
20
+ > = {
14
21
  [rootRouteId]: {
15
22
  filePath: rootRouteNode.fullPath,
16
- children: routeTree.map((d) => d.routePath),
23
+ children: allChildren,
17
24
  },
18
25
  ...Object.fromEntries(
19
26
  routeNodes.map((d) => {
@@ -23,7 +30,6 @@ export function routesManifestPlugin(): GeneratorPlugin {
23
30
  filePathId,
24
31
  {
25
32
  filePath: d.fullPath,
26
- parent: d.parent?.routePath ? d.parent.routePath : undefined,
27
33
  children: d.children?.map((childRoute) => childRoute.routePath),
28
34
  },
29
35
  ]
@@ -31,7 +37,7 @@ export function routesManifestPlugin(): GeneratorPlugin {
31
37
  ),
32
38
  }
33
39
 
34
- globalThis.TSS_ROUTES_MANIFEST = { routes: routesManifest }
40
+ globalThis.TSS_ROUTES_MANIFEST = routes
35
41
  },
36
42
  }
37
43
  }