diff --git a/packages/@vuepress/core/lib/client/app.js b/packages/@vuepress/core/lib/client/app.js index bcccec1797..a98c4afb71 100644 --- a/packages/@vuepress/core/lib/client/app.js +++ b/packages/@vuepress/core/lib/client/app.js @@ -9,14 +9,12 @@ import globalUIComponents from '@internal/global-ui' import ClientComputedMixin from '@transform/ClientComputedMixin' import VuePress from './plugins/VuePress' import { handleRedirectForCleanUrls } from './redirect.js' -import { getLayoutAsyncComponent } from './util' // built-in components import Content from './components/Content.js' import ContentSlotsDistributor from './components/ContentSlotsDistributor' import OutboundLink from './components/OutboundLink.vue' import ClientOnly from './components/ClientOnly' -import TOC from './components/TOC.vue' // suggest dev server restart on base change if (module.hot) { @@ -44,11 +42,8 @@ Vue.component('ContentSlotsDistributor', ContentSlotsDistributor) Vue.component('OutboundLink', OutboundLink) // component for client-only content Vue.component('ClientOnly', ClientOnly) -// core components -Vue.component('Layout', getLayoutAsyncComponent('Layout')) -Vue.component('NotFound', getLayoutAsyncComponent('NotFound')) // markdown components -Vue.component('TOC', TOC) +Vue.component('TOC', () => import('./components/TOC.vue')) // global helper for adding base path to absolute urls Vue.prototype.$withBase = function (path) { diff --git a/packages/@vuepress/core/lib/client/components/Content.js b/packages/@vuepress/core/lib/client/components/Content.js index c2ed88d487..b4811acf72 100644 --- a/packages/@vuepress/core/lib/client/components/Content.js +++ b/packages/@vuepress/core/lib/client/components/Content.js @@ -1,5 +1,3 @@ -import { isPageExists } from '../util' - export default { props: { pageKey: String, @@ -10,7 +8,7 @@ export default { }, render (h) { const pageKey = this.pageKey || this.$parent.$page.key - if (isPageExists(pageKey)) { + if (this.$vuepress.isPageExists(pageKey)) { return h(pageKey) } return h('') diff --git a/packages/@vuepress/core/lib/client/plugins/VuePress.d.ts b/packages/@vuepress/core/lib/client/plugins/VuePress.d.ts index ef4cf3782f..48af0be18c 100644 --- a/packages/@vuepress/core/lib/client/plugins/VuePress.d.ts +++ b/packages/@vuepress/core/lib/client/plugins/VuePress.d.ts @@ -4,13 +4,7 @@ import { AsyncComponent } from 'vue' declare class VuePress extends Store { isPageExists (pageKey: string): boolean; - isPageLoaded (pageKey: string): boolean; - - getPageAsyncComponent (pageKey: string): () => Promise; - - loadPageAsyncComponent (pageKey: string): Promise; - - registerPageAsyncComponent (pageKey: string): void; + isLayoutExists (pageKey: string): boolean; } declare module "vue/types/vue" { diff --git a/packages/@vuepress/core/lib/client/plugins/VuePress.js b/packages/@vuepress/core/lib/client/plugins/VuePress.js index bdb93e1b54..c5043b3138 100644 --- a/packages/@vuepress/core/lib/client/plugins/VuePress.js +++ b/packages/@vuepress/core/lib/client/plugins/VuePress.js @@ -1,23 +1,28 @@ +import Vue from 'vue' import Store from './Store' -import { - isPageExists, - isPageLoaded, - getPageAsyncComponent, - isLayoutExists, - isLayoutLoaded, - getLayoutAsyncComponent -} from '../util' -class VuePress extends Store {} +// TODO: reuse this function in shared-utils +function cached (fn) { + const cache = Object.create(null) + return str => { + if (typeof cache[str] === 'undefined') { + cache[str] = fn(str) + } + return cache[str] + } +} -Object.assign(VuePress.prototype, { - isPageExists, - isPageLoaded, - getPageAsyncComponent, - isLayoutExists, - isLayoutLoaded, - getLayoutAsyncComponent -}) +const pascalize = cached((str = '') => str.replace(/(^|-)\w/g, s => s.slice(-1).toUpperCase())) + +class VuePress extends Store { + isPageExists (pageKey) { + return Boolean(Vue.component(pascalize(pageKey))) + } + + isLayoutExists (layout) { + return Boolean(Vue.component(pascalize(layout))) + } +} export default { install (Vue) { diff --git a/packages/@vuepress/core/lib/client/util.js b/packages/@vuepress/core/lib/client/util.js index 8a8f552e98..5094b3dc9e 100644 --- a/packages/@vuepress/core/lib/client/util.js +++ b/packages/@vuepress/core/lib/client/util.js @@ -1,48 +1,3 @@ -import Vue from 'vue' -import layoutComponents from '@internal/layout-components' -import pageComponents from '@internal/page-components' - -const asyncComponents = Object.assign({}, layoutComponents, pageComponents) - -// TODO: reuse this function in shared-utils -function pascalize (source = '') { - return source.replace(/(^|-)\w/g, s => s.slice(-1).toUpperCase()) -} - -export function isPageExists (pageKey) { - return Boolean(getPageAsyncComponent(pageKey)) -} - -export function isPageLoaded (pageKey) { - return Boolean(Vue.component(pageKey)) -} - -export function getPageAsyncComponent (pageKey) { - return pageComponents[pascalize(pageKey)] -} - -export function isLayoutExists (layout) { - return Boolean(getLayoutAsyncComponent(layout)) -} - -export function isLayoutLoaded (layout) { - return Boolean(Vue.component(layout)) -} - -export function getLayoutAsyncComponent (pageKey) { - return layoutComponents[pascalize(pageKey)] -} - -export function ensureAsyncComponentsLoaded (...names) { - return Promise.all(names.filter(v => v).map(async (name) => { - name = pascalize(name) - if (!Vue.component(name) && asyncComponents[name]) { - const comp = await asyncComponents[name]() - Vue.component(name, comp.default) - } - })) -} - /** * Inject option to Vue SFC * @param {object} options diff --git a/packages/@vuepress/core/lib/node/internal-plugins/layoutComponents.js b/packages/@vuepress/core/lib/node/internal-plugins/layoutComponents.js index a17c4daf21..60ad57bcd2 100644 --- a/packages/@vuepress/core/lib/node/internal-plugins/layoutComponents.js +++ b/packages/@vuepress/core/lib/node/internal-plugins/layoutComponents.js @@ -4,12 +4,15 @@ module.exports = (options, ctx) => { return { name: '@vuepress/internal-layout-components', - async clientDynamicModules () { + async enhanceAppFiles () { const componentNames = Object.keys(ctx.themeAPI.layoutComponentMap) - const code = `export default {\n${componentNames - .map(name => ` ${JSON.stringify(pascalize(name))}: () => import(${JSON.stringify(ctx.themeAPI.layoutComponentMap[name].path)})`) - .join(',\n')} \n}` - return { name: 'layout-components.js', content: code, dirname: 'internal' } + const code = `import Vue from 'vue'\n${componentNames + .map(name => `Vue.component(${JSON.stringify(pascalize(name))}, () => import(${JSON.stringify(ctx.themeAPI.layoutComponentMap[name].path)}))`) + .join(',\n')} \n` + return { + name: 'layout-components.js', + content: code + } } } } diff --git a/packages/@vuepress/core/lib/node/internal-plugins/pageComponents.js b/packages/@vuepress/core/lib/node/internal-plugins/pageComponents.js index ce190db599..022fc2fdc5 100644 --- a/packages/@vuepress/core/lib/node/internal-plugins/pageComponents.js +++ b/packages/@vuepress/core/lib/node/internal-plugins/pageComponents.js @@ -7,12 +7,15 @@ module.exports = (options, ctx) => { return { name: '@vuepress/internal-page-components', - async clientDynamicModules () { - const code = `export default {\n${pages + async enhanceAppFiles () { + const code = `import Vue from 'vue'\n${pages .filter(({ _filePath }) => _filePath) - .map(({ key, _filePath }) => ` ${JSON.stringify(pascalize(key))}: () => import(${JSON.stringify(_filePath)})`) - .join(',\n')} \n}` - return { name: 'page-components.js', content: code, dirname: 'internal' } + .map(({ key, _filePath }) => `Vue.component(${JSON.stringify(pascalize(key))}, () => import(${JSON.stringify(_filePath)}))`) + .join(',\n')} \n` + return { + name: 'page-components.js', + content: code + } } } } diff --git a/packages/@vuepress/core/lib/node/internal-plugins/routes.js b/packages/@vuepress/core/lib/node/internal-plugins/routes.js index d6cf90b9b1..8c91601c00 100644 --- a/packages/@vuepress/core/lib/node/internal-plugins/routes.js +++ b/packages/@vuepress/core/lib/node/internal-plugins/routes.js @@ -42,10 +42,7 @@ function routesCode (pages) { { name: ${JSON.stringify(componentName)}, path: ${JSON.stringify(pagePath)}, - component: GlobalLayout, - beforeEnter: (to, from, next) => { - ensureAsyncComponentsLoaded(${JSON.stringify(layout || 'Layout')}, ${JSON.stringify(componentName)}).then(next) - },${_meta ? `\n meta: ${JSON.stringify(_meta)}` : ''} + component: GlobalLayout,${_meta ? `\n meta: ${JSON.stringify(_meta)}` : ''} }` const dncodedPath = decodeURIComponent(pagePath)