routes 关联 pages 解析

routes 和 pages 的生成是由 internal-router 生成的

internal-router 核心代码

module.exports = (options, ctx) => ({
  name: "@vuepress/internal-routes",

  // @internal/routes
  async clientDynamicModules() {
    const code = importCode(ctx.globalLayout) + routesCode(ctx.pages);
    console.log("code: " + code);
    return { name: "routes.js", content: code, dirname: "internal" };
  }
});

这里的 ctx.pages 就是 resolvePages 解析的所有 pages; clientDynamicModules 做的就是生成客户端的依赖文件。

下面是这个项目输出的 code, 也就是在.temp 下面的 routes.js

// 输出
import { injectComponentOption, ensureAsyncComponentsLoaded } from "@app/util";
import rootMixins from "@internal/root-mixins";
import GlobalLayout from "/Users/xiangxiao/Documents/work/workspace/vuepress-analysis/node_modules/@vuepress/core/lib/client/components/GlobalLayout.vue";

injectComponentOption(GlobalLayout, "mixins", rootMixins);
export const routes = [
  {
    name: "v-9d2814e2",
    path: "/",
    component: GlobalLayout,
    beforeEnter: (to, from, next) => {
      ensureAsyncComponentsLoaded("Layout", "v-9d2814e2").then(next);
    }
  },
  {
    path: "/index.html",
    redirect: "/"
  },
  {
    name: "v-02aefb2c",
    path: "/main/webpack/webpackconfig.html",
    component: GlobalLayout,
    beforeEnter: (to, from, next) => {
      ensureAsyncComponentsLoaded("Layout", "v-02aefb2c").then(next);
    }
  },
  ...,
  {
    path: "*",
    component: GlobalLayout
  }
];

还有一个就是对应 pages 的 internal-page-comonents, 也是在.temp 文件件下面。

其实生成这个文件就一目了然整个项目的结构了

中间没有什么华丽的操作,运用了 2 个方法 injectComponentOptionensureAsyncComponentsLoaded, 让整个 router 赋予了灵魂

/**
 * Generated by "@vuepress/internal-page-components"
 */
export default {
  "v-9d2814e2": () => import("/Users/xiangxiao/Documents/work/workspace/vuepress-analysis/docs/README.md"),
  ...
  "v-5be8b2fc": () => import("/Users/xiangxiao/Documents/work/workspace/vuepress-analysis/docs/plugin/pluginAPI.md"),
  "v-02aefb2c": () => import("/Users/xiangxiao/Documents/work/workspace/vuepress-analysis/docs/main/webpack/webpackconfig.md")
}

internal-page-comonents 将 name 的 key 值和 routes.js 的对应起来继而实现了 router 和页面的对应关系并加载在最终挂在到 vue 实例中。

client/app.js

import { routes } from "@internal/routes";

const routerBase = typeof window !== 'undefined'
    ? window.__VUEPRESS_ROUTER_BASE__
    : (siteData.routerBase || siteData.base)

const router = new Router({
    base: routerBase,
    mode: 'history',
    fallback: false,
    routes,
    ...
  })

项目中把 routerBase 的配置也写在一个静态的 temp 里面

总结

这里是搭建 vuepress 网站地图的中心,将地图拆解成部分碎片并分布到 temp 文件中。设计的理念还是将非配置类需要的文件给抽离出来,并根据 config 和 router 去生产相应的代码,中间还夹杂了 global 控件,和将 theme 的相关控件也集成到里面