From e0b69973f840bfa281fae209da1f1c674c1301a8 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 13 Sep 2021 23:56:11 -0400 Subject: [PATCH] feat: support `` + fs.removeSync(path.resolve(config.outDir, matchingChunk.fileName)) + } else { + inlinedScript = `` + } + } + } + const html = ` @@ -87,10 +111,16 @@ export async function renderPage(
${content}
${ config.mpa - ? `` - : `` + - `` - } + ? '' + : `` + } + ${ + appChunk + ? `` + : `` + } + ${inlinedScript} + `.trim() const htmlFileName = path.join(config.outDir, page.replace(/\.md$/, '.html')) await fs.ensureDir(path.dirname(htmlFileName)) diff --git a/src/node/config.ts b/src/node/config.ts index 20dac3686e32..a367ac677a50 100644 --- a/src/node/config.ts +++ b/src/node/config.ts @@ -45,6 +45,7 @@ export interface UserConfig { /** * Enable MPA / zero-JS mode + * @experimental */ mpa?: boolean } diff --git a/src/node/markdownToVue.ts b/src/node/markdownToVue.ts index fc4b36c58dd5..280d4b47c293 100644 --- a/src/node/markdownToVue.ts +++ b/src/node/markdownToVue.ts @@ -133,6 +133,7 @@ export function createMarkdownToVueRenderFn( const scriptRE = /<\/script>/ 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/ @@ -142,7 +143,11 @@ function genPageDataCode(tags: string[], data: PageData) { )}` const existingScriptIndex = tags.findIndex((tag) => { - return scriptRE.test(tag) && !scriptSetupRE.test(tag) + return ( + scriptRE.test(tag) && + !scriptSetupRE.test(tag) && + !scriptClientRe.test(tag) + ) }) if (existingScriptIndex > -1) { diff --git a/src/node/plugin.ts b/src/node/plugin.ts index 2da0847f0937..9c8e9f504a83 100644 --- a/src/node/plugin.ts +++ b/src/node/plugin.ts @@ -16,6 +16,11 @@ const staticInjectMarkerRE = const staticStripRE = /__VP_STATIC_START__.*?__VP_STATIC_END__/g const staticRestoreRE = /__VP_STATIC_(START|END)__/g +// matches client-side js blocks in MPA mode. +// in the future we may add different execution strategies like visible or +// media queries. +const scriptClientRE = /]*client\b[^>]*>([^]*?)<\/script>/ + const isPageChunk = ( chunk: OutputAsset | OutputChunk ): chunk is OutputChunk & { facadeModuleId: string } => @@ -28,7 +33,12 @@ const isPageChunk = ( export function createVitePressPlugin( root: string, - { + siteConfig: SiteConfig, + ssr = false, + pageToHashMap?: Record, + clientJSMap?: Record +): Plugin[] { + const { srcDir, configPath, alias, @@ -37,10 +47,8 @@ export function createVitePressPlugin( vue: userVuePluginOptions, vite: userViteConfig, pages - }: SiteConfig, - ssr = false, - pageToHashMap?: Record -): Plugin[] { + } = siteConfig + let markdownToVue: ( src: string, file: string, @@ -52,6 +60,15 @@ export function createVitePressPlugin( ...userVuePluginOptions }) + const processClientJS = (code: string, id: string) => { + return scriptClientRE.test(code) + ? code.replace(scriptClientRE, (_, content) => { + if (ssr && clientJSMap) clientJSMap[id] = content + return `\n`.repeat(_.split('\n').length - 1) + }) + : code + } + let siteData = site let hasDeadLinks = false let config: ResolvedConfig @@ -109,7 +126,9 @@ export function createVitePressPlugin( }, transform(code, id) { - if (id.endsWith('.md')) { + if (id.endsWith('.vue')) { + return processClientJS(code, id) + } else if (id.endsWith('.md')) { // transform .md files into vueSrc so plugin-vue can handle it const { vueSrc, deadLinks, includes } = markdownToVue( code, @@ -124,7 +143,7 @@ export function createVitePressPlugin( this.addWatchFile(i) }) } - return vueSrc + return processClientJS(vueSrc, id) } },