index.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import { createApp as createClientApp, createSSRApp } from 'vue';
  2. import { createRouter, RouterSymbol } from './router';
  3. import { useUpdateHead } from './composables/head';
  4. import { Content } from './components/Content';
  5. import Debug from './components/Debug.vue';
  6. import Theme from '/@theme/index';
  7. import { inBrowser, pathToFile } from './utils';
  8. import { useSiteDataByRoute } from './composables/siteDataByRoute';
  9. import { siteDataRef } from './composables/siteData';
  10. const NotFound = Theme.NotFound || (() => '404 Not Found');
  11. export function createApp() {
  12. let isInitialPageLoad = inBrowser;
  13. let initialPath;
  14. const router = createRouter((path) => {
  15. let pageFilePath = pathToFile(path);
  16. if (isInitialPageLoad) {
  17. initialPath = pageFilePath;
  18. }
  19. // use lean build if this is the initial page load or navigating back
  20. // to the initial loaded path (the static vnodes already adopted the
  21. // static content on that load so no need to re-fetch the page)
  22. if (isInitialPageLoad || initialPath === pageFilePath) {
  23. pageFilePath = pageFilePath.replace(/\.js$/, '.lean.js');
  24. }
  25. if (inBrowser) {
  26. isInitialPageLoad = false;
  27. // in browser: native dynamic import
  28. return import(/*@vite-ignore*/ pageFilePath);
  29. }
  30. else {
  31. // SSR, sync require
  32. return require(pageFilePath);
  33. }
  34. }, NotFound);
  35. // update route.data on HMR updates of active page
  36. if (import.meta.hot) {
  37. // hot reload pageData
  38. import.meta.hot.on('vitepress:pageData', (payload) => {
  39. if (payload.path.replace(/(\bindex)?\.md$/, '') ===
  40. location.pathname.replace(/(\bindex)?\.html$/, '')) {
  41. router.route.data = payload.pageData;
  42. }
  43. });
  44. }
  45. const app = process.env.NODE_ENV === 'production'
  46. ? createSSRApp(Theme.Layout)
  47. : createClientApp(Theme.Layout);
  48. app.provide(RouterSymbol, router);
  49. app.component('Content', Content);
  50. app.component('Debug', process.env.NODE_ENV === 'production' ? () => null : Debug);
  51. const siteDataByRouteRef = useSiteDataByRoute(router.route);
  52. if (inBrowser) {
  53. // dynamically update head tags
  54. useUpdateHead(router.route, siteDataByRouteRef);
  55. }
  56. Object.defineProperties(app.config.globalProperties, {
  57. $site: {
  58. get() {
  59. return siteDataRef.value;
  60. }
  61. },
  62. $siteByRoute: {
  63. get() {
  64. return siteDataByRouteRef.value;
  65. }
  66. },
  67. $page: {
  68. get() {
  69. return router.route.data;
  70. }
  71. },
  72. $theme: {
  73. get() {
  74. return siteDataByRouteRef.value.themeConfig;
  75. }
  76. }
  77. });
  78. if (Theme.enhanceApp) {
  79. Theme.enhanceApp({
  80. app,
  81. router,
  82. siteData: siteDataByRouteRef
  83. });
  84. }
  85. return { app, router };
  86. }
  87. if (inBrowser) {
  88. const { app, router } = createApp();
  89. // wait unitl page component is fetched before mounting
  90. router.go().then(() => {
  91. app.mount('#app');
  92. });
  93. }