fix(build): handle vite constants replacement (#419) (#888)

pull/896/head
meteorlxy 2 years ago committed by GitHub
parent a2b1490a01
commit 9d9db6227d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -34,14 +34,7 @@ export async function createMarkdownToVueRenderFn(
pages = pages.map((p) => slash(p.replace(/\.md$/, '')))
const userDefineRegex = userDefines
? new RegExp(
`\\b(${Object.keys(userDefines)
.map((key) => key.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'))
.join('|')})`,
'g'
)
: null
const replaceRegex = genReplaceRegexp(userDefines, isBuild)
return async (
src: string,
@ -74,24 +67,9 @@ export async function createMarkdownToVueRenderFn(
md.__path = file
md.__relativePath = relativePath
let html = md.render(content)
const html = md.render(content)
const data = md.__data
if (isBuild) {
// avoid env variables being replaced by vite
html = html
.replace(/\bimport\.meta/g, 'import.<wbr/>meta')
.replace(/\bprocess\.env/g, 'process.<wbr/>env')
// also avoid replacing vite user defines
if (userDefineRegex) {
html = html.replace(
userDefineRegex,
(_) => `${_[0]}<wbr/>${_.slice(1)}`
)
}
}
// validate data.links
const deadLinks: string[] = []
const recordDeadLink = (url: string) => {
@ -149,8 +127,14 @@ export async function createMarkdownToVueRenderFn(
}
const vueSrc =
genPageDataCode(data.hoistedTags || [], pageData).join('\n') +
`\n<template><div>${html}</div></template>`
genPageDataCode(data.hoistedTags || [], pageData, replaceRegex).join(
'\n'
) +
`\n<template><div>${replaceConstants(
html,
replaceRegex,
vueTemplateBreaker
)}</div></template>`
debug(`[render] ${file} in ${Date.now() - start}ms.`)
@ -171,10 +155,42 @@ const scriptSetupRE = /<\s*script[^>]*\bsetup\b[^>]*/
const scriptClientRE = /<\s*script[^>]*\bclient\b[^>]*/
const defaultExportRE = /((?:^|\n|;)\s*)export(\s*)default/
const namedDefaultExportRE = /((?:^|\n|;)\s*)export(.+)as(\s*)default/
const jsStringBreaker = '\u200b'
const vueTemplateBreaker = '<wbr>'
function genReplaceRegexp(
userDefines: Record<string, any> = {},
isBuild: boolean
): RegExp {
// `process.env` need to be handled in both dev and build
// @see https://github.com/vitejs/vite/blob/cad27ee8c00bbd5aeeb2be9bfb3eb164c1b77885/packages/vite/src/node/plugins/clientInjections.ts#L57-L64
const replacements = ['process.env']
if (isBuild) {
replacements.push('import.meta', ...Object.keys(userDefines))
}
return new RegExp(
`\\b(${replacements
.map((key) => key.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'))
.join('|')})`,
'g'
)
}
/**
* To avoid env variables being replaced by vite:
* - insert `'\u200b'` char into those strings inside js string (page data)
* - insert `<wbr>` tag into those strings inside html string (vue template)
*
* @see https://vitejs.dev/guide/env-and-mode.html#production-replacement
*/
function replaceConstants(str: string, replaceRegex: RegExp, breaker: string) {
return str.replace(replaceRegex, (_) => `${_[0]}${breaker}${_.slice(1)}`)
}
function genPageDataCode(tags: string[], data: PageData) {
function genPageDataCode(tags: string[], data: PageData, replaceRegex: RegExp) {
const dataJson = JSON.stringify(data)
const code = `\nexport const __pageData = JSON.parse(${JSON.stringify(
JSON.stringify(data)
replaceConstants(dataJson, replaceRegex, jsStringBreaker)
)})`
const existingScriptIndex = tags.findIndex((tag) => {

Loading…
Cancel
Save