diff --git a/src/build/build.ts b/src/build/build.ts index ec1d5c83..d34caafe 100644 --- a/src/build/build.ts +++ b/src/build/build.ts @@ -14,11 +14,11 @@ export type BuildOptions = Pick< export async function build(buildOptions: BuildOptions = {}) { const siteConfig = await resolveConfig(buildOptions.root) try { - const result = await bundle(siteConfig, buildOptions) + const [clientResult] = await bundle(siteConfig, buildOptions) console.log('rendering pages...') for (const page of siteConfig.pages) { - await renderPage(siteConfig, page, result) + await renderPage(siteConfig, page, clientResult) } if (await exists(siteConfig.publicDir)) { diff --git a/src/build/render.ts b/src/build/render.ts index 4b7eab7f..79e5197a 100644 --- a/src/build/render.ts +++ b/src/build/render.ts @@ -3,13 +3,14 @@ import { promises as fs } from 'fs' import { SiteConfig, HeadConfig } from '../config' import { BuildResult } from 'vite' import { renderToString } from '@vue/server-renderer' +import { OutputChunk } from 'rollup' const escape = require('escape-html') export async function renderPage( config: SiteConfig, page: string, // foo.md - result: BuildResult[] + result: BuildResult ) { const { createApp } = require(path.join(config.tempDir, '_assets/index.js')) const { app, router } = createApp() @@ -17,15 +18,29 @@ export async function renderPage( router.go(routePath) const content = await renderToString(app) - const assetPath = `${config.site.base}_assets` - const pageJsPath = page.replace(/\//g, '_') + '.js' + const pageJsFileName = page.replace(/\//g, '_') + '.js' + + // resolve page data so we can render head tags const { __pageData } = require(path.join( config.tempDir, '_assets', - pageJsPath + pageJsFileName )) const pageData = JSON.parse(__pageData) + const assetPath = `${config.site.base}_assets` + const renderScript = (file: string) => { + return `` + } + + // resolve imports for index.js + page.md.js and inject script tags for + // them as well so we fetch everything as early as possible without having + // to wait for entry chunks to parse + const pageImports = resolvePageImports(config, page, result) + const pageImportScripts = pageImports.length + ? pageImports.map((i) => renderScript(i)).join('\n') + `\n ` + : `` + const html = ` @@ -39,8 +54,8 @@ export async function renderPage(
${content}
- - + ${pageImportScripts}${renderScript(pageJsFileName)} + ${renderScript(`index.js`)} `.trim() const htmlFileName = path.join(config.outDir, page.replace(/\.md$/, '.html')) @@ -48,6 +63,23 @@ export async function renderPage( await fs.writeFile(htmlFileName, html) } +function resolvePageImports( + config: SiteConfig, + page: string, + result: BuildResult +) { + // find the page's js chunk and inject script tags for its imports so that + // they are start fetching as early as possible + const indexChunk = result.js.find( + (chunk) => chunk.type === 'chunk' && chunk.fileName === `_assets/index.js` + ) as OutputChunk + const srcPath = path.join(config.root, page) + const pageChunk = result.js.find( + (chunk) => chunk.type === 'chunk' && chunk.facadeModuleId === srcPath + ) as OutputChunk + return Array.from(new Set([...indexChunk.imports, ...pageChunk.imports])) +} + function renderHead(head: HeadConfig[]) { if (!head || !head.length) { return ''