@tanstack/start-plugin-core 1.132.32 → 1.132.33

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.
@@ -14,6 +14,7 @@ export interface ResolvedStartConfig {
14
14
  startFilePath: string | undefined;
15
15
  routerFilePath: string;
16
16
  srcDirectory: string;
17
+ viteAppBase: string;
17
18
  }
18
19
  export type GetConfigFn = () => {
19
20
  startConfig: TanStackStartOutputConfig;
@@ -1,4 +1,4 @@
1
- import { trimPathRight } from "@tanstack/router-core";
1
+ import { joinPaths } from "@tanstack/router-core";
2
2
  import { VIRTUAL_MODULES } from "@tanstack/start-server-core";
3
3
  import { TanStackServerFnPluginEnv } from "@tanstack/server-functions-plugin";
4
4
  import * as vite from "vite";
@@ -16,12 +16,21 @@ import { resolveEntry } from "./resolve-entries.js";
16
16
  import { getServerOutputDirectory, getClientOutputDirectory } from "./output-directory.js";
17
17
  import { postServerBuild } from "./post-server-build.js";
18
18
  import { createServerFnPlugin } from "./create-server-fn-plugin/plugin.js";
19
+ function isFullUrl(str) {
20
+ try {
21
+ new URL(str);
22
+ return true;
23
+ } catch {
24
+ return false;
25
+ }
26
+ }
19
27
  function TanStackStartVitePluginCore(corePluginOpts, startPluginOpts) {
20
28
  const resolvedStartConfig = {
21
29
  root: "",
22
30
  startFilePath: void 0,
23
31
  routerFilePath: "",
24
- srcDirectory: ""
32
+ srcDirectory: "",
33
+ viteAppBase: ""
25
34
  };
26
35
  let startConfig;
27
36
  const getConfig = () => {
@@ -50,11 +59,40 @@ function TanStackStartVitePluginCore(corePluginOpts, startPluginOpts) {
50
59
  name: "tanstack-start-core:config",
51
60
  enforce: "pre",
52
61
  async config(viteConfig, { command }) {
53
- const viteAppBase = trimPathRight(viteConfig.base || "/");
54
- globalThis.TSS_APP_BASE = viteAppBase;
62
+ resolvedStartConfig.viteAppBase = viteConfig.base ?? "/";
63
+ if (!isFullUrl(resolvedStartConfig.viteAppBase)) {
64
+ resolvedStartConfig.viteAppBase = joinPaths([
65
+ "/",
66
+ viteConfig.base,
67
+ "/"
68
+ ]);
69
+ }
55
70
  const root = viteConfig.root || process.cwd();
56
71
  resolvedStartConfig.root = root;
57
72
  const { startConfig: startConfig2 } = getConfig();
73
+ if (startConfig2.router.basepath === void 0) {
74
+ if (!isFullUrl(resolvedStartConfig.viteAppBase)) {
75
+ startConfig2.router.basepath = resolvedStartConfig.viteAppBase.replace(/^\/|\/$/g, "");
76
+ } else {
77
+ startConfig2.router.basepath = "/";
78
+ }
79
+ } else {
80
+ if (command === "serve" && !viteConfig.server?.middlewareMode) {
81
+ if (!joinPaths(["/", startConfig2.router.basepath, "/"]).startsWith(
82
+ joinPaths(["/", resolvedStartConfig.viteAppBase, "/"])
83
+ )) {
84
+ this.error(
85
+ "[tanstack-start]: During `vite dev`, `router.basepath` must start with the vite `base` config value"
86
+ );
87
+ }
88
+ }
89
+ }
90
+ const TSS_SERVER_FN_BASE = joinPaths([
91
+ "/",
92
+ startConfig2.router.basepath,
93
+ startConfig2.serverFns.base,
94
+ "/"
95
+ ]);
58
96
  const resolvedSrcDirectory = join(root, startConfig2.srcDirectory);
59
97
  resolvedStartConfig.srcDirectory = resolvedSrcDirectory;
60
98
  const startFilePath = resolveEntry({
@@ -116,7 +154,6 @@ function TanStackStartVitePluginCore(corePluginOpts, startPluginOpts) {
116
154
  }
117
155
  });
118
156
  return {
119
- base: viteAppBase,
120
157
  // see https://vite.dev/config/shared-options.html#apptype
121
158
  // this will prevent vite from injecting middlewares that we don't want
122
159
  appType: viteConfig.appType ?? "custom",
@@ -181,9 +218,9 @@ function TanStackStartVitePluginCore(corePluginOpts, startPluginOpts) {
181
218
  // define is an esbuild function that replaces the any instances of given keys with the given values
182
219
  // i.e: __FRAMEWORK_NAME__ can be replaced with JSON.stringify("TanStack Start")
183
220
  // This is not the same as injecting environment variables.
184
- ...defineReplaceEnv("TSS_SERVER_FN_BASE", startConfig2.serverFns.base),
221
+ ...defineReplaceEnv("TSS_SERVER_FN_BASE", TSS_SERVER_FN_BASE),
185
222
  ...defineReplaceEnv("TSS_CLIENT_OUTPUT_DIR", getClientOutputDirectory(viteConfig)),
186
- ...defineReplaceEnv("TSS_APP_BASE", viteAppBase),
223
+ ...defineReplaceEnv("TSS_ROUTER_BASEPATH", startConfig2.router.basepath),
187
224
  ...command === "serve" ? defineReplaceEnv("TSS_SHELL", startConfig2.spa?.enabled ? "true" : "false") : {},
188
225
  ...defineReplaceEnv("TSS_DEV_SERVER", command === "serve" ? "true" : "false")
189
226
  },
@@ -232,7 +269,8 @@ function TanStackStartVitePluginCore(corePluginOpts, startPluginOpts) {
232
269
  }),
233
270
  loadEnvPlugin(),
234
271
  startManifestPlugin({
235
- getClientBundle: () => getBundle(VITE_ENVIRONMENT_NAMES.client)
272
+ getClientBundle: () => getBundle(VITE_ENVIRONMENT_NAMES.client),
273
+ getConfig
236
274
  }),
237
275
  devServerPlugin({ getConfig }),
238
276
  {
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sources":["../../src/plugin.ts"],"sourcesContent":["import { trimPathRight } from '@tanstack/router-core'\nimport { VIRTUAL_MODULES } from '@tanstack/start-server-core'\nimport { TanStackServerFnPluginEnv } from '@tanstack/server-functions-plugin'\nimport * as vite from 'vite'\nimport { crawlFrameworkPkgs } from 'vitefu'\nimport { join } from 'pathe'\nimport { escapePath } from 'tinyglobby'\nimport { startManifestPlugin } from './start-manifest-plugin/plugin'\nimport { startCompilerPlugin } from './start-compiler-plugin/plugin'\nimport { ENTRY_POINTS, VITE_ENVIRONMENT_NAMES } from './constants'\nimport { tanStackStartRouter } from './start-router-plugin/plugin'\nimport { loadEnvPlugin } from './load-env-plugin/plugin'\nimport { devServerPlugin } from './dev-server-plugin/plugin'\nimport { parseStartConfig } from './schema'\nimport { resolveEntry } from './resolve-entries'\nimport {\n getClientOutputDirectory,\n getServerOutputDirectory,\n} from './output-directory'\nimport { postServerBuild } from './post-server-build'\nimport { createServerFnPlugin } from './create-server-fn-plugin/plugin'\nimport type { ViteEnvironmentNames } from './constants'\nimport type {\n TanStackStartInputConfig,\n TanStackStartOutputConfig,\n} from './schema'\nimport type { PluginOption } from 'vite'\nimport type { CompileStartFrameworkOptions } from './start-compiler-plugin/compilers'\n\nexport interface TanStackStartVitePluginCoreOptions {\n framework: CompileStartFrameworkOptions\n defaultEntryPaths: {\n client: string\n server: string\n start: string\n }\n}\n\nexport interface ResolvedStartConfig {\n root: string\n startFilePath: string | undefined\n routerFilePath: string\n srcDirectory: string\n}\n\nexport type GetConfigFn = () => {\n startConfig: TanStackStartOutputConfig\n resolvedStartConfig: ResolvedStartConfig\n}\nexport function TanStackStartVitePluginCore(\n corePluginOpts: TanStackStartVitePluginCoreOptions,\n startPluginOpts: TanStackStartInputConfig,\n): Array<PluginOption> {\n const resolvedStartConfig: ResolvedStartConfig = {\n root: '',\n startFilePath: undefined,\n routerFilePath: '',\n srcDirectory: '',\n }\n\n let startConfig: TanStackStartOutputConfig | null\n const getConfig: GetConfigFn = () => {\n if (!resolvedStartConfig.root) {\n throw new Error(`Cannot get config before root is resolved`)\n }\n if (!startConfig) {\n startConfig = parseStartConfig(\n startPluginOpts,\n corePluginOpts,\n resolvedStartConfig.root,\n )\n }\n return { startConfig, resolvedStartConfig }\n }\n\n const capturedBundle: Partial<\n Record<ViteEnvironmentNames, vite.Rollup.OutputBundle>\n > = {}\n\n function getBundle(envName: ViteEnvironmentNames): vite.Rollup.OutputBundle {\n const bundle = capturedBundle[envName]\n if (!bundle) {\n throw new Error(`No bundle captured for environment: ${envName}`)\n }\n return bundle\n }\n\n return [\n {\n name: 'tanstack-start-core:config',\n enforce: 'pre',\n async config(viteConfig, { command }) {\n const viteAppBase = trimPathRight(viteConfig.base || '/')\n globalThis.TSS_APP_BASE = viteAppBase\n\n const root = viteConfig.root || process.cwd()\n resolvedStartConfig.root = root\n\n const { startConfig } = getConfig()\n const resolvedSrcDirectory = join(root, startConfig.srcDirectory)\n resolvedStartConfig.srcDirectory = resolvedSrcDirectory\n\n const startFilePath = resolveEntry({\n type: 'start entry',\n configuredEntry: startConfig.start.entry,\n defaultEntry: 'start',\n resolvedSrcDirectory,\n required: false,\n })\n resolvedStartConfig.startFilePath = startFilePath\n\n const routerFilePath = resolveEntry({\n type: 'router entry',\n configuredEntry: startConfig.router.entry,\n defaultEntry: 'router',\n resolvedSrcDirectory,\n required: true,\n })\n resolvedStartConfig.routerFilePath = routerFilePath\n\n const clientEntryPath = resolveEntry({\n type: 'client entry',\n configuredEntry: startConfig.client.entry,\n defaultEntry: 'client',\n resolvedSrcDirectory,\n required: false,\n })\n\n const serverEntryPath = resolveEntry({\n type: 'server entry',\n configuredEntry: startConfig.server.entry,\n defaultEntry: 'server',\n resolvedSrcDirectory,\n required: false,\n })\n\n const clientAlias = vite.normalizePath(\n clientEntryPath ?? corePluginOpts.defaultEntryPaths.client,\n )\n const serverAlias = vite.normalizePath(\n serverEntryPath ?? corePluginOpts.defaultEntryPaths.server,\n )\n const startAlias = vite.normalizePath(\n startFilePath ?? corePluginOpts.defaultEntryPaths.start,\n )\n const routerAlias = vite.normalizePath(routerFilePath)\n\n const entryAliasConfiguration: Record<\n (typeof ENTRY_POINTS)[keyof typeof ENTRY_POINTS],\n string\n > = {\n [ENTRY_POINTS.client]: clientAlias,\n [ENTRY_POINTS.server]: serverAlias,\n [ENTRY_POINTS.start]: startAlias,\n [ENTRY_POINTS.router]: routerAlias,\n }\n\n const startPackageName =\n `@tanstack/${corePluginOpts.framework}-start` as const\n\n // crawl packages that have start in \"peerDependencies\"\n // see https://github.com/svitejs/vitefu/blob/d8d82fa121e3b2215ba437107093c77bde51b63b/src/index.js#L95-L101\n\n // this is currently uncached; could be implemented similarly as vite handles lock file changes\n // see https://github.com/vitejs/vite/blob/557f797d29422027e8c451ca50dd84bf8c41b5f0/packages/vite/src/node/optimizer/index.ts#L1282\n\n const crawlFrameworkPkgsResult = await crawlFrameworkPkgs({\n root: process.cwd(),\n isBuild: command === 'build',\n isFrameworkPkgByJson(pkgJson) {\n const peerDependencies = pkgJson['peerDependencies']\n\n if (peerDependencies) {\n return startPackageName in peerDependencies\n }\n\n return false\n },\n })\n\n return {\n base: viteAppBase,\n // see https://vite.dev/config/shared-options.html#apptype\n // this will prevent vite from injecting middlewares that we don't want\n appType: viteConfig.appType ?? 'custom',\n environments: {\n [VITE_ENVIRONMENT_NAMES.client]: {\n consumer: 'client',\n build: {\n rollupOptions: {\n input: {\n main: ENTRY_POINTS.client,\n },\n },\n outDir: getClientOutputDirectory(viteConfig),\n },\n optimizeDeps: {\n // Ensure user code can be crawled for dependencies\n entries: [clientAlias, routerAlias].map((entry) =>\n // Entries are treated as `tinyglobby` patterns so need to be escaped\n escapePath(entry),\n ),\n },\n },\n [VITE_ENVIRONMENT_NAMES.server]: {\n consumer: 'server',\n build: {\n ssr: true,\n rollupOptions: {\n input:\n viteConfig.environments?.[VITE_ENVIRONMENT_NAMES.server]\n ?.build?.rollupOptions?.input ?? ENTRY_POINTS.server,\n },\n outDir: getServerOutputDirectory(viteConfig),\n commonjsOptions: {\n include: [/node_modules/],\n },\n copyPublicDir:\n viteConfig.environments?.[VITE_ENVIRONMENT_NAMES.server]\n ?.build?.copyPublicDir ?? false,\n },\n optimizeDeps: {\n // Ensure user code can be crawled for dependencies\n entries: [serverAlias, startAlias, routerAlias].map((entry) =>\n // Entries are treated as `tinyglobby` patterns so need to be escaped\n escapePath(entry),\n ),\n },\n },\n },\n\n resolve: {\n noExternal: [\n // ENTRY_POINTS.start,\n '@tanstack/start**',\n `@tanstack/${corePluginOpts.framework}-start**`,\n ...crawlFrameworkPkgsResult.ssr.noExternal.sort(),\n ],\n alias: {\n ...entryAliasConfiguration,\n },\n },\n /* prettier-ignore */\n define: {\n // define is an esbuild function that replaces the any instances of given keys with the given values\n // i.e: __FRAMEWORK_NAME__ can be replaced with JSON.stringify(\"TanStack Start\")\n // This is not the same as injecting environment variables.\n\n ...defineReplaceEnv('TSS_SERVER_FN_BASE', startConfig.serverFns.base),\n ...defineReplaceEnv('TSS_CLIENT_OUTPUT_DIR', getClientOutputDirectory(viteConfig)),\n ...defineReplaceEnv('TSS_APP_BASE', viteAppBase),\n ...(command === 'serve' ? defineReplaceEnv('TSS_SHELL', startConfig.spa?.enabled ? 'true' : 'false') : {}),\n ...defineReplaceEnv('TSS_DEV_SERVER', command === 'serve' ? 'true' : 'false'),\n },\n builder: {\n sharedPlugins: true,\n async buildApp(builder) {\n const client = builder.environments[VITE_ENVIRONMENT_NAMES.client]\n const server = builder.environments[VITE_ENVIRONMENT_NAMES.server]\n\n if (!client) {\n throw new Error('Client environment not found')\n }\n\n if (!server) {\n throw new Error('SSR environment not found')\n }\n\n if (!client.isBuilt) {\n // Build the client bundle first\n await builder.build(client)\n }\n if (!server.isBuilt) {\n // Build the SSR bundle\n await builder.build(server)\n }\n const serverBundle = getBundle(VITE_ENVIRONMENT_NAMES.server)\n await postServerBuild({ builder, startConfig, serverBundle })\n },\n },\n }\n },\n },\n tanStackStartRouter(startPluginOpts, getConfig, corePluginOpts),\n // N.B. TanStackStartCompilerPlugin must be before the TanStackServerFnPluginEnv\n startCompilerPlugin(corePluginOpts.framework),\n createServerFnPlugin(corePluginOpts.framework),\n\n TanStackServerFnPluginEnv({\n // This is the ID that will be available to look up and import\n // our server function manifest and resolve its module\n manifestVirtualImportId: VIRTUAL_MODULES.serverFnManifest,\n client: {\n getRuntimeCode: () =>\n `import { createClientRpc } from '@tanstack/${corePluginOpts.framework}-start/client-rpc'`,\n replacer: (d) => `createClientRpc('${d.functionId}')`,\n envName: VITE_ENVIRONMENT_NAMES.client,\n },\n server: {\n getRuntimeCode: () =>\n `import { createServerRpc } from '@tanstack/${corePluginOpts.framework}-start/server-rpc'`,\n replacer: (d) => `createServerRpc('${d.functionId}', ${d.fn})`,\n envName: VITE_ENVIRONMENT_NAMES.server,\n },\n }),\n loadEnvPlugin(),\n startManifestPlugin({\n getClientBundle: () => getBundle(VITE_ENVIRONMENT_NAMES.client),\n }),\n devServerPlugin({ getConfig }),\n {\n name: 'tanstack-start:core:capture-bundle',\n applyToEnvironment(e) {\n return (\n e.name === VITE_ENVIRONMENT_NAMES.client ||\n e.name === VITE_ENVIRONMENT_NAMES.server\n )\n },\n enforce: 'post',\n generateBundle(_options, bundle) {\n const environment = this.environment.name as ViteEnvironmentNames\n if (!Object.values(VITE_ENVIRONMENT_NAMES).includes(environment)) {\n throw new Error(`Unknown environment: ${environment}`)\n }\n capturedBundle[environment] = bundle\n },\n },\n ]\n}\n\nfunction defineReplaceEnv<TKey extends string, TValue extends string>(\n key: TKey,\n value: TValue,\n): { [P in `process.env.${TKey}` | `import.meta.env.${TKey}`]: TValue } {\n return {\n [`process.env.${key}`]: JSON.stringify(value),\n [`import.meta.env.${key}`]: JSON.stringify(value),\n } as { [P in `process.env.${TKey}` | `import.meta.env.${TKey}`]: TValue }\n}\n"],"names":["startConfig"],"mappings":";;;;;;;;;;;;;;;;;;AAiDO,SAAS,4BACd,gBACA,iBACqB;AACrB,QAAM,sBAA2C;AAAA,IAC/C,MAAM;AAAA,IACN,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,cAAc;AAAA,EAAA;AAGhB,MAAI;AACJ,QAAM,YAAyB,MAAM;AACnC,QAAI,CAAC,oBAAoB,MAAM;AAC7B,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC7D;AACA,QAAI,CAAC,aAAa;AAChB,oBAAc;AAAA,QACZ;AAAA,QACA;AAAA,QACA,oBAAoB;AAAA,MAAA;AAAA,IAExB;AACA,WAAO,EAAE,aAAa,oBAAA;AAAA,EACxB;AAEA,QAAM,iBAEF,CAAA;AAEJ,WAAS,UAAU,SAAyD;AAC1E,UAAM,SAAS,eAAe,OAAO;AACrC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,uCAAuC,OAAO,EAAE;AAAA,IAClE;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM,OAAO,YAAY,EAAE,WAAW;AACpC,cAAM,cAAc,cAAc,WAAW,QAAQ,GAAG;AACxD,mBAAW,eAAe;AAE1B,cAAM,OAAO,WAAW,QAAQ,QAAQ,IAAA;AACxC,4BAAoB,OAAO;AAE3B,cAAM,EAAE,aAAAA,aAAAA,IAAgB,UAAA;AACxB,cAAM,uBAAuB,KAAK,MAAMA,aAAY,YAAY;AAChE,4BAAoB,eAAe;AAEnC,cAAM,gBAAgB,aAAa;AAAA,UACjC,MAAM;AAAA,UACN,iBAAiBA,aAAY,MAAM;AAAA,UACnC,cAAc;AAAA,UACd;AAAA,UACA,UAAU;AAAA,QAAA,CACX;AACD,4BAAoB,gBAAgB;AAEpC,cAAM,iBAAiB,aAAa;AAAA,UAClC,MAAM;AAAA,UACN,iBAAiBA,aAAY,OAAO;AAAA,UACpC,cAAc;AAAA,UACd;AAAA,UACA,UAAU;AAAA,QAAA,CACX;AACD,4BAAoB,iBAAiB;AAErC,cAAM,kBAAkB,aAAa;AAAA,UACnC,MAAM;AAAA,UACN,iBAAiBA,aAAY,OAAO;AAAA,UACpC,cAAc;AAAA,UACd;AAAA,UACA,UAAU;AAAA,QAAA,CACX;AAED,cAAM,kBAAkB,aAAa;AAAA,UACnC,MAAM;AAAA,UACN,iBAAiBA,aAAY,OAAO;AAAA,UACpC,cAAc;AAAA,UACd;AAAA,UACA,UAAU;AAAA,QAAA,CACX;AAED,cAAM,cAAc,KAAK;AAAA,UACvB,mBAAmB,eAAe,kBAAkB;AAAA,QAAA;AAEtD,cAAM,cAAc,KAAK;AAAA,UACvB,mBAAmB,eAAe,kBAAkB;AAAA,QAAA;AAEtD,cAAM,aAAa,KAAK;AAAA,UACtB,iBAAiB,eAAe,kBAAkB;AAAA,QAAA;AAEpD,cAAM,cAAc,KAAK,cAAc,cAAc;AAErD,cAAM,0BAGF;AAAA,UACF,CAAC,aAAa,MAAM,GAAG;AAAA,UACvB,CAAC,aAAa,MAAM,GAAG;AAAA,UACvB,CAAC,aAAa,KAAK,GAAG;AAAA,UACtB,CAAC,aAAa,MAAM,GAAG;AAAA,QAAA;AAGzB,cAAM,mBACJ,aAAa,eAAe,SAAS;AAQvC,cAAM,2BAA2B,MAAM,mBAAmB;AAAA,UACxD,MAAM,QAAQ,IAAA;AAAA,UACd,SAAS,YAAY;AAAA,UACrB,qBAAqB,SAAS;AAC5B,kBAAM,mBAAmB,QAAQ,kBAAkB;AAEnD,gBAAI,kBAAkB;AACpB,qBAAO,oBAAoB;AAAA,YAC7B;AAEA,mBAAO;AAAA,UACT;AAAA,QAAA,CACD;AAED,eAAO;AAAA,UACL,MAAM;AAAA;AAAA;AAAA,UAGN,SAAS,WAAW,WAAW;AAAA,UAC/B,cAAc;AAAA,YACZ,CAAC,uBAAuB,MAAM,GAAG;AAAA,cAC/B,UAAU;AAAA,cACV,OAAO;AAAA,gBACL,eAAe;AAAA,kBACb,OAAO;AAAA,oBACL,MAAM,aAAa;AAAA,kBAAA;AAAA,gBACrB;AAAA,gBAEF,QAAQ,yBAAyB,UAAU;AAAA,cAAA;AAAA,cAE7C,cAAc;AAAA;AAAA,gBAEZ,SAAS,CAAC,aAAa,WAAW,EAAE;AAAA,kBAAI,CAAC;AAAA;AAAA,oBAEvC,WAAW,KAAK;AAAA;AAAA,gBAAA;AAAA,cAClB;AAAA,YACF;AAAA,YAEF,CAAC,uBAAuB,MAAM,GAAG;AAAA,cAC/B,UAAU;AAAA,cACV,OAAO;AAAA,gBACL,KAAK;AAAA,gBACL,eAAe;AAAA,kBACb,OACE,WAAW,eAAe,uBAAuB,MAAM,GACnD,OAAO,eAAe,SAAS,aAAa;AAAA,gBAAA;AAAA,gBAEpD,QAAQ,yBAAyB,UAAU;AAAA,gBAC3C,iBAAiB;AAAA,kBACf,SAAS,CAAC,cAAc;AAAA,gBAAA;AAAA,gBAE1B,eACE,WAAW,eAAe,uBAAuB,MAAM,GACnD,OAAO,iBAAiB;AAAA,cAAA;AAAA,cAEhC,cAAc;AAAA;AAAA,gBAEZ,SAAS,CAAC,aAAa,YAAY,WAAW,EAAE;AAAA,kBAAI,CAAC;AAAA;AAAA,oBAEnD,WAAW,KAAK;AAAA;AAAA,gBAAA;AAAA,cAClB;AAAA,YACF;AAAA,UACF;AAAA,UAGF,SAAS;AAAA,YACP,YAAY;AAAA;AAAA,cAEV;AAAA,cACA,aAAa,eAAe,SAAS;AAAA,cACrC,GAAG,yBAAyB,IAAI,WAAW,KAAA;AAAA,YAAK;AAAA,YAElD,OAAO;AAAA,cACL,GAAG;AAAA,YAAA;AAAA,UACL;AAAA;AAAA,UAGF,QAAQ;AAAA;AAAA;AAAA;AAAA,YAKN,GAAG,iBAAiB,sBAAsBA,aAAY,UAAU,IAAI;AAAA,YACpE,GAAG,iBAAiB,yBAAyB,yBAAyB,UAAU,CAAC;AAAA,YACjF,GAAG,iBAAiB,gBAAgB,WAAW;AAAA,YAC/C,GAAI,YAAY,UAAU,iBAAiB,aAAaA,aAAY,KAAK,UAAU,SAAS,OAAO,IAAI,CAAA;AAAA,YACvG,GAAG,iBAAiB,kBAAkB,YAAY,UAAU,SAAS,OAAO;AAAA,UAAA;AAAA,UAE9E,SAAS;AAAA,YACP,eAAe;AAAA,YACf,MAAM,SAAS,SAAS;AACtB,oBAAM,SAAS,QAAQ,aAAa,uBAAuB,MAAM;AACjE,oBAAM,SAAS,QAAQ,aAAa,uBAAuB,MAAM;AAEjE,kBAAI,CAAC,QAAQ;AACX,sBAAM,IAAI,MAAM,8BAA8B;AAAA,cAChD;AAEA,kBAAI,CAAC,QAAQ;AACX,sBAAM,IAAI,MAAM,2BAA2B;AAAA,cAC7C;AAEA,kBAAI,CAAC,OAAO,SAAS;AAEnB,sBAAM,QAAQ,MAAM,MAAM;AAAA,cAC5B;AACA,kBAAI,CAAC,OAAO,SAAS;AAEnB,sBAAM,QAAQ,MAAM,MAAM;AAAA,cAC5B;AACA,oBAAM,eAAe,UAAU,uBAAuB,MAAM;AAC5D,oBAAM,gBAAgB,EAAE,SAAS,aAAAA,cAAa,cAAc;AAAA,YAC9D;AAAA,UAAA;AAAA,QACF;AAAA,MAEJ;AAAA,IAAA;AAAA,IAEF,oBAAoB,iBAAiB,WAAW,cAAc;AAAA;AAAA,IAE9D,oBAAoB,eAAe,SAAS;AAAA,IAC5C,qBAAqB,eAAe,SAAS;AAAA,IAE7C,0BAA0B;AAAA;AAAA;AAAA,MAGxB,yBAAyB,gBAAgB;AAAA,MACzC,QAAQ;AAAA,QACN,gBAAgB,MACd,8CAA8C,eAAe,SAAS;AAAA,QACxE,UAAU,CAAC,MAAM,oBAAoB,EAAE,UAAU;AAAA,QACjD,SAAS,uBAAuB;AAAA,MAAA;AAAA,MAElC,QAAQ;AAAA,QACN,gBAAgB,MACd,8CAA8C,eAAe,SAAS;AAAA,QACxE,UAAU,CAAC,MAAM,oBAAoB,EAAE,UAAU,MAAM,EAAE,EAAE;AAAA,QAC3D,SAAS,uBAAuB;AAAA,MAAA;AAAA,IAClC,CACD;AAAA,IACD,cAAA;AAAA,IACA,oBAAoB;AAAA,MAClB,iBAAiB,MAAM,UAAU,uBAAuB,MAAM;AAAA,IAAA,CAC/D;AAAA,IACD,gBAAgB,EAAE,WAAW;AAAA,IAC7B;AAAA,MACE,MAAM;AAAA,MACN,mBAAmB,GAAG;AACpB,eACE,EAAE,SAAS,uBAAuB,UAClC,EAAE,SAAS,uBAAuB;AAAA,MAEtC;AAAA,MACA,SAAS;AAAA,MACT,eAAe,UAAU,QAAQ;AAC/B,cAAM,cAAc,KAAK,YAAY;AACrC,YAAI,CAAC,OAAO,OAAO,sBAAsB,EAAE,SAAS,WAAW,GAAG;AAChE,gBAAM,IAAI,MAAM,wBAAwB,WAAW,EAAE;AAAA,QACvD;AACA,uBAAe,WAAW,IAAI;AAAA,MAChC;AAAA,IAAA;AAAA,EACF;AAEJ;AAEA,SAAS,iBACP,KACA,OACsE;AACtE,SAAO;AAAA,IACL,CAAC,eAAe,GAAG,EAAE,GAAG,KAAK,UAAU,KAAK;AAAA,IAC5C,CAAC,mBAAmB,GAAG,EAAE,GAAG,KAAK,UAAU,KAAK;AAAA,EAAA;AAEpD;"}
1
+ {"version":3,"file":"plugin.js","sources":["../../src/plugin.ts"],"sourcesContent":["import { joinPaths } from '@tanstack/router-core'\nimport { VIRTUAL_MODULES } from '@tanstack/start-server-core'\nimport { TanStackServerFnPluginEnv } from '@tanstack/server-functions-plugin'\nimport * as vite from 'vite'\nimport { crawlFrameworkPkgs } from 'vitefu'\nimport { join } from 'pathe'\nimport { escapePath } from 'tinyglobby'\nimport { startManifestPlugin } from './start-manifest-plugin/plugin'\nimport { startCompilerPlugin } from './start-compiler-plugin/plugin'\nimport { ENTRY_POINTS, VITE_ENVIRONMENT_NAMES } from './constants'\nimport { tanStackStartRouter } from './start-router-plugin/plugin'\nimport { loadEnvPlugin } from './load-env-plugin/plugin'\nimport { devServerPlugin } from './dev-server-plugin/plugin'\nimport { parseStartConfig } from './schema'\nimport { resolveEntry } from './resolve-entries'\nimport {\n getClientOutputDirectory,\n getServerOutputDirectory,\n} from './output-directory'\nimport { postServerBuild } from './post-server-build'\nimport { createServerFnPlugin } from './create-server-fn-plugin/plugin'\nimport type { ViteEnvironmentNames } from './constants'\nimport type {\n TanStackStartInputConfig,\n TanStackStartOutputConfig,\n} from './schema'\nimport type { PluginOption } from 'vite'\nimport type { CompileStartFrameworkOptions } from './start-compiler-plugin/compilers'\n\nexport interface TanStackStartVitePluginCoreOptions {\n framework: CompileStartFrameworkOptions\n defaultEntryPaths: {\n client: string\n server: string\n start: string\n }\n}\n\nexport interface ResolvedStartConfig {\n root: string\n startFilePath: string | undefined\n routerFilePath: string\n srcDirectory: string\n viteAppBase: string\n}\n\nexport type GetConfigFn = () => {\n startConfig: TanStackStartOutputConfig\n resolvedStartConfig: ResolvedStartConfig\n}\n\nfunction isFullUrl(str: string): boolean {\n try {\n new URL(str)\n return true\n } catch {\n return false\n }\n}\n\nexport function TanStackStartVitePluginCore(\n corePluginOpts: TanStackStartVitePluginCoreOptions,\n startPluginOpts: TanStackStartInputConfig,\n): Array<PluginOption> {\n const resolvedStartConfig: ResolvedStartConfig = {\n root: '',\n startFilePath: undefined,\n routerFilePath: '',\n srcDirectory: '',\n viteAppBase: '',\n }\n\n let startConfig: TanStackStartOutputConfig | null\n const getConfig: GetConfigFn = () => {\n if (!resolvedStartConfig.root) {\n throw new Error(`Cannot get config before root is resolved`)\n }\n if (!startConfig) {\n startConfig = parseStartConfig(\n startPluginOpts,\n corePluginOpts,\n resolvedStartConfig.root,\n )\n }\n return { startConfig, resolvedStartConfig }\n }\n\n const capturedBundle: Partial<\n Record<ViteEnvironmentNames, vite.Rollup.OutputBundle>\n > = {}\n\n function getBundle(envName: ViteEnvironmentNames): vite.Rollup.OutputBundle {\n const bundle = capturedBundle[envName]\n if (!bundle) {\n throw new Error(`No bundle captured for environment: ${envName}`)\n }\n return bundle\n }\n\n return [\n {\n name: 'tanstack-start-core:config',\n enforce: 'pre',\n async config(viteConfig, { command }) {\n resolvedStartConfig.viteAppBase = viteConfig.base ?? '/'\n if (!isFullUrl(resolvedStartConfig.viteAppBase)) {\n resolvedStartConfig.viteAppBase = joinPaths([\n '/',\n viteConfig.base,\n '/',\n ])\n }\n const root = viteConfig.root || process.cwd()\n resolvedStartConfig.root = root\n\n const { startConfig } = getConfig()\n if (startConfig.router.basepath === undefined) {\n if (!isFullUrl(resolvedStartConfig.viteAppBase)) {\n startConfig.router.basepath =\n resolvedStartConfig.viteAppBase.replace(/^\\/|\\/$/g, '')\n } else {\n startConfig.router.basepath = '/'\n }\n } else {\n if (command === 'serve' && !viteConfig.server?.middlewareMode) {\n // when serving, we must ensure that router basepath and viteAppBase are aligned\n if (\n !joinPaths(['/', startConfig.router.basepath, '/']).startsWith(\n joinPaths(['/', resolvedStartConfig.viteAppBase, '/']),\n )\n ) {\n this.error(\n '[tanstack-start]: During `vite dev`, `router.basepath` must start with the vite `base` config value',\n )\n }\n }\n }\n\n const TSS_SERVER_FN_BASE = joinPaths([\n '/',\n startConfig.router.basepath,\n startConfig.serverFns.base,\n '/',\n ])\n const resolvedSrcDirectory = join(root, startConfig.srcDirectory)\n resolvedStartConfig.srcDirectory = resolvedSrcDirectory\n\n const startFilePath = resolveEntry({\n type: 'start entry',\n configuredEntry: startConfig.start.entry,\n defaultEntry: 'start',\n resolvedSrcDirectory,\n required: false,\n })\n resolvedStartConfig.startFilePath = startFilePath\n\n const routerFilePath = resolveEntry({\n type: 'router entry',\n configuredEntry: startConfig.router.entry,\n defaultEntry: 'router',\n resolvedSrcDirectory,\n required: true,\n })\n resolvedStartConfig.routerFilePath = routerFilePath\n\n const clientEntryPath = resolveEntry({\n type: 'client entry',\n configuredEntry: startConfig.client.entry,\n defaultEntry: 'client',\n resolvedSrcDirectory,\n required: false,\n })\n\n const serverEntryPath = resolveEntry({\n type: 'server entry',\n configuredEntry: startConfig.server.entry,\n defaultEntry: 'server',\n resolvedSrcDirectory,\n required: false,\n })\n\n const clientAlias = vite.normalizePath(\n clientEntryPath ?? corePluginOpts.defaultEntryPaths.client,\n )\n const serverAlias = vite.normalizePath(\n serverEntryPath ?? corePluginOpts.defaultEntryPaths.server,\n )\n const startAlias = vite.normalizePath(\n startFilePath ?? corePluginOpts.defaultEntryPaths.start,\n )\n const routerAlias = vite.normalizePath(routerFilePath)\n\n const entryAliasConfiguration: Record<\n (typeof ENTRY_POINTS)[keyof typeof ENTRY_POINTS],\n string\n > = {\n [ENTRY_POINTS.client]: clientAlias,\n [ENTRY_POINTS.server]: serverAlias,\n [ENTRY_POINTS.start]: startAlias,\n [ENTRY_POINTS.router]: routerAlias,\n }\n\n const startPackageName =\n `@tanstack/${corePluginOpts.framework}-start` as const\n\n // crawl packages that have start in \"peerDependencies\"\n // see https://github.com/svitejs/vitefu/blob/d8d82fa121e3b2215ba437107093c77bde51b63b/src/index.js#L95-L101\n\n // this is currently uncached; could be implemented similarly as vite handles lock file changes\n // see https://github.com/vitejs/vite/blob/557f797d29422027e8c451ca50dd84bf8c41b5f0/packages/vite/src/node/optimizer/index.ts#L1282\n\n const crawlFrameworkPkgsResult = await crawlFrameworkPkgs({\n root: process.cwd(),\n isBuild: command === 'build',\n isFrameworkPkgByJson(pkgJson) {\n const peerDependencies = pkgJson['peerDependencies']\n\n if (peerDependencies) {\n return startPackageName in peerDependencies\n }\n\n return false\n },\n })\n\n return {\n // see https://vite.dev/config/shared-options.html#apptype\n // this will prevent vite from injecting middlewares that we don't want\n appType: viteConfig.appType ?? 'custom',\n environments: {\n [VITE_ENVIRONMENT_NAMES.client]: {\n consumer: 'client',\n build: {\n rollupOptions: {\n input: {\n main: ENTRY_POINTS.client,\n },\n },\n outDir: getClientOutputDirectory(viteConfig),\n },\n optimizeDeps: {\n // Ensure user code can be crawled for dependencies\n entries: [clientAlias, routerAlias].map((entry) =>\n // Entries are treated as `tinyglobby` patterns so need to be escaped\n escapePath(entry),\n ),\n },\n },\n [VITE_ENVIRONMENT_NAMES.server]: {\n consumer: 'server',\n build: {\n ssr: true,\n rollupOptions: {\n input:\n viteConfig.environments?.[VITE_ENVIRONMENT_NAMES.server]\n ?.build?.rollupOptions?.input ?? ENTRY_POINTS.server,\n },\n outDir: getServerOutputDirectory(viteConfig),\n commonjsOptions: {\n include: [/node_modules/],\n },\n copyPublicDir:\n viteConfig.environments?.[VITE_ENVIRONMENT_NAMES.server]\n ?.build?.copyPublicDir ?? false,\n },\n optimizeDeps: {\n // Ensure user code can be crawled for dependencies\n entries: [serverAlias, startAlias, routerAlias].map((entry) =>\n // Entries are treated as `tinyglobby` patterns so need to be escaped\n escapePath(entry),\n ),\n },\n },\n },\n\n resolve: {\n noExternal: [\n // ENTRY_POINTS.start,\n '@tanstack/start**',\n `@tanstack/${corePluginOpts.framework}-start**`,\n ...crawlFrameworkPkgsResult.ssr.noExternal.sort(),\n ],\n alias: {\n ...entryAliasConfiguration,\n },\n },\n /* prettier-ignore */\n define: {\n // define is an esbuild function that replaces the any instances of given keys with the given values\n // i.e: __FRAMEWORK_NAME__ can be replaced with JSON.stringify(\"TanStack Start\")\n // This is not the same as injecting environment variables.\n\n ...defineReplaceEnv('TSS_SERVER_FN_BASE', TSS_SERVER_FN_BASE),\n ...defineReplaceEnv('TSS_CLIENT_OUTPUT_DIR', getClientOutputDirectory(viteConfig)),\n ...defineReplaceEnv('TSS_ROUTER_BASEPATH', startConfig.router.basepath),\n ...(command === 'serve' ? defineReplaceEnv('TSS_SHELL', startConfig.spa?.enabled ? 'true' : 'false') : {}),\n ...defineReplaceEnv('TSS_DEV_SERVER', command === 'serve' ? 'true' : 'false'),\n },\n builder: {\n sharedPlugins: true,\n async buildApp(builder) {\n const client = builder.environments[VITE_ENVIRONMENT_NAMES.client]\n const server = builder.environments[VITE_ENVIRONMENT_NAMES.server]\n\n if (!client) {\n throw new Error('Client environment not found')\n }\n\n if (!server) {\n throw new Error('SSR environment not found')\n }\n\n if (!client.isBuilt) {\n // Build the client bundle first\n await builder.build(client)\n }\n if (!server.isBuilt) {\n // Build the SSR bundle\n await builder.build(server)\n }\n const serverBundle = getBundle(VITE_ENVIRONMENT_NAMES.server)\n await postServerBuild({ builder, startConfig, serverBundle })\n },\n },\n }\n },\n },\n tanStackStartRouter(startPluginOpts, getConfig, corePluginOpts),\n // N.B. TanStackStartCompilerPlugin must be before the TanStackServerFnPluginEnv\n startCompilerPlugin(corePluginOpts.framework),\n createServerFnPlugin(corePluginOpts.framework),\n\n TanStackServerFnPluginEnv({\n // This is the ID that will be available to look up and import\n // our server function manifest and resolve its module\n manifestVirtualImportId: VIRTUAL_MODULES.serverFnManifest,\n client: {\n getRuntimeCode: () =>\n `import { createClientRpc } from '@tanstack/${corePluginOpts.framework}-start/client-rpc'`,\n replacer: (d) => `createClientRpc('${d.functionId}')`,\n envName: VITE_ENVIRONMENT_NAMES.client,\n },\n server: {\n getRuntimeCode: () =>\n `import { createServerRpc } from '@tanstack/${corePluginOpts.framework}-start/server-rpc'`,\n replacer: (d) => `createServerRpc('${d.functionId}', ${d.fn})`,\n envName: VITE_ENVIRONMENT_NAMES.server,\n },\n }),\n loadEnvPlugin(),\n startManifestPlugin({\n getClientBundle: () => getBundle(VITE_ENVIRONMENT_NAMES.client),\n getConfig,\n }),\n devServerPlugin({ getConfig }),\n {\n name: 'tanstack-start:core:capture-bundle',\n applyToEnvironment(e) {\n return (\n e.name === VITE_ENVIRONMENT_NAMES.client ||\n e.name === VITE_ENVIRONMENT_NAMES.server\n )\n },\n enforce: 'post',\n generateBundle(_options, bundle) {\n const environment = this.environment.name as ViteEnvironmentNames\n if (!Object.values(VITE_ENVIRONMENT_NAMES).includes(environment)) {\n throw new Error(`Unknown environment: ${environment}`)\n }\n capturedBundle[environment] = bundle\n },\n },\n ]\n}\n\nfunction defineReplaceEnv<TKey extends string, TValue extends string>(\n key: TKey,\n value: TValue,\n): { [P in `process.env.${TKey}` | `import.meta.env.${TKey}`]: TValue } {\n return {\n [`process.env.${key}`]: JSON.stringify(value),\n [`import.meta.env.${key}`]: JSON.stringify(value),\n } as { [P in `process.env.${TKey}` | `import.meta.env.${TKey}`]: TValue }\n}\n"],"names":["startConfig"],"mappings":"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"}
@@ -2,7 +2,7 @@ import { existsSync, rmSync, promises } from "node:fs";
2
2
  import { pathToFileURL } from "node:url";
3
3
  import os from "node:os";
4
4
  import path from "pathe";
5
- import { withBase, joinURL, withoutBase } from "ufo";
5
+ import { joinURL, withBase, withoutBase } from "ufo";
6
6
  import { VITE_ENVIRONMENT_NAMES } from "./constants.js";
7
7
  import { createLogger } from "./utils.js";
8
8
  import { Queue } from "./queue.js";
@@ -79,6 +79,7 @@ async function prerender({
79
79
  const concurrency = startConfig.prerender?.concurrency ?? os.cpus().length;
80
80
  logger.info(`Concurrency: ${concurrency}`);
81
81
  const queue = new Queue({ concurrency });
82
+ const routerBasePath = joinURL("/", startConfig.router.basepath ?? "");
82
83
  startConfig.pages.forEach((page) => addCrawlPageTask(page));
83
84
  await queue.start();
84
85
  return Array.from(seen);
@@ -100,7 +101,7 @@ async function prerender({
100
101
  const retries = retriesByPath.get(page.path) || 0;
101
102
  try {
102
103
  const encodedRoute = encodeURI(page.path);
103
- const res = await localFetch(withBase(encodedRoute, TSS_APP_BASE), {
104
+ const res = await localFetch(withBase(encodedRoute, routerBasePath), {
104
105
  headers: {
105
106
  ...prerenderOptions.headers
106
107
  }
@@ -117,7 +118,7 @@ async function prerender({
117
118
  const htmlPath = cleanPagePath.endsWith("/") || prerenderOptions.autoSubfolderIndex ? joinURL(cleanPagePath, "index.html") : cleanPagePath + ".html";
118
119
  const filename = withoutBase(
119
120
  isImplicitHTML ? htmlPath : routeWithIndex,
120
- TSS_APP_BASE
121
+ routerBasePath
121
122
  );
122
123
  const html = await res.text();
123
124
  const filepath = path.join(outputDir2, filename);
@@ -1 +1 @@
1
- {"version":3,"file":"prerender.js","sources":["../../src/prerender.ts"],"sourcesContent":["import { existsSync, promises as fsp, rmSync } from 'node:fs'\nimport { pathToFileURL } from 'node:url'\nimport os from 'node:os'\nimport path from 'pathe'\nimport { joinURL, withBase, withoutBase } from 'ufo'\nimport { VITE_ENVIRONMENT_NAMES } from './constants'\nimport { createLogger } from './utils'\nimport { Queue } from './queue'\nimport type { Rollup, ViteBuilder } from 'vite'\nimport type { Page, TanStackStartOutputConfig } from './schema'\n\nexport async function prerender({\n startConfig,\n builder,\n serverBundle,\n}: {\n startConfig: TanStackStartOutputConfig\n builder: ViteBuilder\n serverBundle: Rollup.OutputBundle\n}) {\n const logger = createLogger('prerender')\n logger.info('Prerendering pages...')\n\n // If prerender is enabled but no pages are provided, default to prerendering the root page\n if (startConfig.prerender?.enabled && !startConfig.pages.length) {\n startConfig.pages = [\n {\n path: '/',\n },\n ]\n }\n\n const serverEnv = builder.environments[VITE_ENVIRONMENT_NAMES.server]\n\n if (!serverEnv) {\n throw new Error(\n `Vite's \"${VITE_ENVIRONMENT_NAMES.server}\" environment not found`,\n )\n }\n\n const clientEnv = builder.environments[VITE_ENVIRONMENT_NAMES.client]\n if (!clientEnv) {\n throw new Error(\n `Vite's \"${VITE_ENVIRONMENT_NAMES.client}\" environment not found`,\n )\n }\n\n const outputDir = clientEnv.config.build.outDir\n\n const entryFile = findEntryFileInBundle(serverBundle)\n let fullEntryFilePath = path.join(serverEnv.config.build.outDir, entryFile)\n process.env.TSS_PRERENDERING = 'true'\n\n if (!existsSync(fullEntryFilePath)) {\n // if the file does not exist, we need to write the bundle to a temporary directory\n // this can happen e.g. with nitro that postprocesses the bundle and thus does not write SSR build to disk\n const bundleOutputDir = path.resolve(\n serverEnv.config.root,\n '.tanstack',\n 'start',\n 'prerender',\n )\n rmSync(bundleOutputDir, { recursive: true, force: true })\n await writeBundleToDisk({ bundle: serverBundle, outDir: bundleOutputDir })\n fullEntryFilePath = path.join(bundleOutputDir, entryFile)\n }\n\n const { default: serverEntrypoint } = await import(\n pathToFileURL(fullEntryFilePath).toString()\n )\n\n function localFetch(path: string, options?: RequestInit): Promise<Response> {\n const url = new URL(`http://localhost${path}`)\n return serverEntrypoint.fetch(new Request(url, options))\n }\n\n try {\n // Crawl all pages\n const pages = await prerenderPages({ outputDir })\n\n logger.info(`Prerendered ${pages.length} pages:`)\n pages.forEach((page) => {\n logger.info(`- ${page}`)\n })\n } catch (error) {\n logger.error(error)\n }\n\n function extractLinks(html: string): Array<string> {\n const linkRegex = /<a[^>]+href=[\"']([^\"']+)[\"'][^>]*>/g\n const links: Array<string> = []\n let match\n\n while ((match = linkRegex.exec(html)) !== null) {\n const href = match[1]\n if (href && (href.startsWith('/') || href.startsWith('./'))) {\n links.push(href)\n }\n }\n\n return links\n }\n\n async function prerenderPages({ outputDir }: { outputDir: string }) {\n const seen = new Set<string>()\n const retriesByPath = new Map<string, number>()\n const concurrency = startConfig.prerender?.concurrency ?? os.cpus().length\n logger.info(`Concurrency: ${concurrency}`)\n const queue = new Queue({ concurrency })\n\n startConfig.pages.forEach((page) => addCrawlPageTask(page))\n\n await queue.start()\n\n return Array.from(seen)\n\n function addCrawlPageTask(page: Page) {\n // Was the page already seen?\n if (seen.has(page.path)) return\n\n // Add the page to the seen set\n seen.add(page.path)\n\n if (page.fromCrawl) {\n startConfig.pages.push(page)\n }\n\n // If not enabled, skip\n if (!(page.prerender?.enabled ?? true)) return\n\n // If there is a filter link, check if the page should be prerendered\n if (startConfig.prerender?.filter && !startConfig.prerender.filter(page))\n return\n\n // Resolve the merged default and page-specific prerender options\n const prerenderOptions = {\n ...startConfig.prerender,\n ...page.prerender,\n }\n\n // Add the task\n queue.add(async () => {\n logger.info(`Crawling: ${page.path}`)\n const retries = retriesByPath.get(page.path) || 0\n try {\n // Fetch the route\n const encodedRoute = encodeURI(page.path)\n\n const res = await localFetch(withBase(encodedRoute, TSS_APP_BASE), {\n headers: {\n ...prerenderOptions.headers,\n },\n })\n\n if (!res.ok) {\n throw new Error(`Failed to fetch ${page.path}: ${res.statusText}`, {\n cause: res,\n })\n }\n\n const cleanPagePath = (\n prerenderOptions.outputPath || page.path\n ).split(/[?#]/)[0]!\n\n // Guess route type and populate fileName\n const contentType = res.headers.get('content-type') || ''\n const isImplicitHTML =\n !cleanPagePath.endsWith('.html') && contentType.includes('html')\n // &&\n // !JsonSigRx.test(dataBuff.subarray(0, 32).toString('utf8'))\n const routeWithIndex = cleanPagePath.endsWith('/')\n ? cleanPagePath + 'index'\n : cleanPagePath\n\n const htmlPath =\n cleanPagePath.endsWith('/') || prerenderOptions.autoSubfolderIndex\n ? joinURL(cleanPagePath, 'index.html')\n : cleanPagePath + '.html'\n\n const filename = withoutBase(\n isImplicitHTML ? htmlPath : routeWithIndex,\n TSS_APP_BASE,\n )\n\n const html = await res.text()\n\n const filepath = path.join(outputDir, filename)\n\n await fsp.mkdir(path.dirname(filepath), {\n recursive: true,\n })\n\n await fsp.writeFile(filepath, html)\n\n const newPage = await prerenderOptions.onSuccess?.({ page, html })\n\n if (newPage) {\n Object.assign(page, newPage)\n }\n\n // Find new links\n if (prerenderOptions.crawlLinks ?? true) {\n const links = extractLinks(html)\n for (const link of links) {\n addCrawlPageTask({ path: link, fromCrawl: true })\n }\n }\n } catch (error) {\n if (retries < (prerenderOptions.retryCount ?? 0)) {\n logger.warn(`Encountered error, retrying: ${page.path} in 500ms`)\n await new Promise((resolve) =>\n setTimeout(resolve, prerenderOptions.retryDelay),\n )\n retriesByPath.set(page.path, retries + 1)\n addCrawlPageTask(page)\n } else {\n if (prerenderOptions.failOnError ?? true) {\n throw error\n }\n }\n }\n })\n }\n }\n}\n\nfunction findEntryFileInBundle(bundle: Rollup.OutputBundle): string {\n let entryFile: string | undefined\n\n for (const [_name, file] of Object.entries(bundle)) {\n if (file.type === 'chunk') {\n if (file.isEntry) {\n if (entryFile !== undefined) {\n throw new Error(\n `Multiple entry points found. Only one entry point is allowed.`,\n )\n }\n entryFile = file.fileName\n }\n }\n }\n if (entryFile === undefined) {\n throw new Error(`No entry point found in the bundle.`)\n }\n return entryFile\n}\n\nexport async function writeBundleToDisk({\n bundle,\n outDir,\n}: {\n bundle: Rollup.OutputBundle\n outDir: string\n}) {\n for (const [fileName, asset] of Object.entries(bundle)) {\n const fullPath = path.join(outDir, fileName)\n const content = asset.type === 'asset' ? asset.source : asset.code\n await fsp.mkdir(path.dirname(fullPath), { recursive: true })\n await fsp.writeFile(fullPath, content)\n }\n}\n"],"names":["path","outputDir","fsp"],"mappings":"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"}
1
+ {"version":3,"file":"prerender.js","sources":["../../src/prerender.ts"],"sourcesContent":["import { existsSync, promises as fsp, rmSync } from 'node:fs'\nimport { pathToFileURL } from 'node:url'\nimport os from 'node:os'\nimport path from 'pathe'\nimport { joinURL, withBase, withoutBase } from 'ufo'\nimport { VITE_ENVIRONMENT_NAMES } from './constants'\nimport { createLogger } from './utils'\nimport { Queue } from './queue'\nimport type { Rollup, ViteBuilder } from 'vite'\nimport type { Page, TanStackStartOutputConfig } from './schema'\n\nexport async function prerender({\n startConfig,\n builder,\n serverBundle,\n}: {\n startConfig: TanStackStartOutputConfig\n builder: ViteBuilder\n serverBundle: Rollup.OutputBundle\n}) {\n const logger = createLogger('prerender')\n logger.info('Prerendering pages...')\n\n // If prerender is enabled but no pages are provided, default to prerendering the root page\n if (startConfig.prerender?.enabled && !startConfig.pages.length) {\n startConfig.pages = [\n {\n path: '/',\n },\n ]\n }\n\n const serverEnv = builder.environments[VITE_ENVIRONMENT_NAMES.server]\n\n if (!serverEnv) {\n throw new Error(\n `Vite's \"${VITE_ENVIRONMENT_NAMES.server}\" environment not found`,\n )\n }\n\n const clientEnv = builder.environments[VITE_ENVIRONMENT_NAMES.client]\n if (!clientEnv) {\n throw new Error(\n `Vite's \"${VITE_ENVIRONMENT_NAMES.client}\" environment not found`,\n )\n }\n\n const outputDir = clientEnv.config.build.outDir\n\n const entryFile = findEntryFileInBundle(serverBundle)\n let fullEntryFilePath = path.join(serverEnv.config.build.outDir, entryFile)\n process.env.TSS_PRERENDERING = 'true'\n\n if (!existsSync(fullEntryFilePath)) {\n // if the file does not exist, we need to write the bundle to a temporary directory\n // this can happen e.g. with nitro that postprocesses the bundle and thus does not write SSR build to disk\n const bundleOutputDir = path.resolve(\n serverEnv.config.root,\n '.tanstack',\n 'start',\n 'prerender',\n )\n rmSync(bundleOutputDir, { recursive: true, force: true })\n await writeBundleToDisk({ bundle: serverBundle, outDir: bundleOutputDir })\n fullEntryFilePath = path.join(bundleOutputDir, entryFile)\n }\n\n const { default: serverEntrypoint } = await import(\n pathToFileURL(fullEntryFilePath).toString()\n )\n\n function localFetch(path: string, options?: RequestInit): Promise<Response> {\n const url = new URL(`http://localhost${path}`)\n return serverEntrypoint.fetch(new Request(url, options))\n }\n\n try {\n // Crawl all pages\n const pages = await prerenderPages({ outputDir })\n\n logger.info(`Prerendered ${pages.length} pages:`)\n pages.forEach((page) => {\n logger.info(`- ${page}`)\n })\n } catch (error) {\n logger.error(error)\n }\n\n function extractLinks(html: string): Array<string> {\n const linkRegex = /<a[^>]+href=[\"']([^\"']+)[\"'][^>]*>/g\n const links: Array<string> = []\n let match\n\n while ((match = linkRegex.exec(html)) !== null) {\n const href = match[1]\n if (href && (href.startsWith('/') || href.startsWith('./'))) {\n links.push(href)\n }\n }\n\n return links\n }\n\n async function prerenderPages({ outputDir }: { outputDir: string }) {\n const seen = new Set<string>()\n const retriesByPath = new Map<string, number>()\n const concurrency = startConfig.prerender?.concurrency ?? os.cpus().length\n logger.info(`Concurrency: ${concurrency}`)\n const queue = new Queue({ concurrency })\n const routerBasePath = joinURL('/', startConfig.router.basepath ?? '')\n\n startConfig.pages.forEach((page) => addCrawlPageTask(page))\n\n await queue.start()\n\n return Array.from(seen)\n\n function addCrawlPageTask(page: Page) {\n // Was the page already seen?\n if (seen.has(page.path)) return\n\n // Add the page to the seen set\n seen.add(page.path)\n\n if (page.fromCrawl) {\n startConfig.pages.push(page)\n }\n\n // If not enabled, skip\n if (!(page.prerender?.enabled ?? true)) return\n\n // If there is a filter link, check if the page should be prerendered\n if (startConfig.prerender?.filter && !startConfig.prerender.filter(page))\n return\n\n // Resolve the merged default and page-specific prerender options\n const prerenderOptions = {\n ...startConfig.prerender,\n ...page.prerender,\n }\n\n // Add the task\n queue.add(async () => {\n logger.info(`Crawling: ${page.path}`)\n const retries = retriesByPath.get(page.path) || 0\n try {\n // Fetch the route\n const encodedRoute = encodeURI(page.path)\n\n const res = await localFetch(withBase(encodedRoute, routerBasePath), {\n headers: {\n ...prerenderOptions.headers,\n },\n })\n\n if (!res.ok) {\n throw new Error(`Failed to fetch ${page.path}: ${res.statusText}`, {\n cause: res,\n })\n }\n\n const cleanPagePath = (\n prerenderOptions.outputPath || page.path\n ).split(/[?#]/)[0]!\n\n // Guess route type and populate fileName\n const contentType = res.headers.get('content-type') || ''\n const isImplicitHTML =\n !cleanPagePath.endsWith('.html') && contentType.includes('html')\n // &&\n // !JsonSigRx.test(dataBuff.subarray(0, 32).toString('utf8'))\n const routeWithIndex = cleanPagePath.endsWith('/')\n ? cleanPagePath + 'index'\n : cleanPagePath\n\n const htmlPath =\n cleanPagePath.endsWith('/') || prerenderOptions.autoSubfolderIndex\n ? joinURL(cleanPagePath, 'index.html')\n : cleanPagePath + '.html'\n\n const filename = withoutBase(\n isImplicitHTML ? htmlPath : routeWithIndex,\n routerBasePath,\n )\n\n const html = await res.text()\n\n const filepath = path.join(outputDir, filename)\n\n await fsp.mkdir(path.dirname(filepath), {\n recursive: true,\n })\n\n await fsp.writeFile(filepath, html)\n\n const newPage = await prerenderOptions.onSuccess?.({ page, html })\n\n if (newPage) {\n Object.assign(page, newPage)\n }\n\n // Find new links\n if (prerenderOptions.crawlLinks ?? true) {\n const links = extractLinks(html)\n for (const link of links) {\n addCrawlPageTask({ path: link, fromCrawl: true })\n }\n }\n } catch (error) {\n if (retries < (prerenderOptions.retryCount ?? 0)) {\n logger.warn(`Encountered error, retrying: ${page.path} in 500ms`)\n await new Promise((resolve) =>\n setTimeout(resolve, prerenderOptions.retryDelay),\n )\n retriesByPath.set(page.path, retries + 1)\n addCrawlPageTask(page)\n } else {\n if (prerenderOptions.failOnError ?? true) {\n throw error\n }\n }\n }\n })\n }\n }\n}\n\nfunction findEntryFileInBundle(bundle: Rollup.OutputBundle): string {\n let entryFile: string | undefined\n\n for (const [_name, file] of Object.entries(bundle)) {\n if (file.type === 'chunk') {\n if (file.isEntry) {\n if (entryFile !== undefined) {\n throw new Error(\n `Multiple entry points found. Only one entry point is allowed.`,\n )\n }\n entryFile = file.fileName\n }\n }\n }\n if (entryFile === undefined) {\n throw new Error(`No entry point found in the bundle.`)\n }\n return entryFile\n}\n\nexport async function writeBundleToDisk({\n bundle,\n outDir,\n}: {\n bundle: Rollup.OutputBundle\n outDir: string\n}) {\n for (const [fileName, asset] of Object.entries(bundle)) {\n const fullPath = path.join(outDir, fileName)\n const content = asset.type === 'asset' ? asset.source : asset.code\n await fsp.mkdir(path.dirname(fullPath), { recursive: true })\n await fsp.writeFile(fullPath, content)\n }\n}\n"],"names":["path","outputDir","fsp"],"mappings":";;;;;;;;AAWA,eAAsB,UAAU;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,SAAS,aAAa,WAAW;AACvC,SAAO,KAAK,uBAAuB;AAGnC,MAAI,YAAY,WAAW,WAAW,CAAC,YAAY,MAAM,QAAQ;AAC/D,gBAAY,QAAQ;AAAA,MAClB;AAAA,QACE,MAAM;AAAA,MAAA;AAAA,IACR;AAAA,EAEJ;AAEA,QAAM,YAAY,QAAQ,aAAa,uBAAuB,MAAM;AAEpE,MAAI,CAAC,WAAW;AACd,UAAM,IAAI;AAAA,MACR,WAAW,uBAAuB,MAAM;AAAA,IAAA;AAAA,EAE5C;AAEA,QAAM,YAAY,QAAQ,aAAa,uBAAuB,MAAM;AACpE,MAAI,CAAC,WAAW;AACd,UAAM,IAAI;AAAA,MACR,WAAW,uBAAuB,MAAM;AAAA,IAAA;AAAA,EAE5C;AAEA,QAAM,YAAY,UAAU,OAAO,MAAM;AAEzC,QAAM,YAAY,sBAAsB,YAAY;AACpD,MAAI,oBAAoB,KAAK,KAAK,UAAU,OAAO,MAAM,QAAQ,SAAS;AAC1E,UAAQ,IAAI,mBAAmB;AAE/B,MAAI,CAAC,WAAW,iBAAiB,GAAG;AAGlC,UAAM,kBAAkB,KAAK;AAAA,MAC3B,UAAU,OAAO;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAEF,WAAO,iBAAiB,EAAE,WAAW,MAAM,OAAO,MAAM;AACxD,UAAM,kBAAkB,EAAE,QAAQ,cAAc,QAAQ,iBAAiB;AACzE,wBAAoB,KAAK,KAAK,iBAAiB,SAAS;AAAA,EAC1D;AAEA,QAAM,EAAE,SAAS,qBAAqB,MAAM,OAC1C,cAAc,iBAAiB,EAAE;AAGnC,WAAS,WAAWA,OAAc,SAA0C;AAC1E,UAAM,MAAM,IAAI,IAAI,mBAAmBA,KAAI,EAAE;AAC7C,WAAO,iBAAiB,MAAM,IAAI,QAAQ,KAAK,OAAO,CAAC;AAAA,EACzD;AAEA,MAAI;AAEF,UAAM,QAAQ,MAAM,eAAe,EAAE,WAAW;AAEhD,WAAO,KAAK,eAAe,MAAM,MAAM,SAAS;AAChD,UAAM,QAAQ,CAAC,SAAS;AACtB,aAAO,KAAK,KAAK,IAAI,EAAE;AAAA,IACzB,CAAC;AAAA,EACH,SAAS,OAAO;AACd,WAAO,MAAM,KAAK;AAAA,EACpB;AAEA,WAAS,aAAa,MAA6B;AACjD,UAAM,YAAY;AAClB,UAAM,QAAuB,CAAA;AAC7B,QAAI;AAEJ,YAAQ,QAAQ,UAAU,KAAK,IAAI,OAAO,MAAM;AAC9C,YAAM,OAAO,MAAM,CAAC;AACpB,UAAI,SAAS,KAAK,WAAW,GAAG,KAAK,KAAK,WAAW,IAAI,IAAI;AAC3D,cAAM,KAAK,IAAI;AAAA,MACjB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,iBAAe,eAAe,EAAE,WAAAC,cAAoC;AAClE,UAAM,2BAAW,IAAA;AACjB,UAAM,oCAAoB,IAAA;AAC1B,UAAM,cAAc,YAAY,WAAW,eAAe,GAAG,OAAO;AACpE,WAAO,KAAK,gBAAgB,WAAW,EAAE;AACzC,UAAM,QAAQ,IAAI,MAAM,EAAE,aAAa;AACvC,UAAM,iBAAiB,QAAQ,KAAK,YAAY,OAAO,YAAY,EAAE;AAErE,gBAAY,MAAM,QAAQ,CAAC,SAAS,iBAAiB,IAAI,CAAC;AAE1D,UAAM,MAAM,MAAA;AAEZ,WAAO,MAAM,KAAK,IAAI;AAEtB,aAAS,iBAAiB,MAAY;AAEpC,UAAI,KAAK,IAAI,KAAK,IAAI,EAAG;AAGzB,WAAK,IAAI,KAAK,IAAI;AAElB,UAAI,KAAK,WAAW;AAClB,oBAAY,MAAM,KAAK,IAAI;AAAA,MAC7B;AAGA,UAAI,EAAE,KAAK,WAAW,WAAW,MAAO;AAGxC,UAAI,YAAY,WAAW,UAAU,CAAC,YAAY,UAAU,OAAO,IAAI;AACrE;AAGF,YAAM,mBAAmB;AAAA,QACvB,GAAG,YAAY;AAAA,QACf,GAAG,KAAK;AAAA,MAAA;AAIV,YAAM,IAAI,YAAY;AACpB,eAAO,KAAK,aAAa,KAAK,IAAI,EAAE;AACpC,cAAM,UAAU,cAAc,IAAI,KAAK,IAAI,KAAK;AAChD,YAAI;AAEF,gBAAM,eAAe,UAAU,KAAK,IAAI;AAExC,gBAAM,MAAM,MAAM,WAAW,SAAS,cAAc,cAAc,GAAG;AAAA,YACnE,SAAS;AAAA,cACP,GAAG,iBAAiB;AAAA,YAAA;AAAA,UACtB,CACD;AAED,cAAI,CAAC,IAAI,IAAI;AACX,kBAAM,IAAI,MAAM,mBAAmB,KAAK,IAAI,KAAK,IAAI,UAAU,IAAI;AAAA,cACjE,OAAO;AAAA,YAAA,CACR;AAAA,UACH;AAEA,gBAAM,iBACJ,iBAAiB,cAAc,KAAK,MACpC,MAAM,MAAM,EAAE,CAAC;AAGjB,gBAAM,cAAc,IAAI,QAAQ,IAAI,cAAc,KAAK;AACvD,gBAAM,iBACJ,CAAC,cAAc,SAAS,OAAO,KAAK,YAAY,SAAS,MAAM;AAGjE,gBAAM,iBAAiB,cAAc,SAAS,GAAG,IAC7C,gBAAgB,UAChB;AAEJ,gBAAM,WACJ,cAAc,SAAS,GAAG,KAAK,iBAAiB,qBAC5C,QAAQ,eAAe,YAAY,IACnC,gBAAgB;AAEtB,gBAAM,WAAW;AAAA,YACf,iBAAiB,WAAW;AAAA,YAC5B;AAAA,UAAA;AAGF,gBAAM,OAAO,MAAM,IAAI,KAAA;AAEvB,gBAAM,WAAW,KAAK,KAAKA,YAAW,QAAQ;AAE9C,gBAAMC,SAAI,MAAM,KAAK,QAAQ,QAAQ,GAAG;AAAA,YACtC,WAAW;AAAA,UAAA,CACZ;AAED,gBAAMA,SAAI,UAAU,UAAU,IAAI;AAElC,gBAAM,UAAU,MAAM,iBAAiB,YAAY,EAAE,MAAM,MAAM;AAEjE,cAAI,SAAS;AACX,mBAAO,OAAO,MAAM,OAAO;AAAA,UAC7B;AAGA,cAAI,iBAAiB,cAAc,MAAM;AACvC,kBAAM,QAAQ,aAAa,IAAI;AAC/B,uBAAW,QAAQ,OAAO;AACxB,+BAAiB,EAAE,MAAM,MAAM,WAAW,MAAM;AAAA,YAClD;AAAA,UACF;AAAA,QACF,SAAS,OAAO;AACd,cAAI,WAAW,iBAAiB,cAAc,IAAI;AAChD,mBAAO,KAAK,gCAAgC,KAAK,IAAI,WAAW;AAChE,kBAAM,IAAI;AAAA,cAAQ,CAAC,YACjB,WAAW,SAAS,iBAAiB,UAAU;AAAA,YAAA;AAEjD,0BAAc,IAAI,KAAK,MAAM,UAAU,CAAC;AACxC,6BAAiB,IAAI;AAAA,UACvB,OAAO;AACL,gBAAI,iBAAiB,eAAe,MAAM;AACxC,oBAAM;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,SAAS,sBAAsB,QAAqC;AAClE,MAAI;AAEJ,aAAW,CAAC,OAAO,IAAI,KAAK,OAAO,QAAQ,MAAM,GAAG;AAClD,QAAI,KAAK,SAAS,SAAS;AACzB,UAAI,KAAK,SAAS;AAChB,YAAI,cAAc,QAAW;AAC3B,gBAAM,IAAI;AAAA,YACR;AAAA,UAAA;AAAA,QAEJ;AACA,oBAAY,KAAK;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AACA,MAAI,cAAc,QAAW;AAC3B,UAAM,IAAI,MAAM,qCAAqC;AAAA,EACvD;AACA,SAAO;AACT;AAEA,eAAsB,kBAAkB;AAAA,EACtC;AAAA,EACA;AACF,GAGG;AACD,aAAW,CAAC,UAAU,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACtD,UAAM,WAAW,KAAK,KAAK,QAAQ,QAAQ;AAC3C,UAAM,UAAU,MAAM,SAAS,UAAU,MAAM,SAAS,MAAM;AAC9D,UAAMA,SAAI,MAAM,KAAK,QAAQ,QAAQ,GAAG,EAAE,WAAW,MAAM;AAC3D,UAAMA,SAAI,UAAU,UAAU,OAAO;AAAA,EACvC;AACF;"}
@@ -40,6 +40,7 @@ export declare function parseStartConfig(opts: z.input<typeof tanstackStartOptio
40
40
  } | undefined;
41
41
  plugins?: import('@tanstack/router-generator').GeneratorPlugin[] | undefined;
42
42
  entry?: string | undefined;
43
+ basepath?: string | undefined;
43
44
  };
44
45
  client: {
45
46
  base: string;
@@ -836,10 +837,13 @@ declare const tanstackStartOptionsSchema: z.ZodDefault<z.ZodOptional<z.ZodObject
836
837
  }>>>;
837
838
  router: z.ZodDefault<z.ZodOptional<z.ZodIntersection<z.ZodObject<{
838
839
  entry: z.ZodOptional<z.ZodString>;
840
+ basepath: z.ZodOptional<z.ZodString>;
839
841
  }, "strip", z.ZodTypeAny, {
840
842
  entry?: string | undefined;
843
+ basepath?: string | undefined;
841
844
  }, {
842
845
  entry?: string | undefined;
846
+ basepath?: string | undefined;
843
847
  }>, z.ZodDefault<z.ZodOptional<z.ZodObject<{
844
848
  plugins: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodType<import('@tanstack/router-generator').GeneratorPlugin, z.ZodTypeDef, import('@tanstack/router-generator').GeneratorPlugin>, "many">>>;
845
849
  experimental: z.ZodOptional<z.ZodOptional<z.ZodObject<{
@@ -3032,6 +3036,7 @@ declare const tanstackStartOptionsSchema: z.ZodDefault<z.ZodOptional<z.ZodObject
3032
3036
  srcDirectory: string;
3033
3037
  router: {
3034
3038
  entry?: string | undefined;
3039
+ basepath?: string | undefined;
3035
3040
  } & {
3036
3041
  plugins?: import('@tanstack/router-generator').GeneratorPlugin[] | undefined;
3037
3042
  experimental?: {
@@ -3358,6 +3363,7 @@ declare const tanstackStartOptionsSchema: z.ZodDefault<z.ZodOptional<z.ZodObject
3358
3363
  srcDirectory?: string | undefined;
3359
3364
  router?: ({
3360
3365
  entry?: string | undefined;
3366
+ basepath?: string | undefined;
3361
3367
  } & {
3362
3368
  plugins?: import('@tanstack/router-generator').GeneratorPlugin[] | undefined;
3363
3369
  experimental?: {
@@ -98,7 +98,8 @@ const tanstackStartOptionsSchema = z.object({
98
98
  entry: z.string().optional()
99
99
  }).optional().default({}),
100
100
  router: z.object({
101
- entry: z.string().optional()
101
+ entry: z.string().optional(),
102
+ basepath: z.string().optional()
102
103
  }).and(tsrConfig.optional().default({})).optional().default({}),
103
104
  client: z.object({
104
105
  entry: z.string().optional(),
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sources":["../../src/schema.ts"],"sourcesContent":["import path from 'node:path'\nimport { z } from 'zod'\nimport { configSchema, getConfig } from '@tanstack/router-plugin'\nimport type { TanStackStartVitePluginCoreOptions } from './plugin'\n\nconst tsrConfig = configSchema\n .omit({ autoCodeSplitting: true, target: true, verboseFileRoutes: true })\n .partial()\n\nexport function parseStartConfig(\n opts: z.input<typeof tanstackStartOptionsSchema>,\n corePluginOpts: TanStackStartVitePluginCoreOptions,\n root: string,\n) {\n const options = tanstackStartOptionsSchema.parse(opts)\n\n const srcDirectory = options.srcDirectory\n\n const routesDirectory = path.resolve(\n root,\n srcDirectory,\n options.router.routesDirectory ?? 'routes',\n )\n\n const generatedRouteTree = path.resolve(\n root,\n srcDirectory,\n options.router.generatedRouteTree ?? 'routeTree.gen.ts',\n )\n\n return {\n ...options,\n router: {\n ...options.router,\n ...getConfig(\n {\n ...options.router,\n routesDirectory,\n generatedRouteTree,\n },\n root,\n ),\n target: corePluginOpts.framework,\n },\n }\n}\n\nconst pageSitemapOptionsSchema = z.object({\n exclude: z.boolean().optional(),\n priority: z.number().min(0).max(1).optional(),\n changefreq: z\n .enum(['always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'])\n .optional(),\n lastmod: z.union([z.string(), z.date()]).optional(),\n alternateRefs: z\n .array(\n z.object({\n href: z.string(),\n hreflang: z.string(),\n }),\n )\n .optional(),\n images: z\n .array(\n z.object({\n loc: z.string(),\n caption: z.string().optional(),\n title: z.string().optional(),\n }),\n )\n .optional(),\n news: z\n .object({\n publication: z.object({\n name: z.string(),\n language: z.string(),\n }),\n publicationDate: z.union([z.string(), z.date()]),\n title: z.string(),\n })\n .optional(),\n})\n\nconst pageBaseSchema = z.object({\n path: z.string(),\n sitemap: pageSitemapOptionsSchema.optional(),\n fromCrawl: z.boolean().optional(),\n})\n\nconst pagePrerenderOptionsSchema = z.object({\n enabled: z.boolean().optional(),\n outputPath: z.string().optional(),\n autoSubfolderIndex: z.boolean().optional(),\n crawlLinks: z.boolean().optional(),\n retryCount: z.number().optional(),\n retryDelay: z.number().optional(),\n onSuccess: z\n .function()\n .args(\n z.object({\n page: pageBaseSchema,\n html: z.string(),\n }),\n )\n .returns(z.any())\n .optional(),\n headers: z.record(z.string(), z.string()).optional(),\n})\n\nconst spaSchema = z.object({\n enabled: z.boolean().optional().default(true),\n maskPath: z.string().optional().default('/'),\n prerender: pagePrerenderOptionsSchema\n .optional()\n .default({})\n .transform((opts) => ({\n outputPath: opts.outputPath ?? '/_shell',\n crawlLinks: false,\n retryCount: 0,\n ...opts,\n enabled: true,\n })),\n})\n\nconst pageSchema = pageBaseSchema.extend({\n prerender: pagePrerenderOptionsSchema.optional(),\n})\n\nconst tanstackStartOptionsSchema = z\n .object({\n srcDirectory: z.string().optional().default('src'),\n start: z\n .object({\n entry: z.string().optional(),\n })\n .optional()\n .default({}),\n router: z\n .object({\n entry: z.string().optional(),\n })\n .and(tsrConfig.optional().default({}))\n .optional()\n .default({}),\n client: z\n .object({\n entry: z.string().optional(),\n base: z.string().optional().default('/_build'),\n })\n .optional()\n .default({}),\n server: z\n .object({\n entry: z.string().optional(),\n })\n .optional()\n .default({}),\n serverFns: z\n .object({\n base: z.string().optional().default('/_serverFn'),\n })\n .optional()\n .default({}),\n public: z\n .object({\n dir: z.string().optional().default('public'),\n base: z.string().optional().default('/'),\n })\n .optional()\n .default({}),\n pages: z.array(pageSchema).optional().default([]),\n sitemap: z\n .object({\n enabled: z.boolean().optional().default(true),\n host: z.string().optional(),\n outputPath: z.string().optional().default('sitemap.xml'),\n })\n .optional(),\n prerender: z\n .object({\n enabled: z.boolean().optional(),\n concurrency: z.number().optional(),\n filter: z.function().args(pageSchema).returns(z.any()).optional(),\n failOnError: z.boolean().optional(),\n })\n .and(pagePrerenderOptionsSchema.optional())\n .optional(),\n spa: spaSchema.optional(),\n vite: z\n .object({ installDevServerMiddleware: z.boolean().optional() })\n .optional(),\n })\n .optional()\n .default({})\n\nexport type Page = z.infer<typeof pageSchema>\n\nexport type TanStackStartInputConfig = z.input<\n typeof tanstackStartOptionsSchema\n>\nexport type TanStackStartOutputConfig = ReturnType<typeof parseStartConfig>\n"],"names":[],"mappings":";;;AAKA,MAAM,YAAY,aACf,KAAK,EAAE,mBAAmB,MAAM,QAAQ,MAAM,mBAAmB,KAAA,CAAM,EACvE,QAAA;AAEI,SAAS,iBACd,MACA,gBACA,MACA;AACA,QAAM,UAAU,2BAA2B,MAAM,IAAI;AAErD,QAAM,eAAe,QAAQ;AAE7B,QAAM,kBAAkB,KAAK;AAAA,IAC3B;AAAA,IACA;AAAA,IACA,QAAQ,OAAO,mBAAmB;AAAA,EAAA;AAGpC,QAAM,qBAAqB,KAAK;AAAA,IAC9B;AAAA,IACA;AAAA,IACA,QAAQ,OAAO,sBAAsB;AAAA,EAAA;AAGvC,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QAAQ;AAAA,MACN,GAAG,QAAQ;AAAA,MACX,GAAG;AAAA,QACD;AAAA,UACE,GAAG,QAAQ;AAAA,UACX;AAAA,UACA;AAAA,QAAA;AAAA,QAEF;AAAA,MAAA;AAAA,MAEF,QAAQ,eAAe;AAAA,IAAA;AAAA,EACzB;AAEJ;AAEA,MAAM,2BAA2B,EAAE,OAAO;AAAA,EACxC,SAAS,EAAE,QAAA,EAAU,SAAA;AAAA,EACrB,UAAU,EAAE,OAAA,EAAS,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,SAAA;AAAA,EACnC,YAAY,EACT,KAAK,CAAC,UAAU,UAAU,SAAS,UAAU,WAAW,UAAU,OAAO,CAAC,EAC1E,SAAA;AAAA,EACH,SAAS,EAAE,MAAM,CAAC,EAAE,UAAU,EAAE,KAAA,CAAM,CAAC,EAAE,SAAA;AAAA,EACzC,eAAe,EACZ;AAAA,IACC,EAAE,OAAO;AAAA,MACP,MAAM,EAAE,OAAA;AAAA,MACR,UAAU,EAAE,OAAA;AAAA,IAAO,CACpB;AAAA,EAAA,EAEF,SAAA;AAAA,EACH,QAAQ,EACL;AAAA,IACC,EAAE,OAAO;AAAA,MACP,KAAK,EAAE,OAAA;AAAA,MACP,SAAS,EAAE,OAAA,EAAS,SAAA;AAAA,MACpB,OAAO,EAAE,OAAA,EAAS,SAAA;AAAA,IAAS,CAC5B;AAAA,EAAA,EAEF,SAAA;AAAA,EACH,MAAM,EACH,OAAO;AAAA,IACN,aAAa,EAAE,OAAO;AAAA,MACpB,MAAM,EAAE,OAAA;AAAA,MACR,UAAU,EAAE,OAAA;AAAA,IAAO,CACpB;AAAA,IACD,iBAAiB,EAAE,MAAM,CAAC,EAAE,UAAU,EAAE,KAAA,CAAM,CAAC;AAAA,IAC/C,OAAO,EAAE,OAAA;AAAA,EAAO,CACjB,EACA,SAAA;AACL,CAAC;AAED,MAAM,iBAAiB,EAAE,OAAO;AAAA,EAC9B,MAAM,EAAE,OAAA;AAAA,EACR,SAAS,yBAAyB,SAAA;AAAA,EAClC,WAAW,EAAE,QAAA,EAAU,SAAA;AACzB,CAAC;AAED,MAAM,6BAA6B,EAAE,OAAO;AAAA,EAC1C,SAAS,EAAE,QAAA,EAAU,SAAA;AAAA,EACrB,YAAY,EAAE,OAAA,EAAS,SAAA;AAAA,EACvB,oBAAoB,EAAE,QAAA,EAAU,SAAA;AAAA,EAChC,YAAY,EAAE,QAAA,EAAU,SAAA;AAAA,EACxB,YAAY,EAAE,OAAA,EAAS,SAAA;AAAA,EACvB,YAAY,EAAE,OAAA,EAAS,SAAA;AAAA,EACvB,WAAW,EACR,SAAA,EACA;AAAA,IACC,EAAE,OAAO;AAAA,MACP,MAAM;AAAA,MACN,MAAM,EAAE,OAAA;AAAA,IAAO,CAChB;AAAA,EAAA,EAEF,QAAQ,EAAE,IAAA,CAAK,EACf,SAAA;AAAA,EACH,SAAS,EAAE,OAAO,EAAE,OAAA,GAAU,EAAE,OAAA,CAAQ,EAAE,SAAA;AAC5C,CAAC;AAED,MAAM,YAAY,EAAE,OAAO;AAAA,EACzB,SAAS,EAAE,QAAA,EAAU,SAAA,EAAW,QAAQ,IAAI;AAAA,EAC5C,UAAU,EAAE,OAAA,EAAS,SAAA,EAAW,QAAQ,GAAG;AAAA,EAC3C,WAAW,2BACR,WACA,QAAQ,CAAA,CAAE,EACV,UAAU,CAAC,UAAU;AAAA,IACpB,YAAY,KAAK,cAAc;AAAA,IAC/B,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,GAAG;AAAA,IACH,SAAS;AAAA,EAAA,EACT;AACN,CAAC;AAED,MAAM,aAAa,eAAe,OAAO;AAAA,EACvC,WAAW,2BAA2B,SAAA;AACxC,CAAC;AAED,MAAM,6BAA6B,EAChC,OAAO;AAAA,EACN,cAAc,EAAE,OAAA,EAAS,SAAA,EAAW,QAAQ,KAAK;AAAA,EACjD,OAAO,EACJ,OAAO;AAAA,IACN,OAAO,EAAE,OAAA,EAAS,SAAA;AAAA,EAAS,CAC5B,EACA,SAAA,EACA,QAAQ,EAAE;AAAA,EACb,QAAQ,EACL,OAAO;AAAA,IACN,OAAO,EAAE,OAAA,EAAS,SAAA;AAAA,EAAS,CAC5B,EACA,IAAI,UAAU,WAAW,QAAQ,CAAA,CAAE,CAAC,EACpC,WACA,QAAQ,CAAA,CAAE;AAAA,EACb,QAAQ,EACL,OAAO;AAAA,IACN,OAAO,EAAE,OAAA,EAAS,SAAA;AAAA,IAClB,MAAM,EAAE,OAAA,EAAS,SAAA,EAAW,QAAQ,SAAS;AAAA,EAAA,CAC9C,EACA,SAAA,EACA,QAAQ,EAAE;AAAA,EACb,QAAQ,EACL,OAAO;AAAA,IACN,OAAO,EAAE,OAAA,EAAS,SAAA;AAAA,EAAS,CAC5B,EACA,SAAA,EACA,QAAQ,EAAE;AAAA,EACb,WAAW,EACR,OAAO;AAAA,IACN,MAAM,EAAE,OAAA,EAAS,SAAA,EAAW,QAAQ,YAAY;AAAA,EAAA,CACjD,EACA,SAAA,EACA,QAAQ,EAAE;AAAA,EACb,QAAQ,EACL,OAAO;AAAA,IACN,KAAK,EAAE,OAAA,EAAS,SAAA,EAAW,QAAQ,QAAQ;AAAA,IAC3C,MAAM,EAAE,OAAA,EAAS,SAAA,EAAW,QAAQ,GAAG;AAAA,EAAA,CACxC,EACA,SAAA,EACA,QAAQ,EAAE;AAAA,EACb,OAAO,EAAE,MAAM,UAAU,EAAE,SAAA,EAAW,QAAQ,EAAE;AAAA,EAChD,SAAS,EACN,OAAO;AAAA,IACN,SAAS,EAAE,QAAA,EAAU,SAAA,EAAW,QAAQ,IAAI;AAAA,IAC5C,MAAM,EAAE,OAAA,EAAS,SAAA;AAAA,IACjB,YAAY,EAAE,OAAA,EAAS,SAAA,EAAW,QAAQ,aAAa;AAAA,EAAA,CACxD,EACA,SAAA;AAAA,EACH,WAAW,EACR,OAAO;AAAA,IACN,SAAS,EAAE,QAAA,EAAU,SAAA;AAAA,IACrB,aAAa,EAAE,OAAA,EAAS,SAAA;AAAA,IACxB,QAAQ,EAAE,SAAA,EAAW,KAAK,UAAU,EAAE,QAAQ,EAAE,IAAA,CAAK,EAAE,SAAA;AAAA,IACvD,aAAa,EAAE,QAAA,EAAU,SAAA;AAAA,EAAS,CACnC,EACA,IAAI,2BAA2B,SAAA,CAAU,EACzC,SAAA;AAAA,EACH,KAAK,UAAU,SAAA;AAAA,EACf,MAAM,EACH,OAAO,EAAE,4BAA4B,EAAE,UAAU,WAAS,CAAG,EAC7D,SAAA;AACL,CAAC,EACA,SAAA,EACA,QAAQ,EAAE;"}
1
+ {"version":3,"file":"schema.js","sources":["../../src/schema.ts"],"sourcesContent":["import path from 'node:path'\nimport { z } from 'zod'\nimport { configSchema, getConfig } from '@tanstack/router-plugin'\nimport type { TanStackStartVitePluginCoreOptions } from './plugin'\n\nconst tsrConfig = configSchema\n .omit({ autoCodeSplitting: true, target: true, verboseFileRoutes: true })\n .partial()\n\nexport function parseStartConfig(\n opts: z.input<typeof tanstackStartOptionsSchema>,\n corePluginOpts: TanStackStartVitePluginCoreOptions,\n root: string,\n) {\n const options = tanstackStartOptionsSchema.parse(opts)\n\n const srcDirectory = options.srcDirectory\n\n const routesDirectory = path.resolve(\n root,\n srcDirectory,\n options.router.routesDirectory ?? 'routes',\n )\n\n const generatedRouteTree = path.resolve(\n root,\n srcDirectory,\n options.router.generatedRouteTree ?? 'routeTree.gen.ts',\n )\n\n return {\n ...options,\n router: {\n ...options.router,\n ...getConfig(\n {\n ...options.router,\n routesDirectory,\n generatedRouteTree,\n },\n root,\n ),\n target: corePluginOpts.framework,\n },\n }\n}\n\nconst pageSitemapOptionsSchema = z.object({\n exclude: z.boolean().optional(),\n priority: z.number().min(0).max(1).optional(),\n changefreq: z\n .enum(['always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'])\n .optional(),\n lastmod: z.union([z.string(), z.date()]).optional(),\n alternateRefs: z\n .array(\n z.object({\n href: z.string(),\n hreflang: z.string(),\n }),\n )\n .optional(),\n images: z\n .array(\n z.object({\n loc: z.string(),\n caption: z.string().optional(),\n title: z.string().optional(),\n }),\n )\n .optional(),\n news: z\n .object({\n publication: z.object({\n name: z.string(),\n language: z.string(),\n }),\n publicationDate: z.union([z.string(), z.date()]),\n title: z.string(),\n })\n .optional(),\n})\n\nconst pageBaseSchema = z.object({\n path: z.string(),\n sitemap: pageSitemapOptionsSchema.optional(),\n fromCrawl: z.boolean().optional(),\n})\n\nconst pagePrerenderOptionsSchema = z.object({\n enabled: z.boolean().optional(),\n outputPath: z.string().optional(),\n autoSubfolderIndex: z.boolean().optional(),\n crawlLinks: z.boolean().optional(),\n retryCount: z.number().optional(),\n retryDelay: z.number().optional(),\n onSuccess: z\n .function()\n .args(\n z.object({\n page: pageBaseSchema,\n html: z.string(),\n }),\n )\n .returns(z.any())\n .optional(),\n headers: z.record(z.string(), z.string()).optional(),\n})\n\nconst spaSchema = z.object({\n enabled: z.boolean().optional().default(true),\n maskPath: z.string().optional().default('/'),\n prerender: pagePrerenderOptionsSchema\n .optional()\n .default({})\n .transform((opts) => ({\n outputPath: opts.outputPath ?? '/_shell',\n crawlLinks: false,\n retryCount: 0,\n ...opts,\n enabled: true,\n })),\n})\n\nconst pageSchema = pageBaseSchema.extend({\n prerender: pagePrerenderOptionsSchema.optional(),\n})\n\nconst tanstackStartOptionsSchema = z\n .object({\n srcDirectory: z.string().optional().default('src'),\n start: z\n .object({\n entry: z.string().optional(),\n })\n .optional()\n .default({}),\n router: z\n .object({\n entry: z.string().optional(),\n basepath: z.string().optional(),\n })\n .and(tsrConfig.optional().default({}))\n .optional()\n .default({}),\n client: z\n .object({\n entry: z.string().optional(),\n base: z.string().optional().default('/_build'),\n })\n .optional()\n .default({}),\n server: z\n .object({\n entry: z.string().optional(),\n })\n .optional()\n .default({}),\n serverFns: z\n .object({\n base: z.string().optional().default('/_serverFn'),\n })\n .optional()\n .default({}),\n public: z\n .object({\n dir: z.string().optional().default('public'),\n base: z.string().optional().default('/'),\n })\n .optional()\n .default({}),\n pages: z.array(pageSchema).optional().default([]),\n sitemap: z\n .object({\n enabled: z.boolean().optional().default(true),\n host: z.string().optional(),\n outputPath: z.string().optional().default('sitemap.xml'),\n })\n .optional(),\n prerender: z\n .object({\n enabled: z.boolean().optional(),\n concurrency: z.number().optional(),\n filter: z.function().args(pageSchema).returns(z.any()).optional(),\n failOnError: z.boolean().optional(),\n })\n .and(pagePrerenderOptionsSchema.optional())\n .optional(),\n spa: spaSchema.optional(),\n vite: z\n .object({ installDevServerMiddleware: z.boolean().optional() })\n .optional(),\n })\n .optional()\n .default({})\n\nexport type Page = z.infer<typeof pageSchema>\n\nexport type TanStackStartInputConfig = z.input<\n typeof tanstackStartOptionsSchema\n>\nexport type TanStackStartOutputConfig = ReturnType<typeof parseStartConfig>\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
+ import { GetConfigFn } from '../plugin.js';
1
2
  import { PluginOption, Rollup } from 'vite';
2
3
  import { RouterManagedTag } from '@tanstack/router-core';
3
4
  export declare const getCSSRecursively: (chunk: Rollup.OutputChunk, chunksByFileName: Map<string, Rollup.OutputChunk>, basePath: string) => RouterManagedTag[];
4
5
  export declare function startManifestPlugin(opts: {
5
6
  getClientBundle: () => Rollup.OutputBundle;
7
+ getConfig: GetConfigFn;
6
8
  }): PluginOption;
@@ -45,15 +45,15 @@ function startManifestPlugin(opts) {
45
45
  id: new RegExp(resolvedModuleId)
46
46
  },
47
47
  handler(id) {
48
+ const { resolvedStartConfig } = opts.getConfig();
48
49
  if (id === resolvedModuleId) {
49
50
  if (this.environment.config.consumer !== "server") {
50
51
  return `export default {}`;
51
52
  }
52
- const APP_BASE = globalThis.TSS_APP_BASE;
53
53
  if (this.environment.config.command === "serve") {
54
54
  return `export const tsrStartManifest = () => ({
55
55
  routes: {},
56
- clientEntry: '${joinURL(APP_BASE, "@id", ENTRY_POINTS.client)}',
56
+ clientEntry: '${joinURL(resolvedStartConfig.viteAppBase, "@id", ENTRY_POINTS.client)}',
57
57
  })`;
58
58
  }
59
59
  const routeTreeRoutes = globalThis.TSS_ROUTES_MANIFEST.routes;
@@ -110,14 +110,16 @@ function startManifestPlugin(opts) {
110
110
  if (chunks) {
111
111
  chunks.forEach((chunk) => {
112
112
  const preloads = chunk.imports.map((d) => {
113
- const assetPath = joinURL(APP_BASE, d);
113
+ const assetPath = joinURL(resolvedStartConfig.viteAppBase, d);
114
114
  return assetPath;
115
115
  });
116
- preloads.unshift(joinURL(APP_BASE, chunk.fileName));
116
+ preloads.unshift(
117
+ joinURL(resolvedStartConfig.viteAppBase, chunk.fileName)
118
+ );
117
119
  const cssAssetsList = getCSSRecursively(
118
120
  chunk,
119
121
  chunksByFileName,
120
- APP_BASE
122
+ resolvedStartConfig.viteAppBase
121
123
  );
122
124
  routeTreeRoutes[routeId] = {
123
125
  ...v,
@@ -131,13 +133,15 @@ function startManifestPlugin(opts) {
131
133
  throw new Error("No entry file found");
132
134
  }
133
135
  routeTreeRoutes[rootRouteId].preloads = [
134
- joinURL(APP_BASE, entryFile.fileName),
135
- ...entryFile.imports.map((d) => joinURL(APP_BASE, d))
136
+ joinURL(resolvedStartConfig.viteAppBase, entryFile.fileName),
137
+ ...entryFile.imports.map(
138
+ (d) => joinURL(resolvedStartConfig.viteAppBase, d)
139
+ )
136
140
  ];
137
141
  const entryCssAssetsList = getCSSRecursively(
138
142
  entryFile,
139
143
  chunksByFileName,
140
- APP_BASE
144
+ resolvedStartConfig.viteAppBase
141
145
  );
142
146
  routeTreeRoutes[rootRouteId].assets = [
143
147
  ...routeTreeRoutes[rootRouteId].assets || [],
@@ -161,7 +165,10 @@ function startManifestPlugin(opts) {
161
165
  recurseRoute(routeTreeRoutes[rootRouteId]);
162
166
  const startManifest = {
163
167
  routes: routeTreeRoutes,
164
- clientEntry: joinURL(APP_BASE, entryFile.fileName)
168
+ clientEntry: joinURL(
169
+ resolvedStartConfig.viteAppBase,
170
+ entryFile.fileName
171
+ )
165
172
  };
166
173
  return `export const tsrStartManifest = () => (${JSON.stringify(startManifest)})`;
167
174
  }
@@ -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 { PluginOption, Rollup } from 'vite'\nimport type { RouterManagedTag } from '@tanstack/router-core'\n\nexport const getCSSRecursively = (\n chunk: Rollup.OutputChunk,\n chunksByFileName: Map<string, Rollup.OutputChunk>,\n basePath: string,\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(importedChunk, chunksByFileName, basePath),\n )\n }\n }\n\n return result\n}\n\nconst resolvedModuleId = resolveViteId(VIRTUAL_MODULES.startManifest)\nexport function startManifestPlugin(opts: {\n getClientBundle: () => Rollup.OutputBundle\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 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 // This is the basepath for the application\n const APP_BASE = globalThis.TSS_APP_BASE\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(APP_BASE, '@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 // 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(APP_BASE, 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(joinURL(APP_BASE, chunk.fileName))\n\n const cssAssetsList = getCSSRecursively(\n chunk,\n chunksByFileName,\n APP_BASE,\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(APP_BASE, entryFile.fileName),\n ...entryFile.imports.map((d) => joinURL(APP_BASE, d)),\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 APP_BASE,\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 const startManifest = {\n routes: routeTreeRoutes,\n clientEntry: joinURL(APP_BASE, entryFile.fileName),\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 { RouterManagedTag } from '@tanstack/router-core'\n\nexport const getCSSRecursively = (\n chunk: Rollup.OutputChunk,\n chunksByFileName: Map<string, Rollup.OutputChunk>,\n basePath: string,\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(importedChunk, chunksByFileName, basePath),\n )\n }\n }\n\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 // 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 )\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 )\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 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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/start-plugin-core",
3
- "version": "1.132.32",
3
+ "version": "1.132.33",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -59,12 +59,12 @@
59
59
  "vitefu": "^1.1.1",
60
60
  "xmlbuilder2": "^3.1.1",
61
61
  "zod": "^3.24.2",
62
- "@tanstack/router-core": "1.132.31",
63
- "@tanstack/router-generator": "1.132.31",
64
- "@tanstack/router-plugin": "1.132.31",
65
- "@tanstack/router-utils": "1.132.31",
62
+ "@tanstack/router-generator": "1.132.33",
63
+ "@tanstack/router-core": "1.132.33",
66
64
  "@tanstack/server-functions-plugin": "1.132.31",
67
- "@tanstack/start-server-core": "1.132.32"
65
+ "@tanstack/router-plugin": "1.132.33",
66
+ "@tanstack/router-utils": "1.132.31",
67
+ "@tanstack/start-server-core": "1.132.33"
68
68
  },
69
69
  "devDependencies": {
70
70
  "@types/babel__code-frame": "^7.0.6",
package/src/global.d.ts CHANGED
@@ -2,7 +2,6 @@ import type { Manifest } from '@tanstack/router-core'
2
2
 
3
3
  /* eslint-disable no-var */
4
4
  declare global {
5
- var TSS_APP_BASE: string
6
5
  var TSS_ROUTES_MANIFEST: Manifest
7
6
  }
8
7
  export {}
package/src/plugin.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { trimPathRight } from '@tanstack/router-core'
1
+ import { joinPaths } from '@tanstack/router-core'
2
2
  import { VIRTUAL_MODULES } from '@tanstack/start-server-core'
3
3
  import { TanStackServerFnPluginEnv } from '@tanstack/server-functions-plugin'
4
4
  import * as vite from 'vite'
@@ -41,12 +41,23 @@ export interface ResolvedStartConfig {
41
41
  startFilePath: string | undefined
42
42
  routerFilePath: string
43
43
  srcDirectory: string
44
+ viteAppBase: string
44
45
  }
45
46
 
46
47
  export type GetConfigFn = () => {
47
48
  startConfig: TanStackStartOutputConfig
48
49
  resolvedStartConfig: ResolvedStartConfig
49
50
  }
51
+
52
+ function isFullUrl(str: string): boolean {
53
+ try {
54
+ new URL(str)
55
+ return true
56
+ } catch {
57
+ return false
58
+ }
59
+ }
60
+
50
61
  export function TanStackStartVitePluginCore(
51
62
  corePluginOpts: TanStackStartVitePluginCoreOptions,
52
63
  startPluginOpts: TanStackStartInputConfig,
@@ -56,6 +67,7 @@ export function TanStackStartVitePluginCore(
56
67
  startFilePath: undefined,
57
68
  routerFilePath: '',
58
69
  srcDirectory: '',
70
+ viteAppBase: '',
59
71
  }
60
72
 
61
73
  let startConfig: TanStackStartOutputConfig | null
@@ -90,13 +102,46 @@ export function TanStackStartVitePluginCore(
90
102
  name: 'tanstack-start-core:config',
91
103
  enforce: 'pre',
92
104
  async config(viteConfig, { command }) {
93
- const viteAppBase = trimPathRight(viteConfig.base || '/')
94
- globalThis.TSS_APP_BASE = viteAppBase
95
-
105
+ resolvedStartConfig.viteAppBase = viteConfig.base ?? '/'
106
+ if (!isFullUrl(resolvedStartConfig.viteAppBase)) {
107
+ resolvedStartConfig.viteAppBase = joinPaths([
108
+ '/',
109
+ viteConfig.base,
110
+ '/',
111
+ ])
112
+ }
96
113
  const root = viteConfig.root || process.cwd()
97
114
  resolvedStartConfig.root = root
98
115
 
99
116
  const { startConfig } = getConfig()
117
+ if (startConfig.router.basepath === undefined) {
118
+ if (!isFullUrl(resolvedStartConfig.viteAppBase)) {
119
+ startConfig.router.basepath =
120
+ resolvedStartConfig.viteAppBase.replace(/^\/|\/$/g, '')
121
+ } else {
122
+ startConfig.router.basepath = '/'
123
+ }
124
+ } else {
125
+ if (command === 'serve' && !viteConfig.server?.middlewareMode) {
126
+ // when serving, we must ensure that router basepath and viteAppBase are aligned
127
+ if (
128
+ !joinPaths(['/', startConfig.router.basepath, '/']).startsWith(
129
+ joinPaths(['/', resolvedStartConfig.viteAppBase, '/']),
130
+ )
131
+ ) {
132
+ this.error(
133
+ '[tanstack-start]: During `vite dev`, `router.basepath` must start with the vite `base` config value',
134
+ )
135
+ }
136
+ }
137
+ }
138
+
139
+ const TSS_SERVER_FN_BASE = joinPaths([
140
+ '/',
141
+ startConfig.router.basepath,
142
+ startConfig.serverFns.base,
143
+ '/',
144
+ ])
100
145
  const resolvedSrcDirectory = join(root, startConfig.srcDirectory)
101
146
  resolvedStartConfig.srcDirectory = resolvedSrcDirectory
102
147
 
@@ -179,7 +224,6 @@ export function TanStackStartVitePluginCore(
179
224
  })
180
225
 
181
226
  return {
182
- base: viteAppBase,
183
227
  // see https://vite.dev/config/shared-options.html#apptype
184
228
  // this will prevent vite from injecting middlewares that we don't want
185
229
  appType: viteConfig.appType ?? 'custom',
@@ -246,9 +290,9 @@ export function TanStackStartVitePluginCore(
246
290
  // i.e: __FRAMEWORK_NAME__ can be replaced with JSON.stringify("TanStack Start")
247
291
  // This is not the same as injecting environment variables.
248
292
 
249
- ...defineReplaceEnv('TSS_SERVER_FN_BASE', startConfig.serverFns.base),
293
+ ...defineReplaceEnv('TSS_SERVER_FN_BASE', TSS_SERVER_FN_BASE),
250
294
  ...defineReplaceEnv('TSS_CLIENT_OUTPUT_DIR', getClientOutputDirectory(viteConfig)),
251
- ...defineReplaceEnv('TSS_APP_BASE', viteAppBase),
295
+ ...defineReplaceEnv('TSS_ROUTER_BASEPATH', startConfig.router.basepath),
252
296
  ...(command === 'serve' ? defineReplaceEnv('TSS_SHELL', startConfig.spa?.enabled ? 'true' : 'false') : {}),
253
297
  ...defineReplaceEnv('TSS_DEV_SERVER', command === 'serve' ? 'true' : 'false'),
254
298
  },
@@ -306,6 +350,7 @@ export function TanStackStartVitePluginCore(
306
350
  loadEnvPlugin(),
307
351
  startManifestPlugin({
308
352
  getClientBundle: () => getBundle(VITE_ENVIRONMENT_NAMES.client),
353
+ getConfig,
309
354
  }),
310
355
  devServerPlugin({ getConfig }),
311
356
  {
package/src/prerender.ts CHANGED
@@ -107,6 +107,7 @@ export async function prerender({
107
107
  const concurrency = startConfig.prerender?.concurrency ?? os.cpus().length
108
108
  logger.info(`Concurrency: ${concurrency}`)
109
109
  const queue = new Queue({ concurrency })
110
+ const routerBasePath = joinURL('/', startConfig.router.basepath ?? '')
110
111
 
111
112
  startConfig.pages.forEach((page) => addCrawlPageTask(page))
112
113
 
@@ -146,7 +147,7 @@ export async function prerender({
146
147
  // Fetch the route
147
148
  const encodedRoute = encodeURI(page.path)
148
149
 
149
- const res = await localFetch(withBase(encodedRoute, TSS_APP_BASE), {
150
+ const res = await localFetch(withBase(encodedRoute, routerBasePath), {
150
151
  headers: {
151
152
  ...prerenderOptions.headers,
152
153
  },
@@ -179,7 +180,7 @@ export async function prerender({
179
180
 
180
181
  const filename = withoutBase(
181
182
  isImplicitHTML ? htmlPath : routeWithIndex,
182
- TSS_APP_BASE,
183
+ routerBasePath,
183
184
  )
184
185
 
185
186
  const html = await res.text()
package/src/schema.ts CHANGED
@@ -138,6 +138,7 @@ const tanstackStartOptionsSchema = z
138
138
  router: z
139
139
  .object({
140
140
  entry: z.string().optional(),
141
+ basepath: z.string().optional(),
141
142
  })
142
143
  .and(tsrConfig.optional().default({}))
143
144
  .optional()
@@ -4,6 +4,7 @@ import { VIRTUAL_MODULES } from '@tanstack/start-server-core'
4
4
  import { tsrSplit } from '@tanstack/router-plugin'
5
5
  import { resolveViteId } from '../utils'
6
6
  import { ENTRY_POINTS } from '../constants'
7
+ import type { GetConfigFn } from '../plugin'
7
8
  import type { PluginOption, Rollup } from 'vite'
8
9
  import type { RouterManagedTag } from '@tanstack/router-core'
9
10
 
@@ -42,6 +43,7 @@ export const getCSSRecursively = (
42
43
  const resolvedModuleId = resolveViteId(VIRTUAL_MODULES.startManifest)
43
44
  export function startManifestPlugin(opts: {
44
45
  getClientBundle: () => Rollup.OutputBundle
46
+ getConfig: GetConfigFn
45
47
  }): PluginOption {
46
48
  return {
47
49
  name: 'tanstack-start:start-manifest-plugin',
@@ -60,6 +62,7 @@ export function startManifestPlugin(opts: {
60
62
  id: new RegExp(resolvedModuleId),
61
63
  },
62
64
  handler(id) {
65
+ const { resolvedStartConfig } = opts.getConfig()
63
66
  if (id === resolvedModuleId) {
64
67
  if (this.environment.config.consumer !== 'server') {
65
68
  // this will ultimately fail the build if the plugin is used outside the server environment
@@ -67,14 +70,11 @@ export function startManifestPlugin(opts: {
67
70
  return `export default {}`
68
71
  }
69
72
 
70
- // This is the basepath for the application
71
- const APP_BASE = globalThis.TSS_APP_BASE
72
-
73
73
  // If we're in development, return a dummy manifest
74
74
  if (this.environment.config.command === 'serve') {
75
75
  return `export const tsrStartManifest = () => ({
76
76
  routes: {},
77
- clientEntry: '${joinURL(APP_BASE, '@id', ENTRY_POINTS.client)}',
77
+ clientEntry: '${joinURL(resolvedStartConfig.viteAppBase, '@id', ENTRY_POINTS.client)}',
78
78
  })`
79
79
  }
80
80
 
@@ -146,19 +146,21 @@ export function startManifestPlugin(opts: {
146
146
  // Map the relevant imports to their route paths,
147
147
  // so that it can be imported in the browser.
148
148
  const preloads = chunk.imports.map((d) => {
149
- const assetPath = joinURL(APP_BASE, d)
149
+ const assetPath = joinURL(resolvedStartConfig.viteAppBase, d)
150
150
  return assetPath
151
151
  })
152
152
 
153
153
  // Since this is the most important JS entry for the route,
154
154
  // it should be moved to the front of the preloads so that
155
155
  // it has the best chance of being loaded first.
156
- preloads.unshift(joinURL(APP_BASE, chunk.fileName))
156
+ preloads.unshift(
157
+ joinURL(resolvedStartConfig.viteAppBase, chunk.fileName),
158
+ )
157
159
 
158
160
  const cssAssetsList = getCSSRecursively(
159
161
  chunk,
160
162
  chunksByFileName,
161
- APP_BASE,
163
+ resolvedStartConfig.viteAppBase,
162
164
  )
163
165
 
164
166
  routeTreeRoutes[routeId] = {
@@ -174,8 +176,10 @@ export function startManifestPlugin(opts: {
174
176
  throw new Error('No entry file found')
175
177
  }
176
178
  routeTreeRoutes[rootRouteId]!.preloads = [
177
- joinURL(APP_BASE, entryFile.fileName),
178
- ...entryFile.imports.map((d) => joinURL(APP_BASE, d)),
179
+ joinURL(resolvedStartConfig.viteAppBase, entryFile.fileName),
180
+ ...entryFile.imports.map((d) =>
181
+ joinURL(resolvedStartConfig.viteAppBase, d),
182
+ ),
179
183
  ]
180
184
 
181
185
  // Gather all the CSS files from the entry file in
@@ -183,7 +187,7 @@ export function startManifestPlugin(opts: {
183
187
  const entryCssAssetsList = getCSSRecursively(
184
188
  entryFile,
185
189
  chunksByFileName,
186
- APP_BASE,
190
+ resolvedStartConfig.viteAppBase,
187
191
  )
188
192
 
189
193
  routeTreeRoutes[rootRouteId]!.assets = [
@@ -218,7 +222,10 @@ export function startManifestPlugin(opts: {
218
222
 
219
223
  const startManifest = {
220
224
  routes: routeTreeRoutes,
221
- clientEntry: joinURL(APP_BASE, entryFile.fileName),
225
+ clientEntry: joinURL(
226
+ resolvedStartConfig.viteAppBase,
227
+ entryFile.fileName,
228
+ ),
222
229
  }
223
230
 
224
231
  return `export const tsrStartManifest = () => (${JSON.stringify(startManifest)})`