|
|
|
@ -1,3 +1,4 @@
|
|
|
|
|
import { createHash } from 'crypto'
|
|
|
|
|
import fs from 'fs-extra'
|
|
|
|
|
import { createRequire } from 'module'
|
|
|
|
|
import ora from 'ora'
|
|
|
|
@ -7,9 +8,9 @@ import { rimraf } from 'rimraf'
|
|
|
|
|
import type { OutputAsset, OutputChunk } from 'rollup'
|
|
|
|
|
import { pathToFileURL } from 'url'
|
|
|
|
|
import type { BuildOptions } from 'vite'
|
|
|
|
|
import { resolveConfig } from '../config'
|
|
|
|
|
import type { HeadConfig } from '../shared'
|
|
|
|
|
import { serializeFunctions } from '../utils/fnSerialize'
|
|
|
|
|
import { resolveConfig, type SiteConfig } from '../config'
|
|
|
|
|
import { slash, type HeadConfig } from '../shared'
|
|
|
|
|
import { deserializeFunctions, serializeFunctions } from '../utils/fnSerialize'
|
|
|
|
|
import { bundle, failMark, okMark } from './bundle'
|
|
|
|
|
import { renderPage } from './render'
|
|
|
|
|
|
|
|
|
@ -79,6 +80,8 @@ export async function build(
|
|
|
|
|
chunk.moduleIds.some((id) => id.includes('client/theme-default'))
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const metadataScript = generateMetadataScript(pageToHashMap, siteConfig)
|
|
|
|
|
|
|
|
|
|
if (isDefaultTheme) {
|
|
|
|
|
const fontURL = assets.find((file) =>
|
|
|
|
|
/inter-roman-latin\.\w+\.woff2/.test(file)
|
|
|
|
@ -97,15 +100,6 @@ export async function build(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We embed the hash map and site config strings into each page directly
|
|
|
|
|
// so that it doesn't alter the main chunk's hash on every build.
|
|
|
|
|
// It's also embedded as a string and JSON.parsed from the client because
|
|
|
|
|
// it's faster than embedding as JS object literal.
|
|
|
|
|
const hashMapString = JSON.stringify(JSON.stringify(pageToHashMap))
|
|
|
|
|
const siteDataString = JSON.stringify(
|
|
|
|
|
JSON.stringify(serializeFunctions({ ...siteConfig.site, head: [] }))
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
await Promise.all(
|
|
|
|
|
['404.md', ...siteConfig.pages]
|
|
|
|
|
.map((page) => siteConfig.rewrites.map[page] || page)
|
|
|
|
@ -119,8 +113,7 @@ export async function build(
|
|
|
|
|
cssChunk,
|
|
|
|
|
assets,
|
|
|
|
|
pageToHashMap,
|
|
|
|
|
hashMapString,
|
|
|
|
|
siteDataString,
|
|
|
|
|
metadataScript,
|
|
|
|
|
additionalHeadTags
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
@ -168,3 +161,51 @@ function linkVue() {
|
|
|
|
|
}
|
|
|
|
|
return () => {}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function generateMetadataScript(
|
|
|
|
|
pageToHashMap: Record<string, string>,
|
|
|
|
|
config: SiteConfig
|
|
|
|
|
) {
|
|
|
|
|
if (config.mpa) {
|
|
|
|
|
return { html: '', inHead: false }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We embed the hash map and site config strings into each page directly
|
|
|
|
|
// so that it doesn't alter the main chunk's hash on every build.
|
|
|
|
|
// It's also embedded as a string and JSON.parsed from the client because
|
|
|
|
|
// it's faster than embedding as JS object literal.
|
|
|
|
|
const hashMapString = JSON.stringify(JSON.stringify(pageToHashMap))
|
|
|
|
|
const siteDataString = JSON.stringify(
|
|
|
|
|
JSON.stringify(serializeFunctions({ ...config.site, head: [] }))
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const metadataContent = `window.__VP_HASH_MAP__=JSON.parse(${hashMapString});${
|
|
|
|
|
siteDataString.includes('_vp-fn_')
|
|
|
|
|
? `${deserializeFunctions.toString()};window.__VP_SITE_DATA__=deserializeFunctions(JSON.parse(${siteDataString}));`
|
|
|
|
|
: `window.__VP_SITE_DATA__=JSON.parse(${siteDataString});`
|
|
|
|
|
}`
|
|
|
|
|
|
|
|
|
|
if (!config.metaChunk) {
|
|
|
|
|
return { html: `<script>${metadataContent}</script>`, inHead: false }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const metadataFile = path.join(
|
|
|
|
|
config.assetsDir,
|
|
|
|
|
'chunks',
|
|
|
|
|
`metadata.${createHash('sha256')
|
|
|
|
|
.update(metadataContent)
|
|
|
|
|
.digest('hex')
|
|
|
|
|
.slice(0, 8)}.js`
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const resolvedMetadataFile = path.join(config.outDir, metadataFile)
|
|
|
|
|
const metadataFileURL = slash(`${config.site.base}${metadataFile}`)
|
|
|
|
|
|
|
|
|
|
fs.ensureDirSync(path.dirname(resolvedMetadataFile))
|
|
|
|
|
fs.writeFileSync(resolvedMetadataFile, metadataContent)
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
html: `<script type="module" src="${metadataFileURL}"></script>`,
|
|
|
|
|
inHead: true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|