利用 nginx + 阿里云部署 Angular/Vue/React 等 SPA 应用

背景

随着 Angular/Vue/React 等 SPA 框架的普及,前后端分离已经深入人心,而 SPA 应用的部署和简单的静态网页的部署又有着微妙的区别,本文就来介绍结合 nginx 和阿里云来使用的一套带预生产环境的 SPA 应用部署方案。

SPA 在 html5 mode 下的域名解析

当 SPA 应用开启 html5 mode 的情况下,指定 url 下的全部请求都会访问入口文件(一般情况下是 index.html),然后 SPA 应用会根据 url 再去决定访问的实际页面。如使用 express 做服务器可以理解为:

1
2
3
app.use("/**", function (req, res) {
res.sendfile(staticPath+"/index.html");
});

具体实现可参考我的另一篇文章 使用 Express 实现一个简单的 SPA 静态资源服务器

使用 nginx 来解析 SPA 应用

与简单的静态网页的部署不同,我们需要将指定 url 下的全部请求都返回 index.html 的内容,其实 nginx 配置的实现方式有很多,这里我们来使用一个讨巧的处理方法,那就是将 404 指向 index.html,实现 nginx 配置如下:

1
2
3
4
5
6
7
8
9
10
server {
listen 80;
server_name dongsj.cn;
index index.html;
root /opt/static/spa-website/;
location / {
index index.html;
try_files $uri $uri/ /index.html =404;
}
}

使用 rsync 上传代码到服务器

部署代码有多种方式,因 SPA 应用的打包和 npm 依赖安装等众多因素,我选择了 rsync 直击上传代码到服务器而不是使用 docker 进行部署。
安装和命令可参考rsync官方网站: https://www.samba.org/ftp/rsync/rsync.html
我们可以直接将同步命令添加至 package.json:

1
2
3
"scripts": {
"rsync": "rsync -azP ./public/ server:/opt/static/spa-website/"
}

分别部署 develop 和 master 分支

实际开发过程中,我们一般都会将开发代码和线上代码分别放在两个分支中,此处以 develop 和 master 分支为例,在服务器分别建立两个目录来存储 SPA 应用打包后的代码,并配置 package.json 的命令如下:

1
2
3
4
"scripts": {
"rsync:develop": "rsync -azP ./public/ server:/opt/static/develop/spa-website/",
"rsync:master": "rsync -azP ./public/ server:/opt/static/master/spa-website/",
}

并应用以下 nginx 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server {
listen 80;
server_name develop.dongsj.cn;
index index.html;
root /opt/static/develop/spa-website/;
location / {
index index.html;
try_files $uri $uri/ /index.html =404;
}
}
server {
listen 80;
server_name master.dongsj.cn;
index index.html;
root /opt/static/master/spa-website/;
location / {
index index.html;
try_files $uri $uri/ /index.html =404;
}
}

配置 nginx 缓存时间和代码压缩

对于 SPA 应用,我们可以配置一定时间的静态文件缓存(如js/css/img等),但 index.html 的缓存时间要配置的尽可能短。添加 nginx 配置如下:

1
2
3
4
5
6
7
8
9
map $sent_http_content_type $expires {
default off;
text/html -10d;
text/css 1d;
application/javascript 1d;
~image/ 1d;
}
# 顺手再配置下gzip代码压缩
gzip_types text/plain text/css application/json application/x-javascript application/javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;

至此,使用 nginx 部署的 spa 应用和命令已基本完成。

使用阿里云的全站加速来实现预生产环境

在实际工作过程中,我们除了开发环境和生产环境外,往往还需要一个预生产环境来验证代码,假设各环境和对应域名如下:

  • 开发环境:develop.dongsj.cn
  • 预生产环境:master.dongsj.cn
  • 生产环境:www.dongsj.cn
    开发环境和预生产环境可以直接使用上文的 nginx 配置,当然生产环境也可以选择手动进行部署,本文我们选择使用阿里云的全站加速来实现预生产环境到生产环境的资源同步。
    首先我们进入阿里云的全站加速控制台添加一个加速域名,加速域名填写生产环境的域名(www.dongsj.cn),源站信息选择源站域名并填写预生产环境的域名(master.dongsj.cn)。
    添加加速域名
    注意,加速区域如果选择中国大陆,则国外ip(包含翻墙的情况)均无法访问。
    确定后阿里云会进入生成CNAME的配置阶段
    等待阿里云生成CNAME
    阿里云CNAME生成完成后,我们要在域名解析为生产环境的域名(www.dongsj.cn)添加域名解析:
    阿里云生成CNAME完成
    配置域名解析
    配置成功后阿里云的全站加速控制台的该域名加速状态就可变为已完成了。
    域名解析配置成功
    最后我们要关闭阿里云的动态加速并添加缓存配置,既修改动态同步预生产和生产环境资源为手动同步:
    关闭动态加速
    添加缓存配置
    至此,阿里云全站加速配置就完成了,当我们更新预生产环境资源时,生产环境不会受到任何影响,而在预生产环境验证完成后,可以进入全站加速的刷新预热来刷新缓存同步生产环境的资源。
    刷新缓存