You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
vitepress/lib/app/index.js

136 lines
3.7 KiB

import { createApp as createClientApp, createSSRApp, ref, readonly } from 'vue'
5 years ago
import { createRouter, RouterSymbol } from './router'
import { useUpdateHead } from './composables/head'
import { siteDataRef } from './composables/siteData'
import { pageDataSymbol } from './composables/pageData'
import { Content } from './components/Content'
import Debug from './components/Debug.vue'
import Theme from '/@theme/index'
import { hot } from 'vite/hmr'
const inBrowser = typeof window !== 'undefined'
const NotFound = Theme.NotFound || (() => '404 Not Found')
5 years ago
5 years ago
export function createApp() {
// unlike site data which is static across all requests, page data is
// distinct per-request.
5 years ago
const pageDataRef = ref()
if (inBrowser) {
// dynamically update head tags
useUpdateHead(pageDataRef)
}
if (__DEV__ && inBrowser) {
// hot reload pageData
5 years ago
hot.on('vitepress:pageData', (data) => {
if (
5 years ago
data.path.replace(/(\bindex)?\.md$/, '') ===
location.pathname.replace(/(\bindex)?\.html$/, '')
5 years ago
) {
pageDataRef.value = data.pageData
}
5 years ago
})
}
5 years ago
let isInitialPageLoad = inBrowser
/**
* @type string
*/
let initialPath
5 years ago
const router = createRouter((route) => {
let pagePath = route.path.replace(/\.html$/, '')
if (pagePath.endsWith('/')) {
pagePath += 'index'
}
5 years ago
if (isInitialPageLoad) {
initialPath = pagePath
}
5 years ago
if (__DEV__) {
// awlays force re-fetch content in dev
pagePath += `.md?t=${Date.now()}`
} else {
// in production, each .md file is built into a .md.js file following
// the path conversion scheme.
// /foo/bar.html -> ./foo_bar.md
if (inBrowser) {
pagePath = pagePath.slice(__BASE__.length).replace(/\//g, '_') + '.md'
// client production build needs to account for page hash, which is
// injected directly in the page's html
const pageHash = __VP_HASH_MAP__[pagePath]
// use lean build if this is the initial page load or navigating back
// to the initial loaded path (the static vnodes already adopted the
// static content on that load so no need to re-fetch the page)
const ext =
isInitialPageLoad || initialPath === pagePath ? 'lean.js' : 'js'
pagePath = `${__BASE__}_assets/${pagePath}.${pageHash}.${ext}`
} else {
// ssr build uses much simpler name mapping
pagePath = `./${pagePath.slice(1).replace(/\//g, '_')}.md.js`
}
5 years ago
}
5 years ago
if (inBrowser) {
5 years ago
isInitialPageLoad = false
5 years ago
// in browser: native dynamic import
5 years ago
return import(pagePath).then((page) => {
if (page.__pageData) {
pageDataRef.value = readonly(JSON.parse(page.__pageData))
}
5 years ago
return page.default
})
5 years ago
} else {
// SSR, sync require
5 years ago
const page = require(pagePath)
pageDataRef.value = JSON.parse(page.__pageData)
5 years ago
return page.default
}
5 years ago
}, NotFound)
5 years ago
const app = __DEV__
? createClientApp(Theme.Layout)
: createSSRApp(Theme.Layout)
5 years ago
5 years ago
app.provide(RouterSymbol, router)
app.provide(pageDataSymbol, pageDataRef)
5 years ago
5 years ago
app.component('Content', Content)
app.component('Debug', __DEV__ ? Debug : () => null)
Object.defineProperties(app.config.globalProperties, {
$site: {
get() {
return siteDataRef.value
}
},
$page: {
get() {
return pageDataRef.value
}
5 years ago
}
})
if (Theme.enhanceApp) {
Theme.enhanceApp({
app,
router,
siteData: siteDataRef
})
}
5 years ago
return { app, router }
}
5 years ago
5 years ago
if (inBrowser) {
5 years ago
const { app, router } = createApp()
// wait unitl page component is fetched before mounting
router.go().then(() => {
app.mount('#app')
})
5 years ago
}