道阻且长

道阻且长

问君西游何时还,畏途巉岩不可攀。
twitter
github

前端项目 OSS 访问部署踩坑记录

事件背景#

部门内同时有多项业务的存在,为了便于访问和管理,整个系统采用乾坤架构,每个业务开发自己的子应用,然后统一挂载到基座应用使用。其大致结构如下:

  Project tree
.
├── ASCM
│   └── index.html
├── OSCM
│   └── index.html
├── PSCM
│   └── index.html
├── TMS
│   └── index.html
├── VSCM
│   └── index.html
├── assets
│   ├── dist.css
│   └── dist.js
└── index.html

7 directories, 8 files

在过去相当长的一段时间里,我们的全部应用都是在编译机器上编译打包后上传,然后 Nginx 中直接指定静态文件目录来访问。配置如下:

server {
  listen 80;
  server_name xxx.test.demo.local;

  client_max_body_size 15M;
  access_log logs/halley.access.log log_access; # 日志输出目录
  gzip on;
  gzip_min_length 1k;

  location ^~ / {
    root /mnt/work/h5/project-dist/;
    index index.html index.htm;
    try_files $uri $uri/ /index.html;
  }
}

本来这是很普通常用的方案。但是由于内部运维平台自身的一些问题,在把新的主应用部署到生产环境的时候(测试和预发没有问题),会直接清空掉整个 Project 文件夹的内容再释放新资源,而不是单纯的覆盖。这就意味着每次更新都会清空掉内部的子应用,使得基座发版 === 重新发布全部应用

虽然发版频率并不高(一个月两次左右),但是随着子应用的数目增加,这依旧成了一项很重的负担。更不论某些和工厂相关的应用白天不能中断,只能放到半夜一起更新,遂萌生了彻底解决问题的念头。

然而,在和运维沟通后,得知现在使用的运维平台几乎无人维护,有需求要自行迁移到另一套系统。

迁移过程#

发布原理#

在中台上使用容器作为构建环境,读取仓库内用户自行编写的 build.sh 进行构建,构建后将 dist 目录下的产物推送到 oss/s3 上,然后通过内部路由将 url 解析到 index.html 的 oss/s3 地址上。

项目更新#

编写脚本#

在项目下新增 build.sh,内容为

#! /bin/sh
. ~/.profile
yarn install --registry http://npm.xxxx.local:7001 --ignore-engines
export CICD_STATIC_PATH=$(echo $CICD_STATIC_PATH) && yarn build

构建系统会把本次构建内容的 oss 地址存储为 CICD_STATIC_PATH 变量,在脚本中自行获取后传递给 webpack 用以构建资源。

更新 Webpack#

修正 webpack.config.js 中相关资源路径

const publicPath = {
  dev: `http://${process.env.HOST}:${process.env.PORT}/`,
  production: process.env.CICD_STATIC_PATH
};
{
  path: __dirname + '/dist/', // 将打包好的文件放在此路径下,dev 模式中,只会在内存中存在,不会真正的打包到此路径
  publicPath: publicPath[process.env.NODE_ENV], // 文件解析路径,index.html 中引用的路径会被设置为相对于此路径
  filename: process.env.NODE_ENV === 'dev' ? 'bundle.js' : 'bundle-[contenthash].js' // 编译后的文件名字
}

更新 Nginx 配置#

server {
  listen 80;
  server_name xxx.test.demo.local;

  client_max_body_size 15M;
  access_log /var/log/nginx/halley.access.log ; # 日志输出目录
  gzip on;
  gzip_min_length 1k;

  location ^~ / {
    proxy_set_header X-Scheme $scheme; # 传递协议
    proxy_set_header Host apisix-area.test.demo.com; # 传递域名
    proxy_set_header X-Real-IP $remote_addr; # 传递 ip
    proxy_set_header REMOTE-HOST $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    add_header X-Rewrite-Result $uri;
    proxy_intercept_errors on;
    error_page 400 403 404 500 = 200 /index.html;
    proxy_pass http://apisix-area.test.demo.com/xxx/xxx-project/;
  }
}

其中 http://apisix-area.test.demo.com 由运维统一提供,静态资源路径在构建时由 shell 脚本从 CICD_STATIC_PATH 变量读取。

更新后不再使用静态资源,而是完全通过 proxy_pass 代理到远程 oss 上的资源进行访问。由于项目是 React 构建,拥有自己的前端路由,并且 js/css 等静态资源会被自动上传到 CICD_STATIC_PATH 这个域名下,所以此处只需要把访问失败的请求全都代理到 oss 上的 index.html 即可。

题外话#

配置 Nginx 的时候自行在本地用 docker 起一个服务来做测试会方便一点,免得更新服务端配置又要没完地扯皮。感觉其中很多时间都浪费在了找人和走流程上面,蛮不愉快的。

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。