@tanstack/start-plugin-core 1.121.0-alpha.2 → 1.121.0-alpha.21

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.
Files changed (137) hide show
  1. package/dist/cjs/constants.cjs +4 -0
  2. package/dist/cjs/constants.cjs.map +1 -1
  3. package/dist/cjs/constants.d.cts +2 -0
  4. package/dist/cjs/{extractHtmlScripts.cjs → dev-server-plugin/extract-html-scripts.cjs} +1 -1
  5. package/dist/cjs/dev-server-plugin/extract-html-scripts.cjs.map +1 -0
  6. package/dist/cjs/{nitro/dev-server-plugin.cjs → dev-server-plugin/plugin.cjs} +2 -2
  7. package/dist/cjs/dev-server-plugin/plugin.cjs.map +1 -0
  8. package/dist/cjs/index.cjs +2 -0
  9. package/dist/cjs/index.cjs.map +1 -1
  10. package/dist/cjs/index.d.cts +1 -0
  11. package/dist/cjs/load-env-plugin/plugin.cjs +34 -0
  12. package/dist/cjs/load-env-plugin/plugin.cjs.map +1 -0
  13. package/dist/cjs/load-env-plugin/plugin.d.cts +3 -0
  14. package/dist/cjs/nitro-plugin/build-sitemap.cjs +138 -0
  15. package/dist/cjs/nitro-plugin/build-sitemap.cjs.map +1 -0
  16. package/dist/cjs/nitro-plugin/build-sitemap.d.cts +31 -0
  17. package/dist/cjs/{nitro/nitro-plugin.cjs → nitro-plugin/plugin.cjs} +77 -54
  18. package/dist/cjs/nitro-plugin/plugin.cjs.map +1 -0
  19. package/dist/cjs/{prerender.cjs → nitro-plugin/prerender.cjs} +12 -17
  20. package/dist/cjs/nitro-plugin/prerender.cjs.map +1 -0
  21. package/dist/cjs/{prerender.d.cts → nitro-plugin/prerender.d.cts} +1 -1
  22. package/dist/cjs/nitro-plugin/queue.cjs.map +1 -0
  23. package/dist/cjs/plugin.cjs +38 -27
  24. package/dist/cjs/plugin.cjs.map +1 -1
  25. package/dist/cjs/plugin.d.cts +25 -3064
  26. package/dist/cjs/resolve-virtual-entries-plugin/plugin.cjs +66 -0
  27. package/dist/cjs/resolve-virtual-entries-plugin/plugin.cjs.map +1 -0
  28. package/dist/cjs/resolve-virtual-entries-plugin/plugin.d.cts +3 -0
  29. package/dist/cjs/schema.cjs +6 -4
  30. package/dist/cjs/schema.cjs.map +1 -1
  31. package/dist/cjs/schema.d.cts +530 -1656
  32. package/dist/cjs/start-compiler-plugin.cjs +2 -2
  33. package/dist/cjs/start-compiler-plugin.cjs.map +1 -1
  34. package/dist/cjs/start-compiler-plugin.d.cts +1 -1
  35. package/dist/cjs/{routesManifestPlugin.cjs → start-routes-manifest-plugin/plugin.cjs} +86 -44
  36. package/dist/cjs/start-routes-manifest-plugin/plugin.cjs.map +1 -0
  37. package/dist/cjs/start-routes-manifest-plugin/plugin.d.cts +3 -0
  38. package/dist/cjs/start-server-routes-plugin/plugin.cjs +4 -2
  39. package/dist/cjs/start-server-routes-plugin/plugin.cjs.map +1 -1
  40. package/dist/cjs/utils.cjs +18 -0
  41. package/dist/cjs/utils.cjs.map +1 -0
  42. package/dist/cjs/utils.d.cts +8 -0
  43. package/dist/esm/constants.d.ts +2 -0
  44. package/dist/esm/constants.js +4 -0
  45. package/dist/esm/constants.js.map +1 -1
  46. package/dist/esm/{extractHtmlScripts.js → dev-server-plugin/extract-html-scripts.js} +1 -1
  47. package/dist/esm/dev-server-plugin/extract-html-scripts.js.map +1 -0
  48. package/dist/esm/{nitro/dev-server-plugin.js → dev-server-plugin/plugin.js} +2 -2
  49. package/dist/esm/dev-server-plugin/plugin.js.map +1 -0
  50. package/dist/esm/index.d.ts +1 -0
  51. package/dist/esm/index.js +3 -1
  52. package/dist/esm/index.js.map +1 -1
  53. package/dist/esm/load-env-plugin/plugin.d.ts +3 -0
  54. package/dist/esm/load-env-plugin/plugin.js +17 -0
  55. package/dist/esm/load-env-plugin/plugin.js.map +1 -0
  56. package/dist/esm/nitro-plugin/build-sitemap.d.ts +31 -0
  57. package/dist/esm/nitro-plugin/build-sitemap.js +138 -0
  58. package/dist/esm/nitro-plugin/build-sitemap.js.map +1 -0
  59. package/dist/esm/nitro-plugin/plugin.js +181 -0
  60. package/dist/esm/nitro-plugin/plugin.js.map +1 -0
  61. package/dist/esm/{prerender.d.ts → nitro-plugin/prerender.d.ts} +1 -1
  62. package/dist/esm/{prerender.js → nitro-plugin/prerender.js} +12 -17
  63. package/dist/esm/nitro-plugin/prerender.js.map +1 -0
  64. package/dist/esm/nitro-plugin/queue.js.map +1 -0
  65. package/dist/esm/plugin.d.ts +25 -3064
  66. package/dist/esm/plugin.js +39 -28
  67. package/dist/esm/plugin.js.map +1 -1
  68. package/dist/esm/resolve-virtual-entries-plugin/plugin.d.ts +3 -0
  69. package/dist/esm/resolve-virtual-entries-plugin/plugin.js +49 -0
  70. package/dist/esm/resolve-virtual-entries-plugin/plugin.js.map +1 -0
  71. package/dist/esm/schema.d.ts +530 -1656
  72. package/dist/esm/schema.js +6 -4
  73. package/dist/esm/schema.js.map +1 -1
  74. package/dist/esm/start-compiler-plugin.d.ts +1 -1
  75. package/dist/esm/start-compiler-plugin.js +2 -2
  76. package/dist/esm/start-compiler-plugin.js.map +1 -1
  77. package/dist/esm/start-routes-manifest-plugin/plugin.d.ts +3 -0
  78. package/dist/esm/{routesManifestPlugin.js → start-routes-manifest-plugin/plugin.js} +87 -45
  79. package/dist/esm/start-routes-manifest-plugin/plugin.js.map +1 -0
  80. package/dist/esm/start-server-routes-plugin/plugin.js +4 -2
  81. package/dist/esm/start-server-routes-plugin/plugin.js.map +1 -1
  82. package/dist/esm/utils.d.ts +8 -0
  83. package/dist/esm/utils.js +18 -0
  84. package/dist/esm/utils.js.map +1 -0
  85. package/package.json +6 -6
  86. package/src/constants.ts +3 -0
  87. package/src/{nitro/dev-server-plugin.ts → dev-server-plugin/plugin.ts} +11 -1
  88. package/src/index.ts +1 -0
  89. package/src/load-env-plugin/plugin.ts +17 -0
  90. package/src/nitro-plugin/build-sitemap.ts +213 -0
  91. package/src/nitro-plugin/plugin.ts +244 -0
  92. package/src/{prerender.ts → nitro-plugin/prerender.ts} +14 -21
  93. package/src/plugin.ts +57 -29
  94. package/src/resolve-virtual-entries-plugin/plugin.ts +63 -0
  95. package/src/schema.ts +11 -9
  96. package/src/start-compiler-plugin.ts +1 -1
  97. package/src/{routesManifestPlugin.ts → start-routes-manifest-plugin/plugin.ts} +111 -45
  98. package/src/start-server-routes-plugin/plugin.ts +4 -2
  99. package/src/utils.ts +14 -0
  100. package/dist/cjs/extractHtmlScripts.cjs.map +0 -1
  101. package/dist/cjs/nitro/build-nitro.cjs +0 -18
  102. package/dist/cjs/nitro/build-nitro.cjs.map +0 -1
  103. package/dist/cjs/nitro/build-nitro.d.cts +0 -2
  104. package/dist/cjs/nitro/build-sitemap.d.cts +0 -9
  105. package/dist/cjs/nitro/dev-server-plugin.cjs.map +0 -1
  106. package/dist/cjs/nitro/nitro-plugin.cjs.map +0 -1
  107. package/dist/cjs/prerender.cjs.map +0 -1
  108. package/dist/cjs/queue.cjs.map +0 -1
  109. package/dist/cjs/routesManifestPlugin.cjs.map +0 -1
  110. package/dist/cjs/routesManifestPlugin.d.cts +0 -3
  111. package/dist/esm/extractHtmlScripts.js.map +0 -1
  112. package/dist/esm/nitro/build-nitro.d.ts +0 -2
  113. package/dist/esm/nitro/build-nitro.js +0 -18
  114. package/dist/esm/nitro/build-nitro.js.map +0 -1
  115. package/dist/esm/nitro/build-sitemap.d.ts +0 -9
  116. package/dist/esm/nitro/dev-server-plugin.js.map +0 -1
  117. package/dist/esm/nitro/nitro-plugin.js +0 -158
  118. package/dist/esm/nitro/nitro-plugin.js.map +0 -1
  119. package/dist/esm/prerender.js.map +0 -1
  120. package/dist/esm/queue.js.map +0 -1
  121. package/dist/esm/routesManifestPlugin.d.ts +0 -3
  122. package/dist/esm/routesManifestPlugin.js.map +0 -1
  123. package/src/nitro/build-nitro.ts +0 -27
  124. package/src/nitro/build-sitemap.ts +0 -79
  125. package/src/nitro/nitro-plugin.ts +0 -199
  126. /package/dist/cjs/{extractHtmlScripts.d.cts → dev-server-plugin/extract-html-scripts.d.cts} +0 -0
  127. /package/dist/cjs/{nitro/dev-server-plugin.d.cts → dev-server-plugin/plugin.d.cts} +0 -0
  128. /package/dist/cjs/{nitro/nitro-plugin.d.cts → nitro-plugin/plugin.d.cts} +0 -0
  129. /package/dist/cjs/{queue.cjs → nitro-plugin/queue.cjs} +0 -0
  130. /package/dist/cjs/{queue.d.cts → nitro-plugin/queue.d.cts} +0 -0
  131. /package/dist/esm/{extractHtmlScripts.d.ts → dev-server-plugin/extract-html-scripts.d.ts} +0 -0
  132. /package/dist/esm/{nitro/dev-server-plugin.d.ts → dev-server-plugin/plugin.d.ts} +0 -0
  133. /package/dist/esm/{nitro/nitro-plugin.d.ts → nitro-plugin/plugin.d.ts} +0 -0
  134. /package/dist/esm/{queue.d.ts → nitro-plugin/queue.d.ts} +0 -0
  135. /package/dist/esm/{queue.js → nitro-plugin/queue.js} +0 -0
  136. /package/src/{extractHtmlScripts.ts → dev-server-plugin/extract-html-scripts.ts} +0 -0
  137. /package/src/{queue.ts → nitro-plugin/queue.ts} +0 -0
package/src/plugin.ts CHANGED
@@ -1,24 +1,29 @@
1
1
  import path from 'node:path'
2
2
  import { createNitro } from 'nitropack'
3
+ import { trimPathRight } from '@tanstack/router-core'
3
4
  import { tanstackRouter } from '@tanstack/router-plugin/vite'
4
5
  import { TanStackServerFnPluginEnv } from '@tanstack/server-functions-plugin'
5
6
  import * as vite from 'vite'
7
+ import { createTanStackConfig } from './schema'
8
+ import { nitroPlugin } from './nitro-plugin/plugin'
9
+ import { startRoutesManifestPlugin } from './start-routes-manifest-plugin/plugin'
10
+ import { startCompilerPlugin } from './start-compiler-plugin'
6
11
  import {
7
- createTanStackConfig,
8
- createTanStackStartOptionsSchema,
9
- } from './schema'
10
- import { nitroPlugin } from './nitro/nitro-plugin'
11
- import { startManifestPlugin } from './routesManifestPlugin'
12
- import { TanStackStartCompilerPlugin } from './start-compiler-plugin'
13
- import { VITE_ENVIRONMENT_NAMES } from './constants'
12
+ CLIENT_DIST_DIR,
13
+ SSR_ENTRY_FILE,
14
+ VITE_ENVIRONMENT_NAMES,
15
+ } from './constants'
14
16
  import { TanStackStartServerRoutesVite } from './start-server-routes-plugin/plugin'
17
+ import { loadEnvPlugin } from './load-env-plugin/plugin'
18
+ import { devServerPlugin } from './dev-server-plugin/plugin'
19
+ import { resolveVirtualEntriesPlugin } from './resolve-virtual-entries-plugin/plugin'
20
+ import type { createTanStackStartOptionsSchema } from './schema'
15
21
  import type { PluginOption, Rollup } from 'vite'
16
22
  import type { z } from 'zod'
17
23
  import type { CompileStartFrameworkOptions } from './compilers'
18
24
 
19
- const TanStackStartOptionsSchema = createTanStackStartOptionsSchema()
20
25
  export type TanStackStartInputConfig = z.input<
21
- typeof TanStackStartOptionsSchema
26
+ ReturnType<typeof createTanStackStartOptionsSchema>
22
27
  >
23
28
 
24
29
  const defaultConfig = createTanStackConfig()
@@ -30,11 +35,19 @@ export type TanStackStartOutputConfig = ReturnType<
30
35
  typeof getTanStackStartOptions
31
36
  >
32
37
 
33
- export const clientDistDir = '.tanstack-start/build/client-dist'
34
- export const ssrEntryFile = 'ssr.mjs'
38
+ declare global {
39
+ // eslint-disable-next-line no-var
40
+ var TSS_APP_BASE: string
41
+ }
35
42
 
36
43
  export interface TanStackStartVitePluginCoreOptions {
37
44
  framework: CompileStartFrameworkOptions
45
+ getVirtualServerRootHandler: (ctx: {
46
+ routerFilepath: string
47
+ serverEntryFilepath: string
48
+ }) => string
49
+ getVirtualServerEntry: (ctx: { routerFilepath: string }) => string
50
+ getVirtualClientEntry: (ctx: { routerFilepath: string }) => string
38
51
  }
39
52
  // this needs to live outside of the TanStackStartVitePluginCore since it will be invoked multiple times by vite
40
53
  let ssrBundle: Rollup.OutputBundle
@@ -51,9 +64,13 @@ export function TanStackStartVitePluginCore(
51
64
  enableRouteGeneration: true,
52
65
  autoCodeSplitting: true,
53
66
  }),
67
+ resolveVirtualEntriesPlugin(opts, startConfig),
54
68
  {
55
69
  name: 'tanstack-start-core:config-client',
56
- async config() {
70
+ async config(viteConfig) {
71
+ const viteAppBase = trimPathRight(viteConfig.base || '/')
72
+ globalThis.TSS_APP_BASE = viteAppBase
73
+
57
74
  const nitroOutputPublicDir = await (async () => {
58
75
  // Create a dummy nitro app to get the resolved public output path
59
76
  const dummyNitroApp = await createNitro({
@@ -77,13 +94,17 @@ export function TanStackStartVitePluginCore(
77
94
  )
78
95
  ? startConfig.clientEntryPath
79
96
  : vite.normalizePath(
80
- path.resolve(startConfig.root, startConfig.clientEntryPath),
97
+ path.join(
98
+ '/@fs',
99
+ path.resolve(startConfig.root, startConfig.clientEntryPath),
100
+ ),
81
101
  )
82
102
 
83
103
  return entry
84
104
  }
85
105
 
86
106
  return {
107
+ base: viteAppBase,
87
108
  environments: {
88
109
  [VITE_ENVIRONMENT_NAMES.client]: {
89
110
  consumer: 'client',
@@ -94,9 +115,9 @@ export function TanStackStartVitePluginCore(
94
115
  main: getClientEntryPath(startConfig),
95
116
  },
96
117
  output: {
97
- dir: path.resolve(startConfig.root, clientDistDir),
118
+ dir: path.resolve(startConfig.root, CLIENT_DIST_DIR),
98
119
  },
99
- // TODO this should be removed
120
+ // TODO: this should be removed
100
121
  external: ['node:fs', 'node:path', 'node:os', 'node:crypto'],
101
122
  },
102
123
  },
@@ -111,13 +132,13 @@ export function TanStackStartVitePluginCore(
111
132
  copyPublicDir: false,
112
133
  rollupOptions: {
113
134
  output: {
114
- entryFileNames: ssrEntryFile,
135
+ entryFileNames: SSR_ENTRY_FILE,
115
136
  },
116
137
  plugins: [
117
138
  {
118
139
  name: 'capture-output',
119
- generateBundle(options, bundle) {
120
- // TODO can this hook be called more than once?
140
+ generateBundle(_options, bundle) {
141
+ // TODO: can this hook be called more than once?
121
142
  ssrBundle = bundle
122
143
  },
123
144
  },
@@ -141,32 +162,37 @@ export function TanStackStartVitePluginCore(
141
162
  '@tanstack/start-router-manifest',
142
163
  '@tanstack/start-config',
143
164
  '@tanstack/server-functions-plugin',
144
- 'tanstack:start-manifest',
145
- 'tanstack:server-fn-manifest',
165
+ 'tanstack-start-router-manifest:v',
166
+ 'tanstack-start-server-fn-manifest:v',
146
167
  'nitropack',
147
168
  '@tanstack/**',
148
169
  ],
149
170
  },
150
171
  /* prettier-ignore */
151
172
  define: {
152
- ...injectDefineEnv('TSS_PUBLIC_BASE', startConfig.public.base),
153
- ...injectDefineEnv('TSS_CLIENT_BASE', startConfig.client.base),
154
- ...injectDefineEnv('TSS_CLIENT_ENTRY', getClientEntryPath(startConfig)), // This is consumed by the router-manifest, where the entry point is imported after the dev refresh runtime is resolved
155
- ...injectDefineEnv('TSS_SERVER_FN_BASE', startConfig.serverFns.base),
156
- ...injectDefineEnv('TSS_OUTPUT_PUBLIC_DIR', nitroOutputPublicDir),
173
+ // define is an esbuild function that replaces the any instances of given keys with the given values
174
+ // i.e: __FRAMEWORK_NAME__ can be replaced with JSON.stringify("TanStack Start")
175
+ // This is not the same as injecting environment variables.
176
+
177
+ ...defineReplaceEnv('TSS_CLIENT_ENTRY', getClientEntryPath(startConfig)), // This is consumed by the router-manifest, where the entry point is imported after the dev refresh runtime is resolved
178
+ ...defineReplaceEnv('TSS_SERVER_FN_BASE', startConfig.serverFns.base),
179
+ ...defineReplaceEnv('TSS_OUTPUT_PUBLIC_DIR', nitroOutputPublicDir),
180
+ ...defineReplaceEnv('TSS_APP_BASE', viteAppBase)
157
181
  },
158
182
  }
159
183
  },
160
184
  },
161
185
  // N.B. TanStackStartCompilerPlugin must be before the TanStackServerFnPluginEnv
162
- TanStackStartCompilerPlugin(opts.framework, {
186
+ startCompilerPlugin(opts.framework, {
163
187
  client: { envName: VITE_ENVIRONMENT_NAMES.client },
164
188
  server: { envName: VITE_ENVIRONMENT_NAMES.server },
165
189
  }),
166
190
  TanStackServerFnPluginEnv({
167
191
  // This is the ID that will be available to look up and import
168
192
  // our server function manifest and resolve its module
169
- manifestVirtualImportId: 'tanstack:server-fn-manifest',
193
+ manifestVirtualImportId: 'tanstack-start-server-fn-manifest:v',
194
+ manifestOutputFilename:
195
+ '.tanstack-start/build/server/server-functions-manifest.json',
170
196
  client: {
171
197
  getRuntimeCode: () =>
172
198
  `import { createClientRpc } from '@tanstack/${opts.framework}-start/server-functions-client'`,
@@ -191,7 +217,9 @@ export function TanStackStartVitePluginCore(
191
217
  return serverEnv.runner.import(fn.extractedFilename)
192
218
  },
193
219
  }),
194
- startManifestPlugin(startConfig),
220
+ loadEnvPlugin(startConfig),
221
+ startRoutesManifestPlugin(startConfig),
222
+ devServerPlugin(),
195
223
  nitroPlugin(startConfig, () => ssrBundle),
196
224
  TanStackStartServerRoutesVite({
197
225
  ...startConfig.tsr,
@@ -200,7 +228,7 @@ export function TanStackStartVitePluginCore(
200
228
  ]
201
229
  }
202
230
 
203
- function injectDefineEnv<TKey extends string, TValue extends string>(
231
+ function defineReplaceEnv<TKey extends string, TValue extends string>(
204
232
  key: TKey,
205
233
  value: TValue,
206
234
  ): { [P in `process.env.${TKey}` | `import.meta.env.${TKey}`]: TValue } {
@@ -0,0 +1,63 @@
1
+ import path from 'node:path'
2
+ import * as vite from 'vite'
3
+ import type {
4
+ TanStackStartOutputConfig,
5
+ TanStackStartVitePluginCoreOptions,
6
+ } from '../plugin'
7
+
8
+ export function resolveVirtualEntriesPlugin(
9
+ opts: TanStackStartVitePluginCoreOptions,
10
+ startConfig: TanStackStartOutputConfig,
11
+ ): vite.Plugin {
12
+ let resolvedConfig: vite.ResolvedConfig
13
+
14
+ const modules = new Set<string>([
15
+ '/~start/server-entry',
16
+ '/~start/default-server-entry',
17
+ '/~start/default-client-entry',
18
+ ])
19
+
20
+ return {
21
+ name: 'tanstack-start-core:resolve-virtual-entries',
22
+ configResolved(config) {
23
+ resolvedConfig = config
24
+ },
25
+ resolveId(id) {
26
+ if (modules.has(id)) {
27
+ return `${id}.tsx`
28
+ }
29
+
30
+ return undefined
31
+ },
32
+ load(id) {
33
+ const routerFilepath = vite.normalizePath(
34
+ path.resolve(startConfig.root, startConfig.tsr.srcDirectory, 'router'),
35
+ )
36
+
37
+ if (id === '/~start/server-entry.tsx') {
38
+ const ssrEntryFilepath = startConfig.serverEntryPath.startsWith(
39
+ '/~start/default-server-entry',
40
+ )
41
+ ? startConfig.serverEntryPath
42
+ : vite.normalizePath(
43
+ path.resolve(resolvedConfig.root, startConfig.serverEntryPath),
44
+ )
45
+
46
+ return opts.getVirtualServerRootHandler({
47
+ routerFilepath,
48
+ serverEntryFilepath: ssrEntryFilepath,
49
+ })
50
+ }
51
+
52
+ if (id === '/~start/default-client-entry.tsx') {
53
+ return opts.getVirtualClientEntry({ routerFilepath })
54
+ }
55
+
56
+ if (id === '/~start/default-server-entry.tsx') {
57
+ return opts.getVirtualServerEntry({ routerFilepath })
58
+ }
59
+
60
+ return undefined
61
+ },
62
+ }
63
+ }
package/src/schema.ts CHANGED
@@ -4,9 +4,12 @@ import { z } from 'zod'
4
4
  import { configSchema, getConfig } from '@tanstack/router-generator'
5
5
  import type { NitroConfig } from 'nitropack'
6
6
 
7
- const tsrConfig = configSchema.partial().extend({
8
- srcDirectory: z.string().optional().default('src'),
9
- })
7
+ const tsrConfig = configSchema
8
+ .omit({ autoCodeSplitting: true })
9
+ .partial()
10
+ .extend({
11
+ srcDirectory: z.string().optional().default('src'),
12
+ })
10
13
 
11
14
  export function createTanStackConfig<
12
15
  TFrameworkPlugin extends Record<string, unknown>,
@@ -111,13 +114,12 @@ export function createTanStackStartOptionsSchema(
111
114
  })
112
115
  .optional()
113
116
  .default({}),
114
- pages: z
115
- .array(z.union([z.string(), pageSchema]))
116
- .optional()
117
- .default([]),
118
- sitemap: pagePrerenderOptionsSchema
119
- .extend({
117
+ pages: z.array(pageSchema).optional().default([]),
118
+ sitemap: z
119
+ .object({
120
+ enabled: z.boolean().optional().default(true),
120
121
  host: z.string().optional(),
122
+ outputPath: z.string().optional().default('sitemap.xml'),
121
123
  })
122
124
  .optional(),
123
125
  prerender: z
@@ -24,7 +24,7 @@ const transformFuncs = [
24
24
 
25
25
  const tokenRegex = new RegExp(transformFuncs.join('|'))
26
26
 
27
- export function TanStackStartCompilerPlugin(
27
+ export function startCompilerPlugin(
28
28
  framework: CompileStartFrameworkOptions,
29
29
  inputOpts?: {
30
30
  client?: {
@@ -1,7 +1,8 @@
1
- import { readFileSync } from 'node:fs'
1
+ import { mkdirSync, readFileSync, rmSync, writeFile } from 'node:fs'
2
2
  import path from 'node:path'
3
3
  import { joinURL } from 'ufo'
4
4
  import { rootRouteId } from '@tanstack/router-core'
5
+ import { resolveViteId } from '../utils'
5
6
  import type {
6
7
  PluginOption,
7
8
  ResolvedConfig,
@@ -9,13 +10,48 @@ import type {
9
10
  ManifestChunk as ViteManifestChunk,
10
11
  } from 'vite'
11
12
  import type { Manifest, RouterManagedTag } from '@tanstack/router-core'
12
- import type { TanStackStartOutputConfig } from './plugin'
13
+ import type { TanStackStartOutputConfig } from '../plugin'
13
14
 
14
- export function startManifestPlugin(
15
+ const getCSSRecursively = (
16
+ file: ViteManifestChunk,
17
+ filesByRouteFilePath: ViteManifest,
18
+ basePath: string,
19
+ ) => {
20
+ const result: Array<RouterManagedTag> = []
21
+
22
+ // Get all css imports from the file
23
+ for (const cssFile of file.css ?? []) {
24
+ result.push({
25
+ tag: 'link',
26
+ attrs: {
27
+ rel: 'stylesheet',
28
+ href: joinURL(basePath, cssFile),
29
+ type: 'text/css',
30
+ },
31
+ })
32
+ }
33
+
34
+ // Recursively get CSS from imports
35
+ for (const imp of file.imports ?? []) {
36
+ const importInfo = filesByRouteFilePath[imp]
37
+ if (importInfo) {
38
+ result.push(
39
+ ...getCSSRecursively(importInfo, filesByRouteFilePath, basePath),
40
+ )
41
+ }
42
+ }
43
+
44
+ return result
45
+ }
46
+
47
+ export function startRoutesManifestPlugin(
15
48
  opts: TanStackStartOutputConfig,
16
49
  ): PluginOption {
17
50
  let config: ResolvedConfig
18
51
 
52
+ const moduleId = 'tanstack-start-router-manifest:v'
53
+ const resolvedModuleId = resolveViteId(moduleId)
54
+
19
55
  return {
20
56
  name: 'tsr-routes-manifest',
21
57
  enforce: 'pre',
@@ -27,27 +63,29 @@ export function startManifestPlugin(
27
63
  // config = envConfig.
28
64
  // },
29
65
  resolveId(id) {
30
- if (id === 'tanstack:start-manifest') {
31
- return id
66
+ if (id === moduleId) {
67
+ return resolvedModuleId
32
68
  }
33
69
  return
34
70
  },
35
71
  load(id) {
36
- if (id === 'tanstack:start-manifest') {
72
+ if (id === resolvedModuleId) {
37
73
  if (this.environment.config.consumer !== 'server') {
38
74
  // this will ultimately fail the build if the plugin is used outside the server environment
39
75
  // TODO: do we need special handling for `serve`?
40
76
  return `export default {}`
41
77
  }
42
- // If we're in development, return a dummy manifest
43
78
 
79
+ // If we're in development, return a dummy manifest
44
80
  if (config.command === 'serve') {
45
81
  return `export const tsrStartManifest = () => ({
46
- entry: "$${process.env.TSS_CLIENT_BASE}/",
47
82
  routes: {}
48
83
  })`
49
84
  }
50
85
 
86
+ // This is the basepath for the application
87
+ const APP_BASE = globalThis.TSS_APP_BASE
88
+
51
89
  const clientViteManifestPath = path.resolve(
52
90
  opts.root,
53
91
  '.tanstack-start/build/client-dist/.vite/manifest.json',
@@ -86,8 +124,12 @@ export function startManifestPlugin(
86
124
  )?.[1] || '{ routes: {} }',
87
125
  ) as Manifest
88
126
 
89
- const routes = routerManifest.routes
127
+ // This the manifest pulled from the generated route tree and later used by the Router.
128
+ // i.e what's located in `src/generatedRouteTree.gen.ts`
129
+ const routeTreeRoutes = routerManifest.routes
90
130
 
131
+ // This is where hydration will start, from when the SSR'd page reaches the browser.
132
+ // By default, this'd be the virtual entry of `/~start/default-client-entry.tsx`, unless a custom entry is provided.
91
133
  let entryFile: ViteManifestChunk | undefined
92
134
 
93
135
  const filesByRouteFilePath: ViteManifest = Object.fromEntries(
@@ -108,34 +150,34 @@ export function startManifestPlugin(
108
150
  )
109
151
 
110
152
  // Add preloads to the routes from the vite manifest
111
- Object.entries(routes).forEach(([k, v]) => {
153
+ Object.entries(routeTreeRoutes).forEach(([routeId, v]) => {
112
154
  const file =
113
155
  filesByRouteFilePath[
114
156
  path.join(routesDirectoryFromRoot, v.filePath as string)
115
157
  ]
116
158
 
117
159
  if (file) {
118
- const preloads = (file.imports ?? []).map((d) =>
119
- path.join('/', viteManifest[d]!.file),
120
- )
160
+ // Map the relevant imports to their route paths,
161
+ // so that it can be imported in the browser.
162
+ const preloads = (file.imports ?? []).map((d) => {
163
+ const assetPath = joinURL(APP_BASE, viteManifest[d]!.file)
164
+ return assetPath
165
+ })
121
166
 
167
+ // Since this is the most important JS entry for the route,
168
+ // it should be moved to the front of the preloads so that
169
+ // it has the best chance of being loaded first.
122
170
  if (file.file) {
123
- preloads.unshift(path.join('/', file.file))
171
+ preloads.unshift(path.join(APP_BASE, file.file))
124
172
  }
125
173
 
126
- const cssFiles = file.css ?? []
127
- const cssAssetsList: Array<RouterManagedTag> = cssFiles.map(
128
- (cssFile) => ({
129
- tag: 'link',
130
- attrs: {
131
- rel: 'stylesheet',
132
- href: joinURL('/', cssFile),
133
- type: 'text/css',
134
- },
135
- }),
174
+ const cssAssetsList = getCSSRecursively(
175
+ file,
176
+ filesByRouteFilePath,
177
+ APP_BASE,
136
178
  )
137
179
 
138
- routes[k] = {
180
+ routeTreeRoutes[routeId] = {
139
181
  ...v,
140
182
  assets: [...(v.assets || []), ...cssAssetsList],
141
183
  preloads,
@@ -144,34 +186,28 @@ export function startManifestPlugin(
144
186
  })
145
187
 
146
188
  if (entryFile) {
147
- routes[rootRouteId]!.preloads = [
148
- path.join('/', entryFile.file),
189
+ routeTreeRoutes[rootRouteId]!.preloads = [
190
+ joinURL(APP_BASE, entryFile.file),
149
191
  ...(entryFile.imports?.map((d) =>
150
- path.join('/', viteManifest[d]!.file),
192
+ joinURL(APP_BASE, viteManifest[d]!.file),
151
193
  ) || []),
152
194
  ]
153
195
 
154
196
  // Gather all the CSS files from the entry file in
155
197
  // the `css` key and add them to the root route
156
- const entryCssFiles = entryFile.css ?? []
157
- const entryCssAssetsList: Array<RouterManagedTag> = entryCssFiles.map(
158
- (cssFile) => ({
159
- tag: 'link',
160
- attrs: {
161
- rel: 'stylesheet',
162
- href: joinURL('/', cssFile),
163
- type: 'text/css',
164
- },
165
- }),
198
+ const entryCssAssetsList = getCSSRecursively(
199
+ entryFile,
200
+ filesByRouteFilePath,
201
+ APP_BASE,
166
202
  )
167
203
 
168
- routes[rootRouteId]!.assets = [
169
- ...(routes[rootRouteId]!.assets || []),
204
+ routeTreeRoutes[rootRouteId]!.assets = [
205
+ ...(routeTreeRoutes[rootRouteId]!.assets || []),
170
206
  ...entryCssAssetsList,
171
207
  {
172
208
  tag: 'script',
173
209
  attrs: {
174
- src: joinURL('/', entryFile.file),
210
+ src: joinURL(APP_BASE, entryFile.file),
175
211
  type: 'module',
176
212
  },
177
213
  },
@@ -195,22 +231,52 @@ export function startManifestPlugin(
195
231
 
196
232
  if (route.children) {
197
233
  route.children.forEach((child) => {
198
- const childRoute = routes[child]!
234
+ const childRoute = routeTreeRoutes[child]!
199
235
  recurseRoute(childRoute, { ...seenPreloads })
200
236
  })
201
237
  }
202
238
  }
203
239
 
204
240
  // @ts-expect-error
205
- recurseRoute(routes[rootRouteId])
241
+ recurseRoute(routeTreeRoutes[rootRouteId])
206
242
 
207
243
  const routesManifest = {
208
- routes,
244
+ routes: routeTreeRoutes,
245
+ }
246
+
247
+ try {
248
+ const routesManifestOutputDirPath = path.resolve(
249
+ opts.root,
250
+ '.tanstack-start/build/route-assets-manifest',
251
+ )
252
+ rmSync(routesManifestOutputDirPath, {
253
+ recursive: true,
254
+ force: true,
255
+ })
256
+ mkdirSync(routesManifestOutputDirPath, { recursive: true })
257
+ writeFile(
258
+ path.join(routesManifestOutputDirPath, 'manifest.json'),
259
+ JSON.stringify(routesManifest),
260
+ (err) => {
261
+ if (err) {
262
+ console.error(
263
+ 'There was an error writing the routes manifest to disk.\nYou can ignore this error. It does not affect the runtime of your application.',
264
+ )
265
+ console.error(err)
266
+ }
267
+ },
268
+ )
269
+ } catch (err) {
270
+ console.error(
271
+ 'There was an error writing the routes manifest to disk.\nYou can ignore this error. It does not affect the runtime of your application.',
272
+ )
273
+ console.error(err)
209
274
  }
210
275
 
211
276
  return `export const tsrStartManifest = () => (${JSON.stringify(routesManifest)})`
212
277
  }
213
- return
278
+
279
+ return undefined
214
280
  },
215
281
  }
216
282
  }
@@ -30,6 +30,7 @@ const setLock = (bool: boolean) => {
30
30
 
31
31
  export function TanStackStartServerRoutesVite(config: Config): Plugin {
32
32
  let ROOT: string = process.cwd()
33
+ const moduleId = 'tanstack-start-server-routes-manifest:v'
33
34
 
34
35
  const getRoutesDirectoryPath = () => {
35
36
  return isAbsolute(config.routesDirectory)
@@ -80,7 +81,7 @@ export function TanStackStartServerRoutesVite(config: Config): Plugin {
80
81
  },
81
82
  sharedDuringBuild: true,
82
83
  resolveId(id) {
83
- if (id === 'tanstack:server-routes') {
84
+ if (id === moduleId) {
84
85
  const generatedRouteTreePath = getGeneratedRouteTreePath(ROOT)
85
86
  return generatedRouteTreePath
86
87
  }
@@ -244,7 +245,8 @@ async function generator(config: Config, root: string) {
244
245
  removeUnderscores(removeLayoutSegments(node.path)) ?? '',
245
246
  )
246
247
 
247
- const routeCode = node.fullPath
248
+ const stats = fs.statSync(node.fullPath)
249
+ const routeCode = stats.isFile()
248
250
  ? fs.readFileSync(node.fullPath, 'utf-8')
249
251
  : ''
250
252
 
package/src/utils.ts ADDED
@@ -0,0 +1,14 @@
1
+ export function resolveViteId(id: string) {
2
+ return `\0${id}`
3
+ }
4
+
5
+ export function createLogger(prefix: string) {
6
+ const label = `[${prefix}]`
7
+ return {
8
+ log: (...args: any) => console.log(label, ...args),
9
+ debug: (...args: any) => console.debug(label, ...args),
10
+ info: (...args: any) => console.info(label, ...args),
11
+ warn: (...args: any) => console.warn(label, ...args),
12
+ error: (...args: any) => console.error(label, ...args),
13
+ }
14
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"extractHtmlScripts.cjs","sources":["../../src/extractHtmlScripts.ts"],"sourcesContent":["import * as cheerio from 'cheerio'\n\nexport function extractHtmlScripts(\n html: string,\n): Array<{ content?: string; src?: string }> {\n const $ = cheerio.load(html)\n const scripts: Array<{ content?: string; src?: string }> = []\n\n $('script').each((_, element) => {\n const src = $(element).attr('src')\n const content = $(element).html() ?? undefined\n scripts.push({\n src,\n content,\n })\n })\n\n return scripts\n}\n"],"names":["cheerio"],"mappings":";;;;;;;;;;;;;;;;;;;;AAEO,SAAS,mBACd,MAC2C;AACrC,QAAA,IAAIA,mBAAQ,KAAK,IAAI;AAC3B,QAAM,UAAqD,CAAC;AAE5D,IAAE,QAAQ,EAAE,KAAK,CAAC,GAAG,YAAY;AAC/B,UAAM,MAAM,EAAE,OAAO,EAAE,KAAK,KAAK;AACjC,UAAM,UAAU,EAAE,OAAO,EAAE,KAAU,KAAA;AACrC,YAAQ,KAAK;AAAA,MACX;AAAA,MACA;AAAA,IAAA,CACD;AAAA,EAAA,CACF;AAEM,SAAA;AACT;;"}
@@ -1,18 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const fs = require("node:fs");
4
- const path = require("node:path");
5
- const nitropack = require("nitropack");
6
- async function buildNitroEnvironment(nitro, build) {
7
- await nitropack.prepare(nitro);
8
- await nitropack.copyPublicAssets(nitro);
9
- await build();
10
- const publicDir = nitro.options.output.publicDir;
11
- const viteDir = path.resolve(publicDir, ".vite");
12
- if (await fs.promises.stat(viteDir).catch(() => false)) {
13
- await fs.promises.rm(viteDir, { recursive: true, force: true });
14
- }
15
- await nitro.close();
16
- }
17
- exports.buildNitroEnvironment = buildNitroEnvironment;
18
- //# sourceMappingURL=build-nitro.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"build-nitro.cjs","sources":["../../../src/nitro/build-nitro.ts"],"sourcesContent":["import { promises as fsp } from 'node:fs'\nimport path from 'node:path'\nimport { copyPublicAssets, prepare } from 'nitropack'\nimport type { Nitro } from 'nitropack'\n\nexport async function buildNitroEnvironment(\n nitro: Nitro,\n build: () => Promise<any>,\n) {\n await prepare(nitro)\n await copyPublicAssets(nitro)\n await build()\n\n const publicDir = nitro.options.output.publicDir\n\n // As a part of the build process, the `.vite/` directory\n // is copied over from `.tanstack-start/build/client-dist/`\n // to the `publicDir` (e.g. `.output/public/`).\n // This directory (containing the vite manifest) should not be\n // included in the final build, so we remove it here.\n const viteDir = path.resolve(publicDir, '.vite')\n if (await fsp.stat(viteDir).catch(() => false)) {\n await fsp.rm(viteDir, { recursive: true, force: true })\n }\n\n await nitro.close()\n}\n"],"names":["prepare","copyPublicAssets","fsp"],"mappings":";;;;;AAKsB,eAAA,sBACpB,OACA,OACA;AACA,QAAMA,UAAAA,QAAQ,KAAK;AACnB,QAAMC,UAAAA,iBAAiB,KAAK;AAC5B,QAAM,MAAM;AAEN,QAAA,YAAY,MAAM,QAAQ,OAAO;AAOvC,QAAM,UAAU,KAAK,QAAQ,WAAW,OAAO;AAC3C,MAAA,MAAMC,YAAI,KAAK,OAAO,EAAE,MAAM,MAAM,KAAK,GAAG;AACxC,UAAAA,GAAA,SAAI,GAAG,SAAS,EAAE,WAAW,MAAM,OAAO,MAAM;AAAA,EAAA;AAGxD,QAAM,MAAM,MAAM;AACpB;;"}
@@ -1,2 +0,0 @@
1
- import { Nitro } from 'nitropack';
2
- export declare function buildNitroEnvironment(nitro: Nitro, build: () => Promise<any>): Promise<void>;
@@ -1,9 +0,0 @@
1
- export type PagesJson = {
2
- page: string;
3
- lastMod: string;
4
- };
5
- export declare function buildSitemap({ host, routes, outputDir, }: {
6
- host: string;
7
- routes: Array<string | undefined> | (() => Promise<Array<string | undefined>>);
8
- outputDir: string;
9
- }): Promise<void>;
@@ -1 +0,0 @@
1
- {"version":3,"file":"dev-server-plugin.cjs","sources":["../../../src/nitro/dev-server-plugin.ts"],"sourcesContent":["import { createEvent, getHeader, sendWebResponse } from 'h3'\nimport { isRunnableDevEnvironment } from 'vite'\nimport { extractHtmlScripts } from '../extractHtmlScripts'\nimport { VITE_ENVIRONMENT_NAMES } from '../constants'\nimport type { Connect, DevEnvironment, Plugin, ViteDevServer } from 'vite'\n\ndeclare global {\n // eslint-disable-next-line no-var\n var TSS_INJECTED_HEAD_SCRIPTS: string | undefined\n}\n\nexport function devServerPlugin(): Plugin {\n // let config: UserConfig\n let isTest = false\n\n return {\n name: 'start-dev-ssr-plugin',\n config(userConfig, { mode }) {\n // config = userConfig\n isTest = isTest ? isTest : mode === 'test'\n },\n configureServer(viteDevServer) {\n if (isTest) {\n return\n }\n\n ;(globalThis as any).viteDevServer = viteDevServer\n\n return () => {\n remove_html_middlewares(viteDevServer.middlewares)\n let cachedScripts: string | undefined\n viteDevServer.middlewares.use(async (req, res) => {\n const event = createEvent(req, res)\n const serverEnv = viteDevServer.environments[\n VITE_ENVIRONMENT_NAMES.server\n ] as DevEnvironment | undefined\n\n try {\n if (!serverEnv) {\n throw new Error(\n `Server environment ${VITE_ENVIRONMENT_NAMES.server} not found`,\n )\n }\n if (!isRunnableDevEnvironment(serverEnv)) {\n throw new Error(\n `Expected server environment ${VITE_ENVIRONMENT_NAMES.server} to be a RunnableDevEnvironment. This can be caused by multiple vite versions being installed in the project.`,\n )\n }\n if (cachedScripts === undefined) {\n const templateHtml = `<html><head></head><body></body></html>`\n const transformedHtml = await viteDevServer.transformIndexHtml(\n req.url || '/',\n templateHtml,\n )\n const scripts = extractHtmlScripts(transformedHtml)\n globalThis.TSS_INJECTED_HEAD_SCRIPTS = scripts\n .map((script) => script.content ?? '')\n .join(';')\n }\n const serverEntry = await serverEnv.runner.import(\n '/~start/server-entry',\n )\n const response = await serverEntry['default'](event)\n\n return sendWebResponse(event, response)\n } catch (e) {\n console.error(e)\n viteDevServer.ssrFixStacktrace(e as Error)\n\n if (\n getHeader(event, 'content-type')?.includes('application/json')\n ) {\n return sendWebResponse(\n event,\n new Response(\n JSON.stringify(\n {\n status: 500,\n error: 'Internal Server Error',\n message:\n 'An unexpected error occurred. Please try again later.',\n timestamp: new Date().toISOString(),\n },\n null,\n 2,\n ),\n {\n status: 500,\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n ),\n )\n }\n\n return sendWebResponse(\n event,\n new Response(\n `\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <title>Error</title>\n <script type=\"module\">\n import { ErrorOverlay } from '/@vite/client'\n document.body.appendChild(new ErrorOverlay(${JSON.stringify(\n prepareError(req, e),\n ).replace(/</g, '\\\\u003c')}))\n </script>\n </head>\n <body>\n </body>\n </html>\n `,\n {\n status: 500,\n headers: {\n 'Content-Type': 'text/html',\n },\n },\n ),\n )\n }\n })\n }\n },\n }\n}\n\n/**\n * Removes Vite internal middleware\n *\n * @param server\n */\nfunction remove_html_middlewares(server: ViteDevServer['middlewares']) {\n const html_middlewares = [\n 'viteIndexHtmlMiddleware',\n 'vite404Middleware',\n 'viteSpaFallbackMiddleware',\n ]\n for (let i = server.stack.length - 1; i > 0; i--) {\n if (\n html_middlewares.includes(\n // @ts-expect-error\n server.stack[i].handle.name,\n )\n ) {\n server.stack.splice(i, 1)\n }\n }\n}\n\n/**\n * Formats error for SSR message in error overlay\n * @param req\n * @param error\n * @returns\n */\nfunction prepareError(req: Connect.IncomingMessage, error: unknown) {\n const e = error as Error\n return {\n message: `An error occured while server rendering ${req.url}:\\n\\n\\t${\n typeof e === 'string' ? e : e.message\n } `,\n stack: typeof e === 'string' ? '' : e.stack,\n }\n}\n"],"names":["createEvent","VITE_ENVIRONMENT_NAMES","isRunnableDevEnvironment","extractHtmlScripts","sendWebResponse","getHeader"],"mappings":"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"}