- 前端
- 文档
- SSR
【免费下载链接】vuepress
📝 Minimalistic Vue-powered static site generator
VuePress 的核心设计理念是**“约定优于配置”**(Convention over Configuration):你只需按照一套固定的目录约定摆放文件,VuePress 的源码编译流程就会自动完成全局组件注册、主题加载、样式注入、页面扫描与路由生成。本篇基于本仓库packages/docs/docs/guide/directory-structure.md原文,结合@vuepress/core与@vuepress/shared-utils的源码实现,逐层拆解.vuepress下每个目录/文件的真实作用与加载顺序,并解释“为什么README.md会路由到/、config.md会路由到/config.html”。读完本文,你将能够从零搭建一个符合 VuePress 约定的文档项目,并在自定义模板、样式、组件与路由时知道该把文件放在哪里、以及背后的生效机制。
一、约定优于配置:推荐目录结构总览
VuePress 官方推荐的目录结构如下(原文完整摘录):
. ├── docs │ ├── .vuepress _(**可选**)_ │ │ ├── `components` _(**可选**)_ │ │ ├── `theme` _(**可选**)_ │ │ │ └── Layout.vue │ │ ├── `public` _(**可选**)_ │ │ ├── `styles` _(**可选**)_ │ │ │ ├── index.styl │ │ │ └── palette.styl │ │ ├── `templates` _(**可选, 谨慎配置**)_ │ │ │ ├── dev.html │ │ │ └── ssr.html │ │ ├── `config.js` _(**可选**)_ │ │ └── `enhanceApp.js` _(**可选**)_ │ │ │ ├── README.md │ ├── guide │ │ └── README.md │ └── config.md │ └── package.json特别注意:目录名的大小写是敏感的。.vuepress必须小写,README.md必须大写。若写错大小写,VuePress 将无法识别对应目录或页面文件——这一点在@vuepress/core的路径解析中体现得淋漓尽致:所有约定路径都是通过path.resolve(sourceDir, '.vuepress')这类精确拼写来定位的(见 App.js)。
在这个结构中,docs是站点源码目录(即命令行中的targetDir),package.json位于项目根目录。从源码结构看,docs目录下除.vuepress之外的任意 Markdown / Vue 文件都会进入页面扫描流程(见下文第四节)。
二、.vuepress核心目录逐项拆解
.vuepress是 VuePress 的“配置中枢”,存放全局配置、组件、静态资源与主题。原文逐项说明了其用途,下面结合源码进一步展开每个条目背后的加载机制。
2.1components:自动注册为全局组件
docs/.vuepress/components中的 Vue 组件会被自动注册为全局组件,无需手动引入。其实现位于官方插件 plugin-register-components/index.js:插件会通过globby(['**/*.vue'])扫描该目录,然后生成一段形如Vue.component('name', () => import(path))的代码注入客户端。
组件名由fileToComponentName决定——文件路径中的/与\会被替换为-(plugin-register-components/index.js),例如components/Foo/Bar.vue会注册为全局组件Foo-Bar。
在核心层,App.js 的applyInternalPlugins()会以@vuepress/register-components插件注册三个组件扫描目录,按优先级排列为:
docs/.vuepress/components(站点级)- 当前主题的
global-components目录 - 父主题(若存在)的
global-components目录
这也是为什么默认主题自带 Badge.vue、CodeGroup.vue 等全局组件 可以直接在 Markdown 中使用的根本原因。
2.2theme:存放本地主题
docs/.vuepress/theme用于存放本地主题(Local Theme)。其加载优先级定义在 loadTheme.js 中:
- 若
theme配置项指向的绝对路径存在,优先使用该路径; - 否则检查
docs/.vuepress/theme目录是否存在且非空,存在则作为本地主题; - 否则把
theme配置当作包名,从依赖中解析(如@vuepress/theme-default)。
主题目录内的Layout.vue是核心布局文件。从 theme-api/index.js 的实现看,主题会同时扫描主题根目录与layouts/子目录中的.vue文件作为命名布局;若找不到Layout.vue,会回退到内置的Layout.fallback.vue并打印警告;404.vue会被归一化为NotFound布局。
仓库中的测试用本地主题示例可参考mocks/vuepress-theme-parent 与mocks/vuepress-theme-child,分别演示了父主题与子主题的目录组织方式。
2.3styles/index.styl:自动应用的全局样式
docs/.vuepress/styles/index.styl是自动应用的全局样式文件。从 internal-plugins/style/index.js 的ready()钩子可以看出,它会在构建阶段生成一个临时的style.styl,其内容结构为:
// Theme's Styles @import(".../theme/styles/index.styl") // User's Styles @import(".../.vuepress/styles/index.styl")即先引入主题样式,再引入你的样式,因此index.styl中的规则排在 CSS 文件末尾,具有比默认样式更高的优先级,可以直接覆盖主题样式。若存在父主题,父主题样式会再排在最前面。
另外,该插件还顺带检测了从 v1.0.0 起已被废弃的docs/.vuepress/override.styl,并提示改用styles/palette.styl(internal-plugins/style/index.js)。
2.4styles/palette.styl:颜色常量与 Stylus 变量
docs/.vuepress/styles/palette.styl用于重写默认颜色常量或定义新的 Stylus 颜色常量。其底层机制在 internal-plugins/palette/index.js 中:该插件会把核心库的 style/config.styl 通过stylus.import全局注入,同时生成临时palette.styl:
// Theme's Palette @import(".../theme/styles/palette.styl") // User's Palette @import(".../.vuepress/styles/palette.styl")用户自定义的 palette 永远排在主题 palette 之后,从而保证你的颜色常量可以覆盖主题与默认常量。如果你在 paletter 中定义了$accentColor之类的变量,主题样式文件可以直接引用——这正是默认主题 styles/config.styl 中大量使用变量的前提。
2.5public:静态资源目录
docs/.vuepress/public是静态资源目录,该目录下的文件会被原样拷贝/托管,不会被 VuePress 编译。开发服务器将它的绝对路径作为contentBase(dev/index.js),因此你可以通过/xxx.png这样的根路径直接访问其中的文件。更完整的静态资源用法(含base路径影响、<img>引用写法)可阅读 assets.md。
2.6templates:HTML 模板(危险区,谨慎配置)
templates存放两个 HTML 模板文件:
dev.html:开发环境的 HTML 模板;ssr.html:构建时基于 Vue SSR 的 HTML 模板。
自定义这两个模板时必须小心。核心层的模板解析逻辑在 App.js 的resolveTemplates()中,其解析优先级为(以devTemplate为例):
siteConfig.devTemplate配置项;docs/.vuepress/templates/dev.html约定文件;- 主题入口文件的
devTemplate配置; - 核心库默认模板。
官方警告:自定义templates/ssr.html或templates/dev.html时,最好基于默认模板修改,否则可能导致构建失败。默认模板位于核心库 index.dev.html 与 index.ssr.html,二者非常精简,核心就是一个<div id="app"></div>挂载点,修改时请保留这个挂载点结构。
2.7config.js:配置文件入口
docs/.vuepress/config.js是配置文件的入口文件。原文指出它也可以是yml或toml;而实际源码 loadConfig.js 还额外支持config.ts。四者共存的解析优先级是:
config.yml(或.yaml,经js-yaml解析);config.ts(经bundle-require打包后取mod.default或mod);config.toml(经toml解析,head数组会被重排为 VuePress 约定的格式,见 loadConfig.js);config.js(通过require直接加载)。
如果config.js导出一个函数,该函数会收到应用上下文并被调用,返回值作为站点配置(App.js)。全部配置项的完整说明见 config/README.md;TypeScript 写法见 typescript-as-config.md。
2.8enhanceApp.js:应用级增强
docs/.vuepress/enhanceApp.js用于在应用层面做增强,例如注册全局组件、混入、路由守卫等。其加载逻辑在 internal-plugins/enhanceApp.js 中:它会按顺序收集三个文件——
docs/.vuepress/enhanceApp.js(站点级);- 父主题的
enhanceApp.js(若存在); - 主题的
enhanceApp.js。
默认导出的函数签名是({ Vue, options, router, siteData }) => {},其中Vue是 Vue 构造器、options是根实例选项、router是路由实例、siteData是站点元数据。更完整的用法参见 using-vue.md。
三、theme目录与默认主题的关系
需要区分两个概念:本地主题目录(docs/.vuepress/theme)与官方默认主题包(@vuepress/theme-default,源码位于 theme-default)。
- 如果你没有配置
theme,且没有本地主题目录,VuePress 会使用依赖中解析到的默认主题@vuepress/theme-default; - 如果你想完全自定义站点外观,可以在
docs/.vuepress/theme下创建Layout.vue搭建本地主题; - 默认主题的布局与组件全部位于 theme-default/layouts 与 theme-default/components,可作为自定义主题时的参考模板。
关于主题的编写、继承(extend)与使用方式,分别见 writing-a-theme.md、inheritance.md 与 using-a-theme.md。
四、页面源文件:哪些文件会变成页面
页面扫描发生在 App.js 的resolvePages()中:VuePress 以targetDir(即示例中的docs)为根,用globby匹配**/*.md与**/*.vue文件(可通过siteConfig.patterns覆盖),并始终排除.vuepress与node_modules目录。若配置了dest且输出目录位于源目录内,也会被排除,避免构建产物被当作页面源。
这意味着docs下除.vuepress外的每个 Markdown 文件都对应一个页面;而.vue文件会被当作布局组件处理(Page.js 中会给 Vue SFC 自动附加layout属性)。
五、默认页面路由:从相对路径到 URL 的映射规则
5.1 添加 npm scripts
把docs目录作为targetDir后,在项目根目录的package.json中添加如下脚本(原文示例,可原样使用):
{ "scripts": { "dev": "vuepress dev docs", "build": "vuepress build docs" } }vuepress dev docs启动带热更新的开发服务器;vuepress build docs生成静态站点,默认输出到docs/.vuepress/dist(见 App.js,也可通过dest配置或-d参数覆盖)。
5.2 默认路由映射表
对于前文给出的目录结构,默认页面路由如下(原文完整表格):
文件的相对路径(相对docs) | 页面路由地址 |
|---|---|
/README.md | / |
/guide/README.md | /guide/ |
/config.md | /config.html |
5.3 规则背后的源码实现
这三条映射不是“魔法”,而是@vuepress/shared-utils中 fileToPath.ts 的确定性算法:
README.md→/:isIndexFile()会命中index或readme的约定(正则/(^|.*\/)(index|readme)\.(md|vue)$/i,见 isIndexFile.ts),于是把README.md替换为所在目录路径。docs根目录的README.md位于根层级,因此映射为/;guide/README.md→/guide/:同样是 index 文件规则,映射为所在目录guide的路径/guide/;config.md→/config.html:普通 Markdown 文件会去掉.md扩展名并追加.html,得到/config.html。
注意大小写:README与index的匹配是大小写不敏感的(正则末尾的i标志),因此readme.md、INDEX.md也会被视为首页文件。
页面路径计算发生在 Page.js 的构造函数中(regularPath = encodeURI(fileToPath(relative))),随后由@vuepress/internal-routes插件生成 Vue Router 路由表(routes.js)。生成的每条路由还附带几条自动重定向规则:
- 以
/结尾的路径自动补充xxx/index.html→xxx/的重定向,保证直接访问guide/index.html也能到达/guide/; - 对 URL 编码差异路径(
decodeURIComponent后不同)生成重定向; - 未匹配到任何页面的路径统一落入
*通配路由(404 页面)。
仓库的测试夹具也印证了这一约定:核心层的 prepare/fixtures/docs 目录下同时存在README.md、alpha.md、excerpt.md等文件,配合Page.spec.js的快照验证了路径映射结果。
5.4 自定义路由:permalink与 frontmatter
默认路由规则可以通过每个页面的 frontmatterpermalink字段覆盖,例如在config.md顶部声明permalink: /settings/即可得到自定义路径;也可以在站点配置中通过permalink模板(如/:year/:month/:day/:slug)统一设置。相关细节见 permalinks.md 与 frontmatter.md。
六、与其他文档的衔接
本指南聚焦目录约定与路由映射,与之配套的官方文档还包括:
- Config 配置:
.vuepress/config.js的全部配置项; - Theme 主题:主题体系与布局约定;
- Default Theme Config:默认主题的可配置项;
- Command-line Interface:
vuepress dev/build的全部 CLI 参数(含targetDir、-d、--temp等); - Getting Started:从安装到运行的最小实践路径。
小结
VuePress 的目录结构本质上是一套“文件即配置”的声明式系统:.vuepress/components决定全局组件、styles/index.styl与styles/palette.styl决定样式覆盖顺序、templates决定 HTML 骨架、enhanceApp.js决定应用增强、config.js(或其 yml/toml/ts 变体)决定全局行为,而docs下的 Markdown 文件则按fileToPath的规则自动生成页面路由。理解这些约定的加载顺序与优先级,是自定义主题、调整样式与构建复杂文档站点的第一步。
- 前端
- 文档
- SSR
【免费下载链接】vuepress
📝 Minimalistic Vue-powered static site generator
相关推荐
CLIP-ReID:突破性视觉-语言模型在无文本标签图像重识别中的创新应用
CLIP ReID:突破性视觉 语言模型在无文本标签图像重识别中的创新应用 CLIP ReID作为一项革命性的图像重识别技术,通过巧妙利用预训练的视觉 语言模型
前端文档SSR为什么选择 Azimutt?下一代 ERD 工具的 7 大优势解析
为什么选择 Azimutt?下一代 ERD 工具的 7 大优势解析 Azimutt 是一款功能强大的数据库探索与文档工具,专为开发者和数据库管理员设计,帮助他们
前端文档SSR7个核心目录结构解析:快速掌握VuePress文档项目高效组织方法
7个核心目录结构解析:快速掌握VuePress文档项目高效组织方法 VuePress是一个基于Vue.js的极简静态网站生成器,它让你能够用Markdown轻松
前端文档SSR
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考