vitePress实现原理(四)

2.resolveAliases函数

源码位置:src/node/alias.ts

typescript 复制代码
import { createRequire } from 'module'
import { resolve, join } from 'path'
import { fileURLToPath } from 'url'
import type { Alias, AliasOptions } from 'vite'
import type { SiteConfig } from './config'

const require = createRequire(import.meta.url)
const PKG_ROOT = resolve(fileURLToPath(import.meta.url), '../..')

export const DIST_CLIENT_PATH = resolve(PKG_ROOT, 'client')
export const APP_PATH = join(DIST_CLIENT_PATH, 'app')
export const SHARED_PATH = join(DIST_CLIENT_PATH, 'shared')
export const DEFAULT_THEME_PATH = join(DIST_CLIENT_PATH, 'theme-default')

// 特殊虚拟文件。我们不能直接导入 '/@siteData' 因为:
// - 它不是一个实际文件,所以无法使用 tsconfig 路径重定向它
// - TypeScript 不允许对以 '/' 开头的模块进行 shimming
export const SITE_DATA_ID = '@siteData'
export const SITE_DATA_REQUEST_PATH = '/' + SITE_DATA_ID

const vueRuntimePath = 'vue/dist/vue.runtime.esm-bundler.js'

export function resolveAliases(
  { root, themeDir }: SiteConfig,
  ssr: boolean
): AliasOptions {
  const paths: Record<string, string> = {
    '@theme': themeDir,
    [SITE_DATA_ID]: SITE_DATA_REQUEST_PATH
  }

  const aliases: Alias[] = [
    ...Object.keys(paths).map((p) => ({
      find: p,
      replacement: paths[p]
    })),
    {
      find: /^vitepress$/,
      replacement: join(DIST_CLIENT_PATH, '/index.js')
    },
    {
      find: /^vitepress\/theme$/,
      replacement: join(DIST_CLIENT_PATH, '/theme-default/index.js')
    },
    {
      find: /^vue-demi$/,
      replacement: require.resolve('vitepress/vue-demi')
    }
  ]

  if (!ssr) {
    // 在非 SSR 构建时,优先使用项目根目录下的 vue,如果找不到则回退到 vitepress 自带的 vue。
    // 这样做的原因是,在 SSR 构建期间,`vue` 需要被外部化处理
    let vuePath
    try {
      vuePath = require.resolve(vueRuntimePath, { paths: [root] })
    } catch (e) {
      vuePath = require.resolve(vueRuntimePath)
    }
    aliases.push({
      find: /^vue$/,
      replacement: vuePath
    })
  }

  return aliases
}
  1. 路径解析工具 :
    • 使用 createRequire 创建一个 CommonJS 的 require 函数,以便在 ES 模块环境中使用 CommonJS 的模块加载机制。
    • 使用 resolvejoin 方法来拼接和解析路径。
    • 使用 fileURLToPath 将文件 URL 转换为文件系统路径。
  2. 路径常量定义 :
    • PKG_ROOT: 包的根目录路径。
    • DIST_CLIENT_PATH: 客户端代码的输出目录。
    • APP_PATH: 应用程序代码的输出目录。
    • SHARED_PATH: 共享代码的输出目录。
    • DEFAULT_THEME_PATH: 默认主题的输出目录。
  3. 特殊路径处理 :
    • SITE_DATA_ID: 特殊虚拟文件 ID。
    • SITE_DATA_REQUEST_PATH: 特殊虚拟文件的实际请求路径。
  4. 路径别名配置 :
    • paths: 存储路径别名的映射关系。
    • aliases: 存储最终的路径别名配置数组。
  5. 路径别名生成 :
    • 遍历 paths 对象,生成基本的路径别名。
    • 添加其他特定的路径别名,如 vitepress, vitepress/theme, 和 vue-demi
    • 在非 SSR 构建时,优先查找项目根目录下的 vue 模块,并将其添加到路径别名配置中。

到这里,整个项目启动流程就结束了。本质其实就是搭建一个vite静态服务器,针对所有html文件做拦截,进行二次封装。通过读取.vitepress/config.ts配置转化基本vitepress配置等等,创建markdown插件扩展markdown文档能力。创建vitepress插件对md文件和vue文件做处理。

大家这时肯定好奇,怎么没有路由呢?下期揭晓...

相关推荐
+VX:Fegn089538 分钟前
计算机毕业设计|基于springboot + vue蛋糕店管理系统(源码+数据库+文档)
前端·数据库·vue.js·spring boot·课程设计
半个落月1 小时前
LangChain.js Agent Memory 实战(下):用 Milvus 构建可检索的长期记忆
javascript·langchain
半个落月1 小时前
LangChain.js Agent Memory 实战(上):从内存对话、文件持久化到截断与摘要
javascript·langchain
Nicander2 小时前
我给 Excalidraw 做了一个本地工作区:DrawSpace
前端·开源
linux_cfan4 小时前
17 · 引擎适配器全景:HLS/DASH/Vimeo/Mux/Cast
前端·javascript·音视频
计算机魔术师4 小时前
烧掉2780亿美元还不够?OpenAI的资本豪赌让人头皮发麻
前端
IT_陈寒5 小时前
Java线程池用错参数,我的服务居然悄悄崩溃了
前端·人工智能·后端
卡布鲁5 小时前
React useMemo 与 useCallback 完全指南:原理、场景与避坑
前端·react.js
碳基修炼6 小时前
排查记:本地 devServer 是 http,浏览器却把 302 重定向升级成了 https
前端·http
步行cgn6 小时前
Spring p 命名空间注入详解
java·前端·spring