diff --git a/src/node/build/build.ts b/src/node/build/build.ts
index 0b1da0c2d..3bce78bd9 100644
--- a/src/node/build/build.ts
+++ b/src/node/build/build.ts
@@ -65,39 +65,42 @@ export async function build(
const { render } = await nativeImport(entryPath)
await task('rendering pages', async () => {
- const appChunk =
- clientResult &&
- (clientResult.output.find(
- (chunk) =>
- chunk.type === 'chunk' &&
- chunk.isEntry &&
- chunk.facadeModuleId?.endsWith('.js')
- ) as Rolldown.OutputChunk)
-
- const cssChunk = (
- siteConfig.mpa ? serverResult : clientResult!
- ).output.find(
- (chunk) => chunk.type === 'asset' && chunk.fileName.endsWith('.css')
- ) as Rolldown.OutputAsset
-
- const assets = (siteConfig.mpa ? serverResult : clientResult!).output
- .filter(
- (chunk) => chunk.type === 'asset' && !chunk.fileName.endsWith('.css')
- )
- .map((asset) => siteConfig.site.base + asset.fileName)
+ const clientOutput: (Rolldown.OutputChunk | Rolldown.OutputAsset)[] =
+ clientResult?.output || []
+
+ const appChunk = clientOutput.find(
+ (chunk): chunk is Rolldown.OutputChunk =>
+ chunk.type === 'chunk' &&
+ chunk.isEntry &&
+ !!chunk.facadeModuleId?.endsWith('.js')
+ )
- // default theme special handling: inject font preload
- // custom themes will need to use `transformHead` to inject this
- const additionalHeadTags: HeadConfig[] = []
- const isDefaultTheme =
- clientResult &&
- clientResult.output.some(
- (chunk) =>
- chunk.type === 'chunk' &&
- chunk.name === 'theme' &&
- chunk.moduleIds.some((id) => id.includes('client/theme-default'))
- )
+ const isDefaultTheme = clientOutput.some(
+ (chunk): chunk is Rolldown.OutputChunk =>
+ chunk.type === 'chunk' &&
+ chunk.name === 'theme' &&
+ chunk.moduleIds.some((id) => id.includes('client/theme-default'))
+ )
+
+ // ----
+ const resultOutput: (Rolldown.OutputChunk | Rolldown.OutputAsset)[] =
+ (siteConfig.mpa ? serverResult : clientResult)?.output || []
+
+ const cssChunk = resultOutput.find(
+ (chunk): chunk is Rolldown.OutputAsset =>
+ chunk.type === 'asset' && chunk.fileName.endsWith('.css')
+ )
+
+ // prettier-ignore
+ const assets = resultOutput.filter(
+ (chunk): chunk is Rolldown.OutputAsset =>
+ chunk.type === 'asset' && !chunk.fileName.endsWith('.css')
+ ).map((asset) => siteConfig.site.base + asset.fileName)
+
+ // ----
+
+ const additionalHeadTags: HeadConfig[] = []
const metadataScript = generateMetadataScript(pageToHashMap, siteConfig)
if (isDefaultTheme) {
diff --git a/src/node/build/bundle.ts b/src/node/build/bundle.ts
index ad25459b7..f851b3d58 100644
--- a/src/node/build/bundle.ts
+++ b/src/node/build/bundle.ts
@@ -2,6 +2,7 @@ import fs from 'node:fs'
import { cp } from 'node:fs/promises'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
+import pMap from 'p-map'
import {
build,
normalizePath,
@@ -102,8 +103,8 @@ export async function bundle(
app: path.resolve(APP_PATH, ssr ? 'ssr.js' : 'index.js'),
...input
},
- // important so that each page chunk and the index export things for each
- // other
+ // important so that each page chunk and the index export things for
+ // each other
preserveEntrySignatures: 'allow-extension',
output: {
sanitizeFileName,
@@ -170,42 +171,40 @@ export async function bundle(
configFile: config.vite?.configFile
})
- let clientResult!: Rolldown.RolldownOutput | null
+ let clientResult: Rolldown.RolldownOutput | null = null
let serverResult!: Rolldown.RolldownOutput
+ // prettier-ignore
await task('building client + server bundles', async () => {
- clientResult = config.mpa
- ? null
- : ((await build(
- await resolveViteConfig(false)
- )) as Rolldown.RolldownOutput)
- serverResult = (await build(
- await resolveViteConfig(true)
- )) as Rolldown.RolldownOutput
+ if (!config.mpa) clientResult =
+ (await build(await resolveViteConfig(false))) as Rolldown.RolldownOutput
+ serverResult =
+ (await build(await resolveViteConfig(true))) as Rolldown.RolldownOutput
})
if (config.mpa) {
// in MPA mode, we need to copy over the non-js asset files from the
// server build since there is no client-side build.
- await Promise.all(
- serverResult.output.map(async (chunk) => {
+ await pMap(
+ serverResult.output,
+ async (chunk) => {
if (!chunk.fileName.endsWith('.js')) {
const tempPath = path.resolve(config.tempDir, chunk.fileName)
const outPath = path.resolve(config.outDir, chunk.fileName)
await cp(tempPath, outPath)
}
- })
+ },
+ { concurrency: config.buildConcurrency }
)
+
// also copy over public dir
const publicDir = path.resolve(config.srcDir, 'public')
if (fs.existsSync(publicDir)) {
// dereference symlinks like vite's own publicDir copy does, and so that
// copying over an existing symlinked file does not fail with EEXIST
- await cp(publicDir, config.outDir, {
- recursive: true,
- dereference: true
- })
+ await cp(publicDir, config.outDir, { recursive: true, dereference: true })
}
+
// build `
@@ -227,12 +227,13 @@ function resolvePageImports(
}
srcPath = normalizePath(srcPath)
const pageChunk = result.output.find(
- (chunk) => chunk.type === 'chunk' && chunk.facadeModuleId === srcPath
- ) as Rolldown.OutputChunk
+ (chunk): chunk is Rolldown.OutputChunk =>
+ chunk.type === 'chunk' && chunk.facadeModuleId === srcPath
+ )
return [
...appChunk.imports,
// ...appChunk.dynamicImports,
- ...pageChunk.imports
+ ...(pageChunk?.imports || [])
// ...pageChunk.dynamicImports
]
}
diff --git a/src/node/plugin.ts b/src/node/plugin.ts
index 09bc3e88f..e415bde67 100644
--- a/src/node/plugin.ts
+++ b/src/node/plugin.ts
@@ -53,14 +53,13 @@ const staticRestoreRE = /__VP_STATIC_(START|END)__/g
// media queries.
const scriptClientRE = /