VuePress 1.x 的设计理念
VuePress 1.x 的设计理念主要体现在以下几个方面:
- 插件化
- 约定大于配置
- 合理的优先级管理
插件化
VuePress 1.0 进行了大范围的重写,其中最重要的就是引入 Plugin API,那么插件带来的好处究竟是什么呢?
解耦
有了插件,我们可以将很多核心功能用插件来实现,你可以在这里看到很多内置的插件,这些插件涵盖了很多 VuePress 的核心功能,在以前,它们糅合在代码库的各个地方,但现在,它们一目了然。
配置的管理
在过去,当我们遇到一些不太常见的需求时,我们会有一些疑虑:如果我们打算不支持,VuePress 的使用场景也就受到了限制;但如果想要支持它,我们就必须将其写到核心代码库中,并为其单独开设配置的 API。对于维护者来说,除了不利于长久的维护,这有时也会让我们心力交瘁。我们必须想到一些更好的解决办法,没错,这个办法就是插件。
.vuepress/config.js
也是插件
没错,你的配置文件也是一个插件,因此,你可以直接使用插件 API,而不必为此新建一个插件,然后在配置中导入它。
提示
.vuepress/config.js
所支持的 API,实际上是在插件选项的基础上又新增了一些特定的选项。
theme/index.js
也是插件
主题的根配置文件也是插件。
提示
和 .vuepress/config.js
一样,theme/config.js
所支持的选项,也是在插件选项的基础上,又新增了一些特定的选项。用一张图来表达它们的关系就是:
在插件中使用插件
在 VuePress 中,你拥有在插件中使用插件的能力:
// vuepress-plugin-xxx
module.exports = {
plugins: [
'a', 'b', 'c'
]
}
约定大于配置
VuePress 1.0 开始引入一些约定,以减少用户过多的配置压力。对于这一点,最直观的体现是对文档目录结构和主题目录结构的约定。
未来我们可能还会结合社区的反馈来引入更多的约定,让我们拭目以待。
合理的优先级管理
资深的 VuePress 用户可能已经发现,主题开发者和普通的文档用户都具有定义全局的 palette
、style
、templates
和 plugins
的能力,那么他们是如何协同工作的呢?
加载优先级
templates/*
遵循一定的加载优先级,以 templates/ssr.html
为例:
@flowstart cond1=>condition: 用户的 ssr.html 是否存在? cond2=>condition: 主题的 ssr.html 是否存在? stage1=>operation: 使用用户的 ssr.html stage2=>operation: 使用主题的 ssr.html stage3=>operation: 使用默认的 ssr.html
cond1(no, right)->cond2(no)->stage3 cond1(yes, bottom)->stage1 cond2(yes, bottom)->stage2 @flowend
注意
当你想要去自定义 templates/ssr.html
或 templates/dev.html
时,最好基于 默认的模板文件 来修改,否则可能会导致构建出错。
Overriding
对于 palette.styl
、index.styl
和 plugins
, 遵循 overriding
的原则:
palette.styl
用户的 styles/palette.styl
具有比主题的 styles/palette.styl
更高的优先级,因此主题可以先预定义一套调色板,而用户又可以根据自身需要修改它。例如:
// theme/styles/palette.styl
$accentColor = #0f0
// .vuepress/styles/palette.styl
$accentColor = #f00
$accentColor
最终的值是 #f00
。
index.styl
用户和主题的 styles/index.styl
都会被生成到最终的 CSS 文件中,但是默认情况下,用户的样式会生成在主题的样式后面,因此对于同样的选择器,用户的样式将具有更高的优先级,如:
// theme/styles/index.styl
.content
font-size 14px
// .vuepress/styles/index.styl
.content
font-size 15px
最终生成的 CSS 文件如下:
/* theme/styles/index.styl */
.content {
font-size: 14px;
}
/* theme/styles/index.styl */
.content {
font-size: 15px;
}
plugins
由于同名插件默认情况下只能应用一次,因此用户可以修改主题中预置的插件选项的默认值,如:
// theme/index.js
module.exports = {
plugins: [
'vuepress-plugin-xxx',
{ name: 'foo' }
]
}
// .vuepress/config.js
module.exports = {
plugins: [
'vuepress-plugin-xxx',
{ name: 'bar' }
]
}
name 的最终值将是 bar
.
其他
本着解耦的目标,引入 monorepo 后,我们也得以将 VuePress 分离成以下两个库:
- @vuepress/core:包含 dev、build 的核心实现和 Plugin API;
- @vuepress/theme-default:你现在所看到的默认主题。
当然,对于大多数用户来说,你并不需要关心上述三个库,vuepress 这个包已经将上述三个包组装在一起,因此你完全可以像 0.x
那样使用 VuePress。