VuePress 1.x 的设计理念

VuePress 1.x 的设计理念主要体现在以下几个方面:

  1. 插件化
  2. 约定大于配置
  3. 合理的优先级管理

插件化

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 所支持的选项,也是在插件选项的基础上,又新增了一些特定的选项。用一张图来表达它们的关系就是:

Created with Sketch. .vuepress/ config.js Plugin API theme/ index.js

在插件中使用插件

在 VuePress 中,你拥有在插件中使用插件的能力:

// vuepress-plugin-xxx
module.exports = {
  plugins: [
    'a', 'b', 'c'
  ]
}

约定大于配置

VuePress 1.0 开始引入一些约定,以减少用户过多的配置压力。对于这一点,最直观的体现是对文档目录结构主题目录结构的约定。

未来我们可能还会结合社区的反馈来引入更多的约定,让我们拭目以待。

合理的优先级管理

资深的 VuePress 用户可能已经发现,主题开发者和普通的文档用户都具有定义全局的 palettestyletemplatesplugins 的能力,那么他们是如何协同工作的呢?

加载优先级

templates/* 遵循一定的加载优先级,以 templates/ssr.html 为例:

注意

当你想要去自定义 templates/ssr.htmltemplates/dev.html 时,最好基于 默认的模板文件 来修改,否则可能会导致构建出错。

Overriding

对于 palette.stylindex.stylplugins, 遵循 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 这个包已经将上述三个包组装在一起,因此你完全可以像 0.x 那样使用 VuePress。