wip: hmr for dynamic routes on add/delete

pull/2005/head
Evan You 2 years ago
parent 08df389db8
commit d6952f37b7

@ -349,6 +349,6 @@ export async function createVitePressPlugin(
webFontsPlugin(siteConfig.useWebFonts), webFontsPlugin(siteConfig.useWebFonts),
...(userViteConfig?.plugins || []), ...(userViteConfig?.plugins || []),
staticDataPlugin, staticDataPlugin,
await dynamicRoutesPlugin(siteConfig.dynamicRoutes) await dynamicRoutesPlugin(siteConfig)
] ]
} }

@ -1,7 +1,13 @@
import { loadConfigFromFile, type Plugin, type ViteDevServer } from 'vite' import {
loadConfigFromFile,
normalizePath,
type Plugin,
type ViteDevServer
} from 'vite'
import fs from 'fs-extra' import fs from 'fs-extra'
import c from 'picocolors' import c from 'picocolors'
import path from 'path' import path from 'path'
import type { SiteConfig } from '../config'
export const dynamicRouteRE = /\[(\.\.\.)?\w+\]/ export const dynamicRouteRE = /\[(\.\.\.)?\w+\]/
@ -32,25 +38,54 @@ type ResolvedRouteConfig = UserRouteConfig & {
} }
export const dynamicRoutesPlugin = async ( export const dynamicRoutesPlugin = async (
initialRoutes: string[] config: SiteConfig
): Promise<Plugin> => { ): Promise<Plugin> => {
let server: ViteDevServer let server: ViteDevServer
let [resolvedRoutes, routeFileToModulesMap] = await resolveRoutes( let routes = config.dynamicRoutes
initialRoutes let [resolvedRoutes, routeFileToModulesMap] = await resolveRoutes(routes)
)
// TODO: make this more efficient by only reloading the invalidated route
// TODO: invlidate modules for paths that are no longer present
async function invlidateRoutes() {
;[resolvedRoutes, routeFileToModulesMap] = await resolveRoutes(routes)
}
return { return {
name: 'vitepress:dynamic-routes', name: 'vitepress:dynamic-routes',
configureServer(_server) { configureServer(_server) {
server = _server server = _server
const onFileAddDelete = (
file: string,
updateRoutes: (route: string) => void
) => {
if (dynamicRouteRE.test(file) && /\.(md|paths\.[jt]s)$/.test(file)) {
if (file.endsWith('.md')) {
updateRoutes(normalizePath(path.relative(config.root, file)))
}
invlidateRoutes().then(() => {
server.ws.send({ type: 'full-reload' })
})
}
}
server.watcher
.on('add', (file) => {
onFileAddDelete(file, (route) => routes.push(route))
})
.on('unlink', (file) => {
onFileAddDelete(file, (route) => {
routes = routes.filter((r) => r !== route)
})
})
}, },
load(id) { load(id) {
const matched = resolvedRoutes.find((r) => r.path === id) const matched = resolvedRoutes.find((r) => r.path === id)
if (matched) { if (matched) {
const { route, params, content } = matched const { route, params, content } = matched
const routeFile = path.resolve(route) const routeFile = normalizePath(path.resolve(config.root, route))
routeFileToModulesMap[routeFile].push(id) routeFileToModulesMap[routeFile].push(id)
let baseContent = fs.readFileSync(routeFile, 'utf-8') let baseContent = fs.readFileSync(routeFile, 'utf-8')
@ -75,12 +110,8 @@ export const dynamicRoutesPlugin = async (
const mods = routeFileToModulesMap[ctx.file] const mods = routeFileToModulesMap[ctx.file]
if (mods) { if (mods) {
// path loader module updated, reset loaded routes // path loader module updated, reset loaded routes
// TODO: make this more efficient by only reloading the invalidated route
// TODO: invlidate modules for paths that are no longer present
if (/\.paths\.[jt]s$/.test(ctx.file)) { if (/\.paths\.[jt]s$/.test(ctx.file)) {
;[resolvedRoutes, routeFileToModulesMap] = await resolveRoutes( await invlidateRoutes()
initialRoutes
)
} }
for (const id of mods) { for (const id of mods) {
ctx.modules.push(server.moduleGraph.getModuleById(id)!) ctx.modules.push(server.moduleGraph.getModuleById(id)!)

Loading…
Cancel
Save