wip: prod build for dynamic routes

pull/2005/head
Evan You 2 years ago
parent d6952f37b7
commit 80fb3b0e98

@ -9,6 +9,7 @@ import { bundle, okMark, failMark } from './bundle'
import { createRequire } from 'module' import { createRequire } from 'module'
import { pathToFileURL } from 'url' import { pathToFileURL } from 'url'
import pkgDir from 'pkg-dir' import pkgDir from 'pkg-dir'
import { resolveRoutes } from '../plugins/dynamicRoutesPlugin'
export async function build( export async function build(
root?: string, root?: string,
@ -31,9 +32,16 @@ export async function build(
} }
try { try {
const [dynamicRoutes] = await resolveRoutes(siteConfig.dynamicRoutes)
const allPages = [
...siteConfig.pages,
...dynamicRoutes.map((r) => r.path)
]
const { clientResult, serverResult, pageToHashMap } = await bundle( const { clientResult, serverResult, pageToHashMap } = await bundle(
siteConfig, siteConfig,
buildOptions buildOptions,
allPages
) )
const entryPath = path.join(siteConfig.tempDir, 'app.js') const entryPath = path.join(siteConfig.tempDir, 'app.js')
@ -64,23 +72,21 @@ export async function build(
// as JS object literal. // as JS object literal.
const hashMapString = JSON.stringify(JSON.stringify(pageToHashMap)) const hashMapString = JSON.stringify(JSON.stringify(pageToHashMap))
const pages = ['404.md', ...siteConfig.pages].map(
(page) => siteConfig.rewrites.map[page] || page
)
await Promise.all( await Promise.all(
pages.map((page) => ['404.md', ...allPages]
renderPage( .map((page) => siteConfig.rewrites.map[page] || page)
render, .map((page) =>
siteConfig, renderPage(
page, render,
clientResult, siteConfig,
appChunk, page,
cssChunk, clientResult,
pageToHashMap, appChunk,
hashMapString cssChunk,
pageToHashMap,
hashMapString
)
) )
)
) )
} catch (e) { } catch (e) {
spinner.stopAndPersist({ spinner.stopAndPersist({

@ -20,7 +20,8 @@ export const failMark = '\x1b[31m✖\x1b[0m'
// bundles the VitePress app for both client AND server. // bundles the VitePress app for both client AND server.
export async function bundle( export async function bundle(
config: SiteConfig, config: SiteConfig,
options: BuildOptions options: BuildOptions,
allPages: string[]
): Promise<{ ): Promise<{
clientResult: RollupOutput clientResult: RollupOutput
serverResult: RollupOutput serverResult: RollupOutput
@ -34,7 +35,7 @@ export async function bundle(
// the loading is done via filename conversion rules so that the // the loading is done via filename conversion rules so that the
// metadata doesn't need to be included in the main chunk. // metadata doesn't need to be included in the main chunk.
const input: Record<string, string> = {} const input: Record<string, string> = {}
config.pages.forEach((file) => { allPages.forEach((file) => {
// page filename conversion // page filename conversion
// foo/bar.md -> foo_bar.md // foo/bar.md -> foo_bar.md
const alias = config.rewrites.map[file] || file const alias = config.rewrites.map[file] || file

@ -197,9 +197,13 @@ function resolvePageImports(
page = config.rewrites.inv[page] || page page = config.rewrites.inv[page] || page
// find the page's js chunk and inject script tags for its imports so that // find the page's js chunk and inject script tags for its imports so that
// they start fetching as early as possible // they start fetching as early as possible
const srcPath = normalizePath( let srcPath = page
fs.realpathSync(path.resolve(config.srcDir, page)) try {
) srcPath = normalizePath(fs.realpathSync(path.resolve(config.srcDir, page)))
} catch (e) {
// if the page is a virtual page generated by a dynamic route this would
// fail, which is expected
}
const pageChunk = result.output.find( const pageChunk = result.output.find(
(chunk) => chunk.type === 'chunk' && chunk.facadeModuleId === srcPath (chunk) => chunk.type === 'chunk' && chunk.facadeModuleId === srcPath
) as OutputChunk ) as OutputChunk

@ -9,7 +9,7 @@ import c from 'picocolors'
import path from 'path' import path from 'path'
import type { SiteConfig } from '../config' import type { SiteConfig } from '../config'
export const dynamicRouteRE = /\[(\.\.\.)?\w+\]/ export const dynamicRouteRE = /\[(\w+?)\]/g
interface UserRouteConfig { interface UserRouteConfig {
params: Record<string, string> params: Record<string, string>
@ -26,7 +26,7 @@ interface RouteModule {
dependencies: string[] dependencies: string[]
} }
type ResolvedRouteConfig = UserRouteConfig & { export type ResolvedRouteConfig = UserRouteConfig & {
/** /**
* the raw route, e.g. foo/[bar].md * the raw route, e.g. foo/[bar].md
*/ */
@ -81,6 +81,17 @@ export const dynamicRoutesPlugin = async (
}) })
}, },
resolveId(id) {
if (!id.endsWith('.md')) return
const normalizedId = id.startsWith(config.root)
? normalizePath(path.relative(config.root, id))
: id.replace(/^\//, '')
const matched = resolvedRoutes.find((r) => r.path === normalizedId)
if (matched) {
return normalizedId
}
},
load(id) { load(id) {
const matched = resolvedRoutes.find((r) => r.path === id) const matched = resolvedRoutes.find((r) => r.path === id)
if (matched) { if (matched) {
@ -121,7 +132,7 @@ export const dynamicRoutesPlugin = async (
} }
} }
async function resolveRoutes(routes: string[]) { export async function resolveRoutes(routes: string[]) {
const pendingResolveRoutes: Promise<ResolvedRouteConfig[]>[] = [] const pendingResolveRoutes: Promise<ResolvedRouteConfig[]>[] = []
const routeFileToModulesMap: Record<string, string[]> = {} const routeFileToModulesMap: Record<string, string[]> = {}
@ -165,9 +176,10 @@ async function resolveRoutes(routes: string[]) {
const paths = await (typeof loader === 'function' ? loader() : loader) const paths = await (typeof loader === 'function' ? loader() : loader)
return paths.map((userConfig) => { return paths.map((userConfig) => {
return { return {
path: path: route.replace(
'/' + dynamicRouteRE,
route.replace(/\[(\w+)\]/g, (_, key) => userConfig.params[key]), (_, key) => userConfig.params[key]
),
route, route,
...userConfig ...userConfig
} }

Loading…
Cancel
Save