部署
# 10.部署
博客写完后,当然是要发布到网络上的。如果想要部署到服务器上,则需编译构建成静态文件,然后将其上传到服务器上的路径(该路径由我们自己决定),然后在web服务器(Nginx等)上配置访问路径即可
这里说的是有自己服务器的情况,如果嫌麻烦和没预算可以使用GitHub Pages服务
# 构建静态文件
VuePress提供了vuepress build docs
命令来构建,也就是我们之前在package.json里配置的docs:build
:
"scripts": {
"docs:dev": "vuepress dev docs --temp .temp",
"docs:build": "vuepress build docs",
},
2
3
4
我们在命令行里执行,结果如下:
> npm run docs:build
> vuepress-learn@1.0.0 docs:build
> vuepress build docs
wait Extracting site metadata...
tip Apply theme @vuepress/theme-default ...
tip Apply plugin container (i.e. "vuepress-plugin-container") ...
tip Apply plugin @vuepress/register-components (i.e. "@vuepress/plugin-register-components") ...
tip Apply plugin @vuepress/active-header-links (i.e. "@vuepress/plugin-active-header-links") ...
tip Apply plugin @vuepress/search (i.e. "@vuepress/plugin-search") ...
tip Apply plugin @vuepress/nprogress (i.e. "@vuepress/plugin-nprogress") ...
√ Client
Compiled successfully in 14.78s
√ Server
Compiled successfully in 4.35s
wait Rendering static HTML...
success Generated static files in docs\.vuepress\dist.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
我们观察最后一行,VuePress告诉我们成功生成了静态文件在这个目录:docs.vuepress\dist
。我们无需关心里面的内容,只需将整个目录上传到服务器上即可(FTP或者压缩后上传)
# Nginx配置
这里已经假设读者有了服务器和安装了Nginx。
以笔者部署的过程为例:
将dist文件夹里的内容上传到/opt/myblog目录下(可以压缩dist目录为压缩包,然后上传再解压)
配置Nginx:
location / { root /opt/myblog; index index.html index.htm; }
1
2
3
4重启Nginx
访问服务器IP,即可看到博客内容,并且可以正常跳转等,和本地运行的效果一致
# GitHub Pages
一个服务器后续的续费高达几千元一年;如果不想要购买服务器和配置域名等等,可以使用GitHub Pages,也是不少人在使用的方式;
但博主本人没有用过,因此也没有去尝试,感兴趣的读者可参考:一篇带你用 VuePress + Github Pages 搭建博客_JavaScript_冴羽_InfoQ写作社区 (opens new window)
# 自动化部署
如果每次修改了博客内容,都要重新构建、然后上传到服务器上,未免也太麻烦了。为此,我们可以用一些第三方工具,自动将打包后的文件上传到服务器上:
- scp2:是一个纯js编写的ssh2协议的Linux远程文件拷贝实现
- ora:是一个优雅的用于命令行Loading的spinner,简单来说就是用来实现命令行环境的loading效果,和显示各种状态的图标等,美观一点。
安装依赖:
npm i scp2 ora@5.0
ora6.0以上版本不支持require方式引入,因为在node中使用,使用5.0版本
在项目里新建两个文件:
- deploy.js:用于编写部署命令
- serverInfo.json:用于存放服务器信息(由于本博客是开源的,不方便将服务器IP和密码等敏感信息公开)
deploy.js的内容:
const fs = require('fs')
const scpClient = require('scp2')
const ora = require('ora')
const serverInfo = JSON.parse(fs.readFileSync('serverInfo.json'))
const loading = ora('正在部署至 ' + serverInfo.host )
loading.start()
scpClient.scp('./docs/.vuepress/dist/', serverInfo ,(err)=>{
loading.stop()
if(err) {
console.log('部署失败')
throw err
}else {
console.log('部署成功')
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
serverInfo.json:存放服务器信息,注意在 .gitignore 文件里添加serverInfo.json,不要将敏感信息公开了。读者需按需修改这些信息
{
"host":"替换成你的IP",
"port":"22",
"username":"替换成你的用户名",
"password":"替换成你的密码",
"path":"/opt/myblog"
}
2
3
4
5
6
7
在package.json中的script中添加deploy命令:
"scripts": {
...
"deploy": "npm run docs:build && node ./deploy.js",
...
},
2
3
4
5
测试:可以删除之前的/opt/myblog目录里的文件
$ cd /opt
$ rm -r myblog/
2
然后在命令行里执行 npm run deploy
,观察是否正常部署了。
> node .\deploy.js
部署成功
2
注意:
- 后续想要部署,直接执行命令即可,会覆盖之前的博客内容。
- 使用GitHub Pages也可以实现自动化部署,这里不展开,可参考:GET 新技能!自己的网站突然就不香了 (opens new window)第3.2节。
- 读者也可以在服务器上,使用git clone 拉取项目,然后npm run docs:build来运行,不过这样也很麻烦。
# 使用GitHub Action
什么是GitHub Action?这里引用阮一峰大佬的说明:GitHub Actions 入门教程 - 阮一峰的网络日志 (opens new window)
大家知道,持续集成由很多操作组成,比如抓取代码、运行测试、登录远程服务器,发布到第三方服务等等。GitHub 把这些操作就称为 actions。
很多操作在不同项目里面是类似的,完全可以共享。GitHub 注意到了这一点,想出了一个很妙的点子,允许开发者把每个操作写成独立的脚本文件,存放到代码仓库,使得其他开发者可以引用。
如果你需要某个 action,不必自己写复杂的脚本,直接引用他人写好的 action 即可,整个持续集成过程,就变成了一个 actions 的组合。这就是 GitHub Actions 最特别的地方。
希望读者看完阮一峰大大的博客后再往下看。
简单来说,就是我们可以使用别人写好的功能,在每次代码推送到Git后,GitHub会自动帮助我们完成编译构建,自动上传到服务器上,重启服务等等操作
一句话:可以实现提交代码到服务器上后,自动更新博客。俗称持续集成、自动化部署。读者也可使用Gitee Action。接下来我们来实践下。
# 服务器准备
首先是服务器得准备下环境,安装 rsync,读者使用的Centos,root用户,安装命令如下:
yum install rsync
然后在服务器上生成公钥和私钥,用来授权
$ ssh-keygen -t rsa -C "peterjxl@qq.com"
然后一直回车即可,执行情况:
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:Pt6bEV/LpmNU5ibmsyJjEstK4DHL2kjAaQvNbz8urok peterjxl@qq.com
The key's randomart image is:
+---[RSA 2048]----+
| |
| |
| |
|.o. o |
|o+* S . +. |
|+o.* .. o+oo. |
| o+ +. oo .+.o+ |
|.= +..=.+o.o=o |
|E +oo+o+.o++o+ |
+----[SHA256]-----+
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
可以看到公钥和私钥的位置。id_rsa就是私钥,id_rsa.pub是公钥。我们需要用到私钥的内容:
cat /root/.ssh/id_rsa
笔者这里就不贴出来了,也算是一种敏感信息
然后修改本机关于ssh的一些配置:如此便完成了公钥的安装。
$ cd /root/.ssh
$ cat id_rsa.pub >> authorized_keys
2
打开密钥登录功能:编辑 /etc/ssh/sshd_config 文件,在文件末尾添加如下几行:
$ RSAAuthentication yes
$ PubkeyAuthentication yes
$ PermitRootLogin yes
2
3
最后,重启 SSH 服务:
$ service sshd restart
# GitHub准备
在项目所在的仓库中配置: 打开Settings->Secrets->New secret
然后将上一步的私钥内容添加进去:
我们再新建一个secret,名字为MY_SERVER_IP
,值为我们的服务器的IP,IP也是一种敏感字段。
# 流水线配置
接下来我们就可以配置流水线了。新建 .github/workflows文件夹,然后再新建main.yml,内容如下:
name: Deploy My Server
on:
push:
branches:
- master # 只在master上push触发部署
jobs:
deploy:
runs-on: ubuntu-latest # 使用ubuntu系统镜像运行自动化脚本
steps: # 自动化步骤
#下载代码仓库
- uses: actions/checkout@v1
# 使用action库,安装node
- name: use Node.js # 使用action库 actions/setup-node安装node
uses: actions/setup-node@v3
with:
node-version: 16
# 安装依赖
- name: npm install
run: npm install
#打包项目
- name: Build
run: npm run docs:build
#部署到服务器
- name: Deploy to Staging My server
uses: easingthemes/ssh-deploy@v2.1.6
env:
# 使用GitHub仓库里的secret设置的值
SSH_PRIVATE_KEY: ${{ secrets.MY_SERVER_PRIVATE_KEY }}
# 源目录,编译后生成的文件目录
SOURCE: './docs/.vuepress/dist/'
#服务器公网地址
REMOTE_HOST: ${{ secrets.MY_SERVER_IP }}
#服务器用户名-一般默认root
REMOTE_USER: 'root'
#服务器中,代码部署的位置
TARGET: '/opt/myblog'
#去除的文件
EXCLUDE: "/dist/, /node_modules/"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
这里简单说明下文件的内容
- 第一行:本次流水线的名字,可自行更换
- 第3~6行:说明只有当master分支有提交到远程库(push)的时候,才更新(也就是执行本次流水线)
- 第8行:jobs,本次我们只用了一个job,也就是第9行的job
- 第10行:指定要在哪个操作系统的环境下编译出包(一般是Linux)
- 接下来就是deploy这个job的steps,每个step做了不同的事情,例如安装node,然后安装依赖和执行构建命令
- 第31行开始就是一些环境变量的设置,例如读取我们上一小节设置的IP和私钥信息
需要注意的是,编译出包和运行部署要在一个job里,不然可能会有这样的情况:编译出包在一个服务器上,但是下一个job用了不同的服务器,导致部署是失败的(因为都不在同一个服务器上执行的流水线,没有文件)
# 测试流水线
每次提交代码到远程仓库,这条流水线就会运行:可以在GitHub项目的Actions选项卡里查看
我们点击本次运行的workflow,可以看到目前正在运行的job:
再点进去,就可以看到这个job里的step执行情况:打勾的说明已完成,黄色的转圈圈的表示还在运行中
如果流水线执行失败了,会有邮件告知,并且可以在Action里查看失败的原因。
还可以重跑失败的jobs:
# 关于GitHub Action部署失败的问题
如果你遇到了GitHub Action部署失败了,报错信息类似这样的:
2023-02-18T12:11:00.0564591Z [BABEL] Note: The code generator has deoptimised the styling of /home/runner/work/vuepress-learn/vuepress-learn/node_modules/lodash/lodash.js as it exceeds the max of 500KB.
2023-02-18T12:11:18.4372148Z [success] [webpackbar] Server: Compiled successfully in 31.22s
2023-02-18T12:11:27.6215689Z [success] [webpackbar] Client: Compiled with some errors in 40.43s
2023-02-18T12:11:27.8557348Z (undefined) ./node_modules/@vuepress/core/.temp/style.styl
2023-02-18T12:11:27.8558854Z Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
2
3
4
5
这是因为@vue/babel-preset-app
的版本问题,解决方法
npm i @vue/babel-preset-app@4.5.18
# 其他部署方式
如果你生成密钥的时候,输入了密码进行保护:
$ ssh-keygen
...
Enter passphrase (empty for no passphrase): # In here can input a password to protect key
2
3
那么部署的时候可能会报错(因为没密码),目前暂无找到其他方法;一般是用没有密码保护的密钥来部署。
如果你不想用密钥登录,而是用密码登录,可以用这个action:appleboy/scp-action: GitHub Action that copy files and artifacts via SSH. (opens new window)
# 使用思源笔记插件
如果你有使用思源笔记,还可以使用terwer (opens new window)开发的思源笔记插件:sy-post-publisher (opens new window),
# 获取源码
本文介绍了几种部署方式,最推荐的是使用GitHub Action,非常方便,一劳永逸。
为了写本系列的博客,博主特地新建了一个项目用于演示,相关代码已放到Gitee (opens new window)和GitHub (opens new window)上。
并且,不同功能创建了不同分支,想要获取本篇文章演示的源码只需切换分支即可!
例如,你想运行本篇文章所创建的博客,可以这样做:
- 打开命令行
- 拉取代码:git clone git@gitee.com:peterjxl/vuepress-learn.git (也可拉取GitHub的)
- 跳转目录:cd vuepress-learn
- 切换分支:git switch -c VuePressDemo6Deploy origin/VuePressDemo6Deploy
- 安装依赖:npm i
- 运行博客:npm run docs:dev