@tanstack/start-plugin-core 1.167.35 → 1.169.0

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 (187) hide show
  1. package/dist/esm/import-protection/adapterUtils.d.ts +27 -0
  2. package/dist/esm/import-protection/adapterUtils.js +31 -0
  3. package/dist/esm/import-protection/adapterUtils.js.map +1 -0
  4. package/dist/esm/import-protection/analysis.d.ts +36 -0
  5. package/dist/esm/import-protection/analysis.js +407 -0
  6. package/dist/esm/import-protection/analysis.js.map +1 -0
  7. package/dist/esm/{import-protection-plugin → import-protection}/ast.js +1 -1
  8. package/dist/esm/import-protection/ast.js.map +1 -0
  9. package/dist/esm/import-protection/constants.d.ts +11 -0
  10. package/dist/esm/{import-protection-plugin → import-protection}/constants.js +7 -2
  11. package/dist/esm/import-protection/constants.js.map +1 -0
  12. package/dist/esm/{import-protection-plugin → import-protection}/defaults.js +1 -1
  13. package/dist/esm/import-protection/defaults.js.map +1 -0
  14. package/dist/esm/{import-protection-plugin → import-protection}/extensionlessAbsoluteIdResolver.js +2 -2
  15. package/dist/esm/import-protection/extensionlessAbsoluteIdResolver.js.map +1 -0
  16. package/dist/esm/{import-protection-plugin → import-protection}/matchers.js +1 -1
  17. package/dist/esm/import-protection/matchers.js.map +1 -0
  18. package/dist/esm/{import-protection-plugin/rewriteDeniedImports.d.ts → import-protection/rewrite.d.ts} +0 -4
  19. package/dist/esm/import-protection/rewrite.js +121 -0
  20. package/dist/esm/import-protection/rewrite.js.map +1 -0
  21. package/dist/esm/{import-protection-plugin → import-protection}/sourceLocation.d.ts +32 -3
  22. package/dist/esm/{import-protection-plugin → import-protection}/sourceLocation.js +65 -10
  23. package/dist/esm/import-protection/sourceLocation.js.map +1 -0
  24. package/dist/esm/{import-protection-plugin → import-protection}/trace.d.ts +0 -1
  25. package/dist/esm/{import-protection-plugin → import-protection}/trace.js +1 -1
  26. package/dist/esm/import-protection/trace.js.map +1 -0
  27. package/dist/esm/{import-protection-plugin → import-protection}/utils.d.ts +18 -1
  28. package/dist/esm/{import-protection-plugin → import-protection}/utils.js +13 -20
  29. package/dist/esm/import-protection/utils.js.map +1 -0
  30. package/dist/esm/import-protection/virtualModules.d.ts +25 -0
  31. package/dist/esm/{import-protection-plugin → import-protection}/virtualModules.js +5 -117
  32. package/dist/esm/import-protection/virtualModules.js.map +1 -0
  33. package/dist/esm/index.d.ts +1 -5
  34. package/dist/esm/index.js +2 -4
  35. package/dist/esm/post-build.d.ts +9 -0
  36. package/dist/esm/post-build.js +37 -0
  37. package/dist/esm/post-build.js.map +1 -0
  38. package/dist/esm/prerender.d.ts +11 -0
  39. package/dist/esm/prerender.js +159 -0
  40. package/dist/esm/prerender.js.map +1 -0
  41. package/dist/esm/rsbuild/dev-server.d.ts +21 -0
  42. package/dist/esm/rsbuild/dev-server.js +76 -0
  43. package/dist/esm/rsbuild/dev-server.js.map +1 -0
  44. package/dist/esm/rsbuild/import-protection.d.ts +10 -0
  45. package/dist/esm/rsbuild/import-protection.js +775 -0
  46. package/dist/esm/rsbuild/import-protection.js.map +1 -0
  47. package/dist/esm/rsbuild/index.d.ts +4 -0
  48. package/dist/esm/rsbuild/index.js +3 -0
  49. package/dist/esm/rsbuild/normalized-client-build.d.ts +18 -0
  50. package/dist/esm/rsbuild/normalized-client-build.js +207 -0
  51. package/dist/esm/rsbuild/normalized-client-build.js.map +1 -0
  52. package/dist/esm/rsbuild/planning.d.ts +52 -0
  53. package/dist/esm/rsbuild/planning.js +108 -0
  54. package/dist/esm/rsbuild/planning.js.map +1 -0
  55. package/dist/esm/rsbuild/plugin.d.ts +4 -0
  56. package/dist/esm/rsbuild/plugin.js +344 -0
  57. package/dist/esm/rsbuild/plugin.js.map +1 -0
  58. package/dist/esm/rsbuild/post-build.d.ts +6 -0
  59. package/dist/esm/rsbuild/post-build.js +57 -0
  60. package/dist/esm/rsbuild/post-build.js.map +1 -0
  61. package/dist/esm/rsbuild/schema.d.ts +3372 -0
  62. package/dist/esm/rsbuild/schema.js +12 -0
  63. package/dist/esm/rsbuild/schema.js.map +1 -0
  64. package/dist/esm/rsbuild/start-compiler-host.d.ts +20 -0
  65. package/dist/esm/rsbuild/start-compiler-host.js +150 -0
  66. package/dist/esm/rsbuild/start-compiler-host.js.map +1 -0
  67. package/dist/esm/rsbuild/start-router-plugin.d.ts +18 -0
  68. package/dist/esm/rsbuild/start-router-plugin.js +63 -0
  69. package/dist/esm/rsbuild/start-router-plugin.js.map +1 -0
  70. package/dist/esm/rsbuild/swc-rsc.d.ts +14 -0
  71. package/dist/esm/rsbuild/swc-rsc.js +93 -0
  72. package/dist/esm/rsbuild/swc-rsc.js.map +1 -0
  73. package/dist/esm/rsbuild/types.d.ts +17 -0
  74. package/dist/esm/rsbuild/types.js +0 -0
  75. package/dist/esm/rsbuild/virtual-modules.d.ts +53 -0
  76. package/dist/esm/rsbuild/virtual-modules.js +287 -0
  77. package/dist/esm/rsbuild/virtual-modules.js.map +1 -0
  78. package/dist/esm/schema.d.ts +43 -43
  79. package/dist/esm/start-compiler/compiler.d.ts +1 -1
  80. package/dist/esm/start-compiler/compiler.js +80 -9
  81. package/dist/esm/start-compiler/compiler.js.map +1 -1
  82. package/dist/esm/start-compiler/handleCreateServerFn.js +9 -0
  83. package/dist/esm/start-compiler/handleCreateServerFn.js.map +1 -1
  84. package/dist/esm/start-compiler/host.js +5 -1
  85. package/dist/esm/start-compiler/host.js.map +1 -1
  86. package/dist/esm/start-compiler/types.d.ts +1 -0
  87. package/dist/esm/utils.d.ts +1 -0
  88. package/dist/esm/utils.js +10 -1
  89. package/dist/esm/utils.js.map +1 -1
  90. package/dist/esm/{import-protection-plugin → vite/import-protection-plugin}/plugin.js +41 -92
  91. package/dist/esm/vite/import-protection-plugin/plugin.js.map +1 -0
  92. package/dist/esm/{import-protection-plugin → vite/import-protection-plugin}/types.d.ts +5 -5
  93. package/dist/esm/vite/import-protection-plugin/virtualModules.d.ts +8 -0
  94. package/dist/esm/vite/import-protection-plugin/virtualModules.js +49 -0
  95. package/dist/esm/vite/import-protection-plugin/virtualModules.js.map +1 -0
  96. package/dist/esm/vite/index.d.ts +5 -0
  97. package/dist/esm/vite/index.js +4 -0
  98. package/dist/esm/vite/plugin.js +1 -1
  99. package/dist/esm/vite/plugin.js.map +1 -1
  100. package/dist/esm/vite/post-server-build.js +14 -32
  101. package/dist/esm/vite/post-server-build.js.map +1 -1
  102. package/dist/esm/vite/prerender.d.ts +2 -2
  103. package/dist/esm/vite/prerender.js +17 -147
  104. package/dist/esm/vite/prerender.js.map +1 -1
  105. package/dist/esm/vite/schema.d.ts +23 -23
  106. package/dist/esm/vite/start-compiler-plugin/hot-update.d.ts +2 -0
  107. package/dist/esm/vite/start-compiler-plugin/hot-update.js +16 -0
  108. package/dist/esm/vite/start-compiler-plugin/hot-update.js.map +1 -0
  109. package/dist/esm/vite/start-compiler-plugin/module-specifier.js +9 -4
  110. package/dist/esm/vite/start-compiler-plugin/module-specifier.js.map +1 -1
  111. package/dist/esm/vite/start-compiler-plugin/plugin.js +86 -13
  112. package/dist/esm/vite/start-compiler-plugin/plugin.js.map +1 -1
  113. package/package.json +32 -4
  114. package/src/import-protection/INTERNALS.md +266 -0
  115. package/src/import-protection/adapterUtils.ts +94 -0
  116. package/src/import-protection/analysis.ts +853 -0
  117. package/src/{import-protection-plugin → import-protection}/constants.ts +7 -0
  118. package/src/import-protection/rewrite.ts +229 -0
  119. package/src/{import-protection-plugin → import-protection}/sourceLocation.ts +125 -9
  120. package/src/{import-protection-plugin → import-protection}/trace.ts +0 -1
  121. package/src/{import-protection-plugin → import-protection}/utils.ts +36 -21
  122. package/src/{import-protection-plugin → import-protection}/virtualModules.ts +30 -177
  123. package/src/index.ts +1 -8
  124. package/src/post-build.ts +64 -0
  125. package/src/prerender.ts +292 -0
  126. package/src/rsbuild/INTERNALS-import-protection.md +169 -0
  127. package/src/rsbuild/dev-server.ts +129 -0
  128. package/src/rsbuild/import-protection.ts +1599 -0
  129. package/src/rsbuild/index.ts +4 -0
  130. package/src/rsbuild/normalized-client-build.ts +346 -0
  131. package/src/rsbuild/planning.ts +234 -0
  132. package/src/rsbuild/plugin.ts +754 -0
  133. package/src/rsbuild/post-build.ts +96 -0
  134. package/src/rsbuild/schema.ts +31 -0
  135. package/src/rsbuild/start-compiler-host.ts +250 -0
  136. package/src/rsbuild/start-router-plugin.ts +86 -0
  137. package/src/rsbuild/swc-rsc.ts +166 -0
  138. package/src/rsbuild/types.ts +20 -0
  139. package/src/rsbuild/virtual-modules.ts +565 -0
  140. package/src/start-compiler/compiler.ts +153 -19
  141. package/src/start-compiler/handleCreateServerFn.ts +18 -0
  142. package/src/start-compiler/types.ts +1 -0
  143. package/src/utils.ts +14 -0
  144. package/src/vite/import-protection-plugin/INTERNALS.md +187 -0
  145. package/src/{import-protection-plugin → vite/import-protection-plugin}/plugin.ts +73 -158
  146. package/src/{import-protection-plugin → vite/import-protection-plugin}/types.ts +5 -5
  147. package/src/vite/import-protection-plugin/virtualModules.ts +122 -0
  148. package/src/vite/index.ts +8 -0
  149. package/src/vite/plugin.ts +1 -1
  150. package/src/vite/post-server-build.ts +14 -57
  151. package/src/vite/prerender.ts +19 -260
  152. package/src/vite/start-compiler-plugin/hot-update.ts +24 -0
  153. package/src/vite/start-compiler-plugin/module-specifier.ts +15 -5
  154. package/src/vite/start-compiler-plugin/plugin.ts +193 -18
  155. package/dist/esm/import-protection-plugin/ast.js.map +0 -1
  156. package/dist/esm/import-protection-plugin/constants.d.ts +0 -6
  157. package/dist/esm/import-protection-plugin/constants.js.map +0 -1
  158. package/dist/esm/import-protection-plugin/defaults.js.map +0 -1
  159. package/dist/esm/import-protection-plugin/extensionlessAbsoluteIdResolver.js.map +0 -1
  160. package/dist/esm/import-protection-plugin/matchers.js.map +0 -1
  161. package/dist/esm/import-protection-plugin/plugin.js.map +0 -1
  162. package/dist/esm/import-protection-plugin/postCompileUsage.d.ts +0 -13
  163. package/dist/esm/import-protection-plugin/postCompileUsage.js +0 -63
  164. package/dist/esm/import-protection-plugin/postCompileUsage.js.map +0 -1
  165. package/dist/esm/import-protection-plugin/rewriteDeniedImports.js +0 -205
  166. package/dist/esm/import-protection-plugin/rewriteDeniedImports.js.map +0 -1
  167. package/dist/esm/import-protection-plugin/sourceLocation.js.map +0 -1
  168. package/dist/esm/import-protection-plugin/trace.js.map +0 -1
  169. package/dist/esm/import-protection-plugin/utils.js.map +0 -1
  170. package/dist/esm/import-protection-plugin/virtualModules.d.ts +0 -78
  171. package/dist/esm/import-protection-plugin/virtualModules.js.map +0 -1
  172. package/dist/esm/start-compiler/load-module.d.ts +0 -14
  173. package/dist/esm/start-compiler/load-module.js +0 -18
  174. package/dist/esm/start-compiler/load-module.js.map +0 -1
  175. package/src/import-protection-plugin/INTERNALS.md +0 -700
  176. package/src/import-protection-plugin/postCompileUsage.ts +0 -100
  177. package/src/import-protection-plugin/rewriteDeniedImports.ts +0 -379
  178. package/src/start-compiler/load-module.ts +0 -31
  179. /package/dist/esm/{import-protection-plugin → import-protection}/ast.d.ts +0 -0
  180. /package/dist/esm/{import-protection-plugin → import-protection}/defaults.d.ts +0 -0
  181. /package/dist/esm/{import-protection-plugin → import-protection}/extensionlessAbsoluteIdResolver.d.ts +0 -0
  182. /package/dist/esm/{import-protection-plugin → import-protection}/matchers.d.ts +0 -0
  183. /package/dist/esm/{import-protection-plugin → vite/import-protection-plugin}/plugin.d.ts +0 -0
  184. /package/src/{import-protection-plugin → import-protection}/ast.ts +0 -0
  185. /package/src/{import-protection-plugin → import-protection}/defaults.ts +0 -0
  186. /package/src/{import-protection-plugin → import-protection}/extensionlessAbsoluteIdResolver.ts +0 -0
  187. /package/src/{import-protection-plugin → import-protection}/matchers.ts +0 -0
@@ -1,7 +1,6 @@
1
- import { HEADERS } from '@tanstack/start-server-core'
2
- import { buildSitemap } from '../build-sitemap'
3
- import { prerender } from './prerender'
1
+ import { postBuild } from '../post-build'
4
2
  import { getClientOutputDirectory } from './output-directory'
3
+ import { prerenderWithVite } from './prerender'
5
4
  import type { TanStackStartOutputConfig } from '../schema'
6
5
  import type { ViteBuilder } from 'vite'
7
6
 
@@ -12,60 +11,18 @@ export async function postServerBuild({
12
11
  builder: ViteBuilder
13
12
  startConfig: TanStackStartOutputConfig
14
13
  }) {
15
- // If the user has not set a prerender option, we need to set it to true
16
- // if the pages array is not empty and has sub options requiring for prerendering
17
- // If the user has explicitly set prerender.enabled, this should be respected
18
- if (startConfig.prerender?.enabled !== false) {
19
- startConfig.prerender = {
20
- ...startConfig.prerender,
21
- enabled:
22
- startConfig.prerender?.enabled ??
23
- startConfig.pages.some((d) =>
24
- typeof d === 'string' ? false : !!d.prerender?.enabled,
25
- ),
26
- }
27
- }
28
-
29
- // Setup the options for prerendering the SPA shell (i.e `src/routes/__root.tsx`)
30
- if (startConfig.spa?.enabled) {
31
- startConfig.prerender = {
32
- ...startConfig.prerender,
33
- enabled: true,
34
- }
35
-
36
- const maskUrl = new URL(startConfig.spa.maskPath, 'http://localhost')
37
- if (maskUrl.origin !== 'http://localhost') {
38
- throw new Error('spa.maskPath must be a path (no protocol/host)')
39
- }
40
-
41
- startConfig.pages.push({
42
- path: maskUrl.toString().replace('http://localhost', ''),
43
- prerender: {
44
- ...startConfig.spa.prerender,
45
- headers: {
46
- ...startConfig.spa.prerender.headers,
47
- [HEADERS.TSS_SHELL]: 'true',
48
- },
14
+ await postBuild({
15
+ startConfig,
16
+ adapter: {
17
+ getClientOutputDirectory() {
18
+ return getClientOutputDirectory(builder.config)
49
19
  },
50
- sitemap: {
51
- exclude: true,
20
+ prerender(startConfig) {
21
+ return prerenderWithVite({
22
+ startConfig,
23
+ builder,
24
+ })
52
25
  },
53
- })
54
- }
55
-
56
- // Run the prerendering process
57
- if (startConfig.prerender.enabled) {
58
- await prerender({
59
- startConfig,
60
- builder,
61
- })
62
- }
63
-
64
- // Run the sitemap build process
65
- if (startConfig.sitemap?.enabled) {
66
- buildSitemap({
67
- startConfig,
68
- publicDir: getClientOutputDirectory(builder.config),
69
- })
70
- }
26
+ },
27
+ })
71
28
  }
@@ -1,50 +1,16 @@
1
- import { promises as fsp } from 'node:fs'
2
- import os from 'node:os'
3
- import path from 'pathe'
4
- import { joinURL, withBase, withTrailingSlash, withoutBase } from 'ufo'
5
1
  import { VITE_ENVIRONMENT_NAMES } from '../constants'
6
- import { createLogger } from '../utils'
7
- import { Queue } from '../queue'
2
+ import { prerender } from '../prerender'
3
+ import type { PrerenderHandler } from '../prerender'
4
+ import type { TanStackStartOutputConfig } from '../schema'
8
5
  import type { PreviewServer, ResolvedConfig, ViteBuilder } from 'vite'
9
- import type { Page, TanStackStartOutputConfig } from '../schema'
10
6
 
11
- export async function prerender({
7
+ export async function prerenderWithVite({
12
8
  startConfig,
13
9
  builder,
14
10
  }: {
15
11
  startConfig: TanStackStartOutputConfig
16
12
  builder: ViteBuilder
17
13
  }) {
18
- const logger = createLogger('prerender')
19
- logger.info('Prerendering pages...')
20
-
21
- if (startConfig.prerender?.enabled) {
22
- let pages = startConfig.pages.length ? startConfig.pages : [{ path: '/' }]
23
-
24
- if (startConfig.prerender.autoStaticPathsDiscovery ?? true) {
25
- const pagesMap = new Map(pages.map((item) => [item.path, item]))
26
- const discoveredPages = globalThis.TSS_PRERENDABLE_PATHS || []
27
-
28
- for (const page of discoveredPages) {
29
- if (!pagesMap.has(page.path)) {
30
- pagesMap.set(page.path, page)
31
- }
32
- }
33
-
34
- pages = Array.from(pagesMap.values())
35
- }
36
-
37
- startConfig.pages = pages
38
- }
39
-
40
- const routerBasePath = joinURL('/', startConfig.router.basepath ?? '')
41
- const routerBaseUrl = new URL(routerBasePath, 'http://localhost')
42
-
43
- startConfig.pages = validateAndNormalizePrerenderPages(
44
- startConfig.pages,
45
- routerBaseUrl,
46
- )
47
-
48
14
  const serverEnv = builder.environments[VITE_ENVIRONMENT_NAMES.server]
49
15
 
50
16
  if (!serverEnv) {
@@ -68,203 +34,23 @@ export async function prerender({
68
34
  const previewServer = await startPreviewServer(serverEnv.config)
69
35
  const baseUrl = getResolvedUrl(previewServer)
70
36
 
71
- const isRedirectResponse = (res: Response) => {
72
- return res.status >= 300 && res.status < 400 && res.headers.get('location')
73
- }
74
-
75
- async function localFetch(
76
- path: string,
77
- options?: RequestInit,
78
- maxRedirects: number = 5,
79
- ): Promise<Response> {
80
- const url = new URL(path, baseUrl)
81
- const request = new Request(url, options)
82
- const response = await fetch(request)
83
-
84
- if (isRedirectResponse(response) && maxRedirects > 0) {
85
- const location = response.headers.get('location')!
86
- if (location.startsWith('http://localhost') || location.startsWith('/')) {
87
- const newUrl = location.replace('http://localhost', '')
88
- return localFetch(newUrl, options, maxRedirects - 1)
89
- }
90
-
91
- logger.warn(`Skipping redirect to external location: ${location}`)
92
- }
93
-
94
- return response
95
- }
96
-
97
- try {
98
- const pages = await prerenderPages({ outputDir })
99
-
100
- logger.info(`Prerendered ${pages.length} pages:`)
101
- pages.forEach((page) => {
102
- logger.info(`- ${page}`)
103
- })
104
- } catch (error) {
105
- logger.error(error)
106
- } finally {
107
- await previewServer.close()
37
+ const handler: PrerenderHandler = {
38
+ getClientOutputDirectory() {
39
+ return outputDir
40
+ },
41
+ request(path, options) {
42
+ const url = new URL(path, baseUrl)
43
+ return fetch(new Request(url, options))
44
+ },
45
+ close() {
46
+ return previewServer.close()
47
+ },
108
48
  }
109
49
 
110
- function extractLinks(html: string): Array<string> {
111
- const linkRegex = /<a[^>]+href=["']([^"']+)["'][^>]*>/g
112
- const links: Array<string> = []
113
- let match: RegExpExecArray | null
114
-
115
- while ((match = linkRegex.exec(html)) !== null) {
116
- const href = match[1]
117
- if (href && (href.startsWith('/') || href.startsWith('./'))) {
118
- links.push(href)
119
- }
120
- }
121
-
122
- return links
123
- }
124
-
125
- async function prerenderPages({ outputDir }: { outputDir: string }) {
126
- const seen = new Set<string>()
127
- const prerendered = new Set<string>()
128
- const retriesByPath = new Map<string, number>()
129
- const concurrency = startConfig.prerender?.concurrency ?? os.cpus().length
130
- logger.info(`Concurrency: ${concurrency}`)
131
- const queue = new Queue({ concurrency })
132
- const routerBasePath = joinURL('/', startConfig.router.basepath ?? '')
133
-
134
- const routerBaseUrl = new URL(routerBasePath, 'http://localhost')
135
- startConfig.pages = validateAndNormalizePrerenderPages(
136
- startConfig.pages,
137
- routerBaseUrl,
138
- )
139
-
140
- startConfig.pages.forEach((page) => addCrawlPageTask(page))
141
-
142
- if (queue.isSettled()) {
143
- logger.info('No pages matched prerender filter; skipping.')
144
- return Array.from(prerendered)
145
- }
146
-
147
- await queue.start()
148
-
149
- return Array.from(prerendered)
150
-
151
- function addCrawlPageTask(page: Page) {
152
- if (seen.has(page.path)) return
153
-
154
- seen.add(page.path)
155
-
156
- if (page.fromCrawl) {
157
- startConfig.pages.push(page)
158
- }
159
-
160
- if (!(page.prerender?.enabled ?? true)) return
161
-
162
- if (
163
- startConfig.prerender?.filter &&
164
- !startConfig.prerender.filter(page)
165
- ) {
166
- return
167
- }
168
-
169
- const prerenderOptions = {
170
- ...startConfig.prerender,
171
- ...page.prerender,
172
- }
173
-
174
- queue.add(async () => {
175
- logger.info(`Crawling: ${page.path}`)
176
- const retries = retriesByPath.get(page.path) || 0
177
- try {
178
- const res = await localFetch(
179
- withTrailingSlash(withBase(page.path, routerBasePath)),
180
- {
181
- headers: {
182
- ...(prerenderOptions.headers ?? {}),
183
- },
184
- },
185
- prerenderOptions.maxRedirects,
186
- )
187
-
188
- if (!res.ok) {
189
- if (isRedirectResponse(res)) {
190
- logger.warn(`Max redirects reached for ${page.path}`)
191
- }
192
- throw new Error(`Failed to fetch ${page.path}: ${res.statusText}`, {
193
- cause: res,
194
- })
195
- }
196
-
197
- const cleanPagePath = (
198
- prerenderOptions.outputPath || page.path
199
- ).split(/[?#]/)[0]!
200
-
201
- const contentType = res.headers.get('content-type') || ''
202
- const isImplicitHTML =
203
- !cleanPagePath.endsWith('.html') && contentType.includes('html')
204
-
205
- const routeWithIndex = cleanPagePath.endsWith('/')
206
- ? cleanPagePath + 'index'
207
- : cleanPagePath
208
-
209
- const isSpaShell =
210
- startConfig.spa?.prerender.outputPath === cleanPagePath
211
-
212
- let htmlPath: string
213
- if (isSpaShell) {
214
- htmlPath = cleanPagePath + '.html'
215
- } else if (
216
- cleanPagePath.endsWith('/') ||
217
- (prerenderOptions.autoSubfolderIndex ?? true)
218
- ) {
219
- htmlPath = joinURL(cleanPagePath, 'index.html')
220
- } else {
221
- htmlPath = cleanPagePath + '.html'
222
- }
223
-
224
- const filename = withoutBase(
225
- isImplicitHTML ? htmlPath : routeWithIndex,
226
- routerBasePath,
227
- )
228
-
229
- const html = await res.text()
230
-
231
- const filepath = path.join(outputDir, filename)
232
-
233
- await fsp.mkdir(path.dirname(filepath), {
234
- recursive: true,
235
- })
236
-
237
- await fsp.writeFile(filepath, html)
238
-
239
- prerendered.add(page.path)
240
-
241
- const newPage = await prerenderOptions.onSuccess?.({ page, html })
242
-
243
- if (newPage) {
244
- Object.assign(page, newPage)
245
- }
246
-
247
- if (prerenderOptions.crawlLinks ?? true) {
248
- const links = extractLinks(html)
249
- for (const link of links) {
250
- addCrawlPageTask({ path: link, fromCrawl: true })
251
- }
252
- }
253
- } catch (error) {
254
- if (retries < (prerenderOptions.retryCount ?? 0)) {
255
- logger.warn(`Encountered error, retrying: ${page.path} in 500ms`)
256
- await new Promise((resolve) =>
257
- setTimeout(resolve, prerenderOptions.retryDelay),
258
- )
259
- retriesByPath.set(page.path, retries + 1)
260
- addCrawlPageTask(page)
261
- } else if (prerenderOptions.failOnError ?? true) {
262
- throw error
263
- }
264
- }
265
- })
266
- }
267
- }
50
+ return prerender({
51
+ startConfig,
52
+ handler,
53
+ })
268
54
  }
269
55
 
270
56
  async function startPreviewServer(
@@ -299,30 +85,3 @@ function getResolvedUrl(previewServer: PreviewServer): URL {
299
85
 
300
86
  return new URL(baseUrl)
301
87
  }
302
-
303
- function validateAndNormalizePrerenderPages(
304
- pages: Array<Page>,
305
- routerBaseUrl: URL,
306
- ): Array<Page> {
307
- return pages.map((page) => {
308
- let url: URL
309
- try {
310
- url = new URL(page.path, routerBaseUrl)
311
- } catch (err) {
312
- throw new Error(`prerender page path must be relative: ${page.path}`, {
313
- cause: err,
314
- })
315
- }
316
-
317
- if (url.origin !== 'http://localhost') {
318
- throw new Error(`prerender page path must be relative: ${page.path}`)
319
- }
320
-
321
- const decodedPathname = decodeURIComponent(url.pathname)
322
-
323
- return {
324
- ...page,
325
- path: decodedPathname + url.search + url.hash,
326
- }
327
- })
328
- }
@@ -0,0 +1,24 @@
1
+ import type { EnvironmentModuleNode } from 'vite'
2
+
3
+ export function mergeHotUpdateModules(
4
+ currentModules: Array<EnvironmentModuleNode>,
5
+ additionalModules: Array<EnvironmentModuleNode>,
6
+ ): Array<EnvironmentModuleNode> | undefined {
7
+ if (additionalModules.length === 0) {
8
+ return undefined
9
+ }
10
+
11
+ const mergedModules = currentModules.slice()
12
+ const seenModules = new Set(currentModules)
13
+
14
+ for (const mod of additionalModules) {
15
+ if (seenModules.has(mod)) {
16
+ continue
17
+ }
18
+
19
+ seenModules.add(mod)
20
+ mergedModules.push(mod)
21
+ }
22
+
23
+ return mergedModules
24
+ }
@@ -3,16 +3,21 @@ import type { DevServerFnModuleSpecifierEncoder } from '../../start-compiler/typ
3
3
  export function createViteDevServerFnModuleSpecifierEncoder(
4
4
  root: string,
5
5
  ): DevServerFnModuleSpecifierEncoder {
6
- const rootWithTrailingSlash = root.endsWith('/') ? root : `${root}/`
6
+ const normalizedRoot = root.replace(/\\/g, '/')
7
+ const rootWithTrailingSlash = normalizedRoot.endsWith('/')
8
+ ? normalizedRoot
9
+ : `${normalizedRoot}/`
7
10
 
8
11
  return ({ extractedFilename }) => {
9
- let file = extractedFilename
12
+ const normalizedFile = extractedFilename.replace(/\\/g, '/')
10
13
 
11
- if (file.startsWith(rootWithTrailingSlash)) {
12
- file = file.slice(rootWithTrailingSlash.length)
14
+ if (normalizedFile.startsWith(rootWithTrailingSlash)) {
15
+ return `/${normalizedFile.slice(rootWithTrailingSlash.length)}`
13
16
  }
14
17
 
15
- return `/@id/${file}`
18
+ return normalizedFile.startsWith('/')
19
+ ? `/@fs${normalizedFile}`
20
+ : `/@fs/${normalizedFile}`
16
21
  }
17
22
  }
18
23
 
@@ -23,6 +28,11 @@ export function decodeViteDevServerModuleSpecifier(
23
28
 
24
29
  if (sourceFile.startsWith('/@id/')) {
25
30
  sourceFile = sourceFile.slice('/@id/'.length)
31
+ } else if (sourceFile.startsWith('/@fs/')) {
32
+ sourceFile = sourceFile.slice('/@fs'.length)
33
+ sourceFile = sourceFile.replace(/^\/([A-Za-z]:\/)/, '$1')
34
+ } else if (sourceFile.startsWith('/')) {
35
+ sourceFile = sourceFile.slice(1)
26
36
  }
27
37
 
28
38
  const queryIndex = sourceFile.indexOf('?')