wip: handle config hmr

pull/198/head
Evan You 4 years ago
parent bf8fd3a6f3
commit 084c7deb02

@ -16,7 +16,7 @@ function parse(data: string): SiteData {
// hmr // hmr
if (import.meta.hot) { if (import.meta.hot) {
import.meta.hot!.accept('/@siteData', (m) => { import.meta.hot.accept('/@siteData', (m) => {
siteDataRef.value = parse(m.default) siteDataRef.value = parse(m.default)
}) })
} }

@ -12,8 +12,6 @@ import { useSiteDataByRoute, usePageData } from 'vitepress'
const site = useSiteDataByRoute() const site = useSiteDataByRoute()
const page = usePageData() const page = usePageData()
const datetime = ref('')
const hasLastUpdated = computed(() => { const hasLastUpdated = computed(() => {
const lu = site.value.themeConfig.lastUpdated const lu = site.value.themeConfig.lastUpdated
@ -22,12 +20,11 @@ const hasLastUpdated = computed(() => {
const prefix = computed(() => { const prefix = computed(() => {
const p = site.value.themeConfig.lastUpdated const p = site.value.themeConfig.lastUpdated
return p === true ? 'Last Updated' : p return p === true ? 'Last Updated' : p
}) })
onMounted(() => { const datetime = computed(() => {
datetime.value = new Date(page.value.lastUpdated).toLocaleString('en-US') return new Date(page.value.lastUpdated).toLocaleString('en-US')
}) })
</script> </script>

@ -15,13 +15,7 @@ if (root) {
if (!command || command === 'dev') { if (!command || command === 'dev') {
createServer(root, argv) createServer(root, argv)
.then((server) => { .then((server) => server.listen())
return server.listen().then(() => {
console.log(
`listening at http://localhost:${server.config.server.port}`
)
})
})
.catch((err) => { .catch((err) => {
console.error(chalk.red(`failed to start server. error:\n`), err) console.error(chalk.red(`failed to start server. error:\n`), err)
process.exit(1) process.exit(1)

@ -8,12 +8,7 @@ import { PageData, HeadConfig } from '../../types/shared'
import slash from 'slash' import slash from 'slash'
const debug = require('debug')('vitepress:md') const debug = require('debug')('vitepress:md')
const cache = new LRUCache<string, MarkdownCompileCachedResult>({ max: 1024 }) const cache = new LRUCache<string, MarkdownCompileResult>({ max: 1024 })
interface MarkdownCompileCachedResult extends MarkdownCompileResult {
tagsWithPageData: string
tagsWithoutPageData: string
}
interface MarkdownCompileResult { interface MarkdownCompileResult {
vueSrc: string vueSrc: string
@ -26,17 +21,13 @@ export function createMarkdownToVueRenderFn(
) { ) {
const md = createMarkdownRenderer(options) const md = createMarkdownRenderer(options)
return ( return (src: string, file: string): MarkdownCompileResult => {
src: string,
file: string,
injectData = true
): MarkdownCompileResult => {
const relativePath = slash(path.relative(root, file)) const relativePath = slash(path.relative(root, file))
const cached = cache.get(src) const cached = cache.get(src)
if (cached) { if (cached) {
debug(`[cache hit] ${relativePath}`) debug(`[cache hit] ${relativePath}`)
return pickResult(cached, injectData) return cached
} }
const start = Date.now() const start = Date.now()
@ -44,8 +35,6 @@ export function createMarkdownToVueRenderFn(
const { content, data: frontmatter } = matter(src) const { content, data: frontmatter } = matter(src)
const { html, data } = md.render(content) const { html, data } = md.render(content)
const vueSrc = `\n<template><div>${html}</div></template>`
// TODO validate data.links? // TODO validate data.links?
const pageData: PageData = { const pageData: PageData = {
title: inferTitle(frontmatter, content), title: inferTitle(frontmatter, content),
@ -54,38 +43,21 @@ export function createMarkdownToVueRenderFn(
headers: data.headers, headers: data.headers,
relativePath, relativePath,
// TODO use git timestamp? // TODO use git timestamp?
lastUpdated: fs.statSync(file).mtimeMs lastUpdated: Math.round(fs.statSync(file).mtimeMs)
} }
const tagsWithPageData = genPageDataCode( const vueSrc =
data.hoistedTags || [], genPageDataCode(data.hoistedTags || [], pageData).join('\n') +
pageData `\n<template><div>${html}</div></template>`
).join('\n')
const tagsWithoutPageData = (data.hoistedTags || []).join('\n')
debug(`[render] ${file} in ${Date.now() - start}ms.`) debug(`[render] ${file} in ${Date.now() - start}ms.`)
const result = { const result = {
vueSrc, vueSrc,
pageData, pageData
tagsWithPageData,
tagsWithoutPageData
} }
cache.set(src, result) cache.set(src, result)
return pickResult(result, injectData) return result
}
}
function pickResult(
res: MarkdownCompileCachedResult,
injectData: boolean
): MarkdownCompileResult {
return {
vueSrc:
res.vueSrc +
(injectData ? res.tagsWithPageData : res.tagsWithoutPageData),
pageData: res.pageData
} }
} }

@ -17,7 +17,6 @@ export function createVitePressPlugin(
}) })
let siteData = initialSiteData let siteData = initialSiteData
let stringifiedData = JSON.stringify(JSON.stringify(initialSiteData))
const vitePressPlugin: Plugin = { const vitePressPlugin: Plugin = {
name: 'vitepress', name: 'vitepress',
@ -37,7 +36,7 @@ export function createVitePressPlugin(
load(id) { load(id) {
if (id === SITE_DATA_REQUEST_PATH) { if (id === SITE_DATA_REQUEST_PATH) {
return `export default ${stringifiedData}` return `export default ${JSON.stringify(JSON.stringify(siteData))}`
} }
}, },
@ -62,30 +61,22 @@ export function createVitePressPlugin(
}, },
async handleHotUpdate(file, mods, read, server) { async handleHotUpdate(file, mods, read, server) {
// handle config hmr
if (file === configPath) { if (file === configPath) {
const newData = await resolveSiteData(root) const newData = await resolveSiteData(root)
stringifiedData = JSON.stringify(JSON.stringify(newData))
if (newData.base !== siteData.base) { if (newData.base !== siteData.base) {
console.warn( console.warn(
`[vitepress]: config.base has changed. Please restart the dev server.` `[vitepress]: config.base has changed. Please restart the dev server.`
) )
} }
siteData = newData siteData = newData
return return [server.moduleGraph.getModuleById(SITE_DATA_REQUEST_PATH)!]
} }
// hot reload .md files as .vue files // hot reload .md files as .vue files
if (file.endsWith('.md')) { if (file.endsWith('.md')) {
const content = await read() const content = await read()
const { pageData, vueSrc } = markdownToVue( const { pageData, vueSrc } = markdownToVue(content, file)
content.toString(),
file,
// do not inject pageData on HMR
// it leads to plugin-vue to think <script> has changed and reloads
// the component instead of re-rendering.
// pageData needs separate HMR logic anyway (see below)
false
)
// notify the client to update page data // notify the client to update page data
server.ws.send({ server.ws.send({

@ -10,7 +10,7 @@ export async function createServer(
return createViteServer({ return createViteServer({
root, root,
logLevel: 'warn', // logLevel: 'warn',
plugins: createVitePressPlugin(root, config), plugins: createVitePressPlugin(root, config),
server: serverOptions server: serverOptions
}) })

Loading…
Cancel
Save