309 lines
18 KiB
Markdown
309 lines
18 KiB
Markdown
# 29|周边:框架发布和维护也是重要的一环
|
||
|
||
你好,我是轩脉刃。
|
||
|
||
终于来到框架设计与完善的最后一节课了。在前面的章节中,我们基本上把框架的功能都开发完成了,但是这只是万里长征的第一步。一个工业级的Web框架一定是经过长时间千锤百炼的迭代升级的。在这门课编写完成的时候,我为hade框架锁定了v 1.0.0版本,后续我们会继续为框架增加更多的功能和特性。
|
||
|
||
那么随着框架的不断更新和升级,随之而来的问题就是如何为一个开源项目设计一套发布和使用机制,并且为每个发布版本维护一套准确的框架说明文档?这就是我们今天要讨论的内容。
|
||
|
||
### 版本
|
||
|
||
每个框架发布都需要有一个版本号,这个版本号如何定义,我们在前面的课程中已经不止一次提到过了,这里再正式说明一下。
|
||
|
||
所有开源软件的版本号基本上都遵循“[语义化版本规范](https://semver.org/lang/zh-CN)”的约定,这份语义化版本规范是由Gravatars 创办者兼 GitHub 共同创办者 Tom Preston-Werner 所建立的,它定义了三段式的版本规范,格式如下:
|
||
|
||
```plain
|
||
主版本号.次版本号.修订号
|
||
|
||
```
|
||
|
||
我们使用的Golang语言项目也是基于这个规范来实现的。
|
||
|
||
**主版本号代表如果做了不兼容的API修改**。比如在你的项目中,原先提供的A方法要替换为B方法,所有的参数和返回值都已经变化了,你的使用方必须修改他的代码,这个变动就叫做“不兼容的API修改”。这个时候,主版本号就必须更新了。
|
||
|
||
**次版本号表示当你做了向下兼容的功能性新增**。比如原先你的类中只有A方法,当你新增了一个B方法,但是并不修改原先的A方法,这个时候你的类有A、B两个方法。原先的库使用者并不需要更新他的任何代码,这就是“向下兼容的功能性新增”。这个时候,你不需要更新主版本号,只需要更新次版本号就行。
|
||
|
||
**修改号,表示当你做了向下兼容的问题修正**。比如原先类中只有A方法,你并没有更新任何的功能,只是修改了A方法中的一个bug,那么这个时候,不需要更新主版本号和次版本号,直接更新修订版本号就行。
|
||
|
||
这个语义化版本规范,基本上已经是开源届的共识了,当然也可以不遵循这个规范,但是一旦不遵循,对你开源项目的使用者来说绝对是一个灾难性的事情,进而你的项目也逐渐会失去使用者。
|
||
|
||
我们使用的Go语言版本就是严格遵循这个规范的。比如现在使用的Golang版本为1.17.2。主版本为1,次版本为17,修改号为2。基本上我们接触Golang都是从1.0.0之后开始的,目前Go还没发布2.0.0,所以1.0之后的Go版本升级都是向下兼容的。如果有做过Go升级的同学可以思考下,在升级的时候,业务代码有没有做任何变动。
|
||
|
||
另外再附带说一下,你也有可能在网络上看到版本号不止三个的,比如1.2.3.4,或者 1.2.3.beta。这些都是对这个语义化规范的扩展使用而已,最后一个字段根据不同的项目可能有不同的意思,比如是否是发行版本。不过前三个版本号都是遵循这个版本规范的。所以见到这些扩展版本号不要吃惊。
|
||
|
||
我们的hade框架当然也要基于这个版本规范,在这门课程更新完成之后,我会把这门课程的所有代码锁定为一个发布版本1.0.0,并且从这个版本开始继续迭代更新功能。有新的功能和模块增加,我们会升级次版本号,有任何的bug修复,就升级修订版本号。
|
||
|
||
### 发布
|
||
|
||
明确了hade的版本号规范之后,要明确我们的发布模式,这个在前面的[第22节课](https://time.geekbang.org/column/article/435534)开发自动化脚手架已经简单说过了,这里再正式说明一下。
|
||
|
||
我们的框架最终在GitHub上的地址为:[https://github.com/gohade/hade](https://github.com/gohade/hade) ,会至少为每一个次版本号打上release版本。
|
||
![](https://static001.geekbang.org/resource/image/ca/75/caec1bcef876ba937a5eacf036e58975.png?wh=1920x1025)
|
||
|
||
而对于框架的使用者来说,使用步骤会是这样的。首先需要在工作机器上安装hade命令,我们可以在任何路径调用:
|
||
|
||
```go
|
||
go install github.com/gohade/hade@latest
|
||
|
||
```
|
||
|
||
来安装hade命令。这个hade命令,其实用任何版本都是可以的,这里直接选用最新版本。
|
||
调用了go install 之后,hade命令就被安装到你的$GOPATH/bin目录下了。直接调用 `$GOPATH/bin/hade` 可以看到安装好的hade命令。
|
||
![](https://static001.geekbang.org/resource/image/b8/c0/b8eec8f059ac82a5a5f1de6657dba7c0.png?wh=1920x1172)
|
||
|
||
然后使用 `hade new` 命令创建一个项目,比如为hellohade。我们可以看到创建出了目标文件夹hellohade。
|
||
![](https://static001.geekbang.org/resource/image/c4/fc/c4de7585ff0c36e79ef038bcdf952bfc.png?wh=1920x1312)
|
||
|
||
进入目标文件夹 `cd hellohade` ,调用 `go mod tidy` 下载所有的依赖包,调用 `go build` 编译目录。
|
||
![](https://static001.geekbang.org/resource/image/03/92/030ec01edf75260c35782db1413ed192.png?wh=1566x1044)
|
||
接下来,使用者就可以在这个目标文件夹中开始基于hade开发应用了。
|
||
![](https://static001.geekbang.org/resource/image/ea/8e/ea74acc44f15623d50dd4608e1cyy48e.png?wh=1920x1320)
|
||
|
||
## 文档维护
|
||
|
||
到这里,我们把框架的版本和发布的流程梳理清楚了。但是随着版本不断迭代更新,框架对应的说明文档也是需要不断更新的,这就涉及框架文档的编写和搭建了。
|
||
|
||
对于一个开源项目,说明文档的查看渠道是多种多样的。
|
||
|
||
对于比较小型的项目和类库,一般都会选择直接使用markdown来编写。比如我们在之前用到的 [go-daemon](https://github.com/sevlyar/go-daemon) 库,功能比较简单,就是创建一个daemon进程,它的使用方式也比较简单,所以,作者就在项目GitHub地址的 README.md 中写所有信息的使用文档了。
|
||
|
||
而对于比较大型的项目,大多数项目都会自己开启一个官方网站,来说明项目的各种使用方法,比如[gorm](https://github.com/go-gorm/gorm) 项目,这个库封装的函数多种多样,所以作者单独创建了一个[网站](https://gorm.io/zh_CN/docs/index.html)来列出对gorm项目的说明。
|
||
|
||
使用网站来展示项目使用文档有一个额外工作,就是当版本升级的时候,要同时升级官方文档。否则的话,使用者就会经常遇到看旧文档、使用新框架的情况,而导致错误的用法。所以必须及时维护代码和文档的一致性。
|
||
|
||
那有没有办法将这两者结合一下呢?我们使用markdown编写说明文档,然后如果能自动将这些markdown文档转化为HTML网站,再将网站部署到服务器上,那就完美了。
|
||
|
||
确实是有这样的工具的,[vuepress](https://vuepress.vuejs.org/zh/guide)。vuepress是一个Vue工具,基于Vue框架生成了一个vuepress的命令行工具,这个工具能将指定的markdown文件转化为HTML文件,而这个HTML文件是可以直接被使用者访问的。
|
||
|
||
**vuepress的编译需要两个目录,存放markdown的目录和生成HTML的目标目录**。vuepress是基于Vue的,正好hade框架也已经融合了Vue。所以自然可以想到,直接将存放markdown的目录放在hade框架地址上,然后将生成HTML的目标目录定义为我们的dist目录。这样,就可以在hade框架上使用npm工具来生成HTML了。
|
||
|
||
## 编写markdown
|
||
|
||
于是我们在根目录下创建docs目录,存放编写的markdown文件。
|
||
|
||
这里框架说明的markdown文件我都事先编写完成,也存放在GitHub上了,你可以比对查看。vuepress的markdown文件格式,编写并没有什么特别,只需要你多阅读尝试,心里对哪种格式最终的页面展现是什么样子有理解就行。
|
||
|
||
比如想要首页的展示形式是这样:
|
||
![](https://static001.geekbang.org/resource/image/ca/2f/cae7c6eb3fc8971f5e4534538e78232f.png?wh=1920x589)
|
||
|
||
它对应的markdown为dos/README.md:
|
||
|
||
```markdown
|
||
---
|
||
home: true
|
||
actionText: 开始体验
|
||
actionLink: /guide/introduce
|
||
footer: MIT Licensed | Copyright © 2020-present jianfengye
|
||
features:
|
||
- title: 基于协议
|
||
details: 服务与服务间的协议是基于协议进行交互的。
|
||
- title: 前后端协同
|
||
details: 前后端协同开发
|
||
- title: 命令行
|
||
details: 有充分的命令行工具
|
||
- title: 集成定时服务
|
||
details: 如果你需要启动定时服务,提供命令进行定时服务的启动
|
||
- title: 文档丰富
|
||
details: 提供丰富的文档说明,提供丰富的文档说明
|
||
- title: 开发模式
|
||
details: 在开发模式下进行前后端开发,极大提高了开发效率和开发体验
|
||
|
||
```
|
||
|
||
根据vuepress的官方文档,我们需要在docs目录下创建一个.vuepress/config.js ,来给vuepress工具阅读,也就是用来告诉vuepress工具,你需要按照这个配置的信息生成HTML文件。这里的所有配置都在[官网](https://vuepress.vuejs.org/zh/config)有说明。
|
||
|
||
我们的config.js的配置如下:
|
||
|
||
```javascript
|
||
module.exports = {
|
||
title: "hade框架", // 设置网站标题
|
||
description: "一个支持前后端开发的基于协议的框架", //描述
|
||
dest: "./dist/", // 设置输出目录
|
||
port: 2333, //端口
|
||
base: "/v1.0/",
|
||
head: [["link", {rel: "icon", href: "/assets/img/head.png"}]],
|
||
themeConfig: {
|
||
//主题配置
|
||
// logo: "/assets/img/head.png",
|
||
// 添加导航栏
|
||
nav: [
|
||
{text: "主页", link: "/"}, // 导航条
|
||
{text: "使用文档", link: "/guide/"},
|
||
{text: "服务提供者", link: "/provider/"},
|
||
{
|
||
text: "github",
|
||
// 这里是下拉列表展现形式。
|
||
items: [
|
||
{
|
||
text: "hade",
|
||
link: "https://github.com/gohade/hade",
|
||
},
|
||
],
|
||
},
|
||
],
|
||
// 为以下路由添加侧边栏
|
||
sidebar: {
|
||
"/guide/": [
|
||
{
|
||
title: "指南",
|
||
collapsable: false,
|
||
children: [
|
||
"introduce",
|
||
"install",
|
||
"build",
|
||
"structure",
|
||
"app",
|
||
"env",
|
||
"dev",
|
||
"command",
|
||
"cron",
|
||
"middleware",
|
||
"swagger",
|
||
"provider",
|
||
"todo",
|
||
],
|
||
},
|
||
],
|
||
"/provider/": [
|
||
{
|
||
title: "服务提供者",
|
||
collapsable: false,
|
||
children: [
|
||
"app",
|
||
"env",
|
||
"config",
|
||
"log",
|
||
],
|
||
},
|
||
],
|
||
},
|
||
},
|
||
};
|
||
|
||
|
||
```
|
||
|
||
说明下几个重点配置项。
|
||
|
||
dest这个配置项指定了我们生成HTML的目标文件夹,这里定义为dist目录。base代表所有页面的访问前缀,我们定义为和版本号一致的/v1.0/。这样设置最终会有什么效果呢?
|
||
|
||
由于hade会有多个版本,而我们希望访问地址的URL中带着版本信息,这样就能通过URL来访问不同的版本信息。比如hade.funaio.cn/v1.0/,访问v1.0的版本信息;hade.funaio.cn/v1.1/ 访问v1.1的版本信息。所以使用/v1.0/的base,能让所有的访问信息都带上这个前缀,就能访问到不同版本的框架信息了。
|
||
|
||
themeConfig.nav是配置导航栏的,我们的导航栏有四个信息。
|
||
![](https://static001.geekbang.org/resource/image/f7/59/f72cd0a32e3d76bf5b67798dbe495e59.png?wh=318x52)
|
||
|
||
所以在themeConfig.nav中需要定义四个子项,子项目的text表示显示文本,而link表示点击这个文本之后的链接地址。比如:
|
||
|
||
```javascript
|
||
{text: "使用文档", link: "/guide/"},
|
||
|
||
```
|
||
|
||
表示“使用文档”这个文本点击之后,会查找/guide/目录下的README文件。
|
||
|
||
而/guide/目录下的所有文件是通过themeConfig.sidebar设置侧边栏的,也就是刚才代码的第29到47行。最终通过这段的设置,点击首页的“使用文档”链接,就会进入如下的效果:
|
||
![](https://static001.geekbang.org/resource/image/c7/16/c72c2edcdc7f4ed9abe098a3285ae016.png?wh=1308x638)
|
||
左边的每个链接都对应docs/guide/中的每个markdown文件。
|
||
|
||
### 生成HTML
|
||
|
||
docs下的markdown文件都编写完成了,下面我们就安装vuepress并且生成HTML。安装vuepress,只需要使用npm命令:
|
||
|
||
```go
|
||
npm install -D vuepress
|
||
|
||
```
|
||
|
||
就能安装最新版本的vuepress。截止11月13日,目前vuepress的2.0还处在beta版本,最稳定版本是1.8.2。在安装过程中你可能会遇到这个错误:
|
||
|
||
```plain
|
||
TypeError: Cannot read property 'createHash' of undefined
|
||
|
||
```
|
||
|
||
这个错误是提示我们的Webpack版本较低,使用命令升级Webpack就行。
|
||
|
||
```plain
|
||
npm i webpack@4.8.3
|
||
|
||
```
|
||
|
||
安装好vuepress之后,我们就可以在package.json中设置vuepress的调试和编译命令了:
|
||
|
||
```go
|
||
{
|
||
"name": "hade",
|
||
...
|
||
"scripts": {
|
||
...
|
||
"docs:dev": "vuepress dev docs",
|
||
"docs:build": "vuepress build docs"
|
||
},
|
||
|
||
```
|
||
|
||
增加了docs:dev 和 docs:build 来运行vuepress。
|
||
|
||
这里我们使用 `npm run docs:build` ,就能生成对应markdown的HTML了,非常方便。
|
||
![](https://static001.geekbang.org/resource/image/85/37/85a2882ca4500282f43d23110fc07537.png?wh=698x518)
|
||
|
||
可以看到dist目录中已经生成了对应的HTML文件:
|
||
![](https://static001.geekbang.org/resource/image/f0/9b/f0671ba855661eb73fb4c4a49f65ed9b.png?wh=321x168)
|
||
|
||
最后将这个HTML文件部署到Web服务器中。这里我们部署在目标服务器的的/webroot/hade\_doc/dist\_1.0目录中。具体部署方法也没有什么难点,通过FTP或者SETP上传dist目录内容到目标目录即可。
|
||
|
||
我们的目标服务器配置的Web服务器为Nginx,Nginx如何配置,你可以参考:
|
||
|
||
```plain
|
||
server {
|
||
server_name hade.funaio.cn;
|
||
access_log logs/hade.access.log main;
|
||
error_log logs/hade.error.log ;
|
||
|
||
location /v1.0/ {
|
||
alias /webroot/hade_doc/dist_1.0/;
|
||
index index.html index.htm;
|
||
}
|
||
|
||
location / {
|
||
root /webroot/hade_doc/dist_1.0/;
|
||
index index.html index.htm;
|
||
}
|
||
}
|
||
|
||
```
|
||
|
||
配置hade.funaio.cn/v1.0/ 来访问目录路径 /webroot/hade\_doc/dist\_1.0/ ,同时hade.funaio.cn/也是访问/webroot/hade\_doc/dist\_1.0/。
|
||
|
||
这样每次我们的版本有更新的时候,创建一个新的目标目录存放这个版本的HTML,比如 /webroot/hade\_doc/dist\_1.1/。而在nginx上,只需要增加一个路径/v1.1/来提供hade.funaio.cn/v1.1/的访问路径,让使用者访问v1.1的文档。
|
||
|
||
于是,我们hade框架的网站文档:[http://hade.funaio.cn](http://hade.funaio.cn) 就正式搭建起来了。
|
||
![](https://static001.geekbang.org/resource/image/c2/6c/c235a8ce622fdfa33e6dc382bfac566c.png?wh=1920x855)
|
||
|
||
看到这里,相信你应该理解了,我们的文档维护是基于hade项目中自带的docs/ 目录下的markdown 来进行的。你可以通过GitHub上的[markdown](https://github.com/gohade/coredemo/blob/geekbang/29/README.md) 来查看框架文档,也可以通过网站 hade.funaio.cn 来查看框架文档。这两者本质上都是通过markdown来编写的。
|
||
|
||
而markdown会随着hade框架的发布而发布,同时网站也是根据markdown生成的。这种方法既能避免文档和框架不一致的问题,又能大大降低维护网站的成本。
|
||
|
||
这节课我们没有修改框架的Go代码,主要创建了包含markdown文件的docs目录。目录截图放在这里供你你参考。所有代码也同步到了[geekbang/29](https://github.com/gohade/coredemo/tree/geekbang/29) 分支上了。
|
||
![](https://static001.geekbang.org/resource/image/c0/25/c0c15e07407e6a7102913446ed46b725.png?wh=361x670)
|
||
|
||
## 小结
|
||
|
||
今天我们为框架的升级和维护设计了一套完整的方案。hade框架的发布和文档维护都有自己的独特设计,比如框架的发布,直接和hade框架的命令行工具进行了关联,只要发布了一个新版本,使用者就能直接用命令行工具使用这个新版本创建一个脚手架。而文档维护,是通过编写markdown以及hade框架已经集成的Vue,来自动生成网站HTML。
|
||
|
||
截止到这节课,hade框架的功能就开发完毕了,GitHub上的coredemo项目也就不再更新了,之前的所有代码,我们都会移动到真正的hade项目的 [https://github.com/gohade/hade](https://github.com/gohade/hade) 地址,并且我们为代码发布了发布版本:v1.0.0,后续会基于这个版本不断迭代更新,如果你有兴趣,欢迎一起来完善这个框架。
|
||
|
||
### 思考题
|
||
|
||
马上我们会进入实战环节,使用hade框架开发具体应用,会使用到Vue和Element-UI的知识,当然在后面我们也会稍微介绍一些前端知识,不过如果你之前完全没有接触过,可以花一些时间预习一下,这样学习的时候才能事半功倍。
|
||
|
||
所以今天就给你分享一些相关资料:
|
||
|
||
* [vue中文官网](https://cn.vuejs.org/index.html),学习Vue必看内容
|
||
* [element-ui官网](https://element.eleme.io/#/zh-CN),一款快速搭建网站的UI框架,目前国内最火
|
||
* [awesome-vue](https://github.com/rumengkai/awesome-vue),收集Vue的一些优秀开源项目,绝对收藏
|
||
* [vue router官网](https://router.vuejs.org/zh),Vue的路由必备
|
||
* [webpack官网](https://v4.webpack.docschina.org/concepts),Vue的打包工具
|
||
|
||
欢迎在留言区分享你的学习笔记。感谢你的收听,如果你觉得今天的内容对你有所帮助,也欢迎分享给你身边的朋友,邀请他一起学习。我们实战篇见。
|
||
|