Note-31132-13

Token ID: 1

ERC-721 1 Transfers

Metadata

{
  "title": "前端项目 OSS 访问部署踩坑记录",
  "tags": [
    "post",
    "踩坑",
    "记录"
  ],
  "summary": "通过 Nginx 的 porxy_pass 来代理存储在 oss/s3 上的 React 项目访问",
  "sources": [
    "xlog"
  ],
  "external_urls": [
    "https://zsakvo.xlog.app/react-project-on-oss"
  ],
  "date_published": "2023-04-07T02:44:43.580Z",
  "content": "## 事件背景\n\n部门内同时有多项业务的存在,为了便于访问和管理,整个系统采用乾坤架构,每个业务开发自己的子应用,然后统一挂载到基座应用使用。其大致结构如下:\n\n```shell\n➜  Project tree\n.\n├── ASCM\n│   └── index.html\n├── OSCM\n│   └── index.html\n├── PSCM\n│   └── index.html\n├── TMS\n│   └── index.html\n├── VSCM\n│   └── index.html\n├── assets\n│   ├── dist.css\n│   └── dist.js\n└── index.html\n\n7 directories, 8 files\n```\n\n\n在过去相当长的一段时间里,我们的全部应用都是在编译机器上编译打包后上传,然后 Nginx 中直接指定静态文件目录来访问。配置如下:\n\n```conf\nserver {\n  listen 80;\n  server_name xxx.test.demo.local;\n\n  client_max_body_size 15M;\n  access_log logs/halley.access.log log_access; # 日志输出目录\n  gzip on;\n  gzip_min_length 1k;\n\n  location ^~ / {\n    root /mnt/work/h5/project-dist/;\n    index index.html index.htm;\n    try_files $uri $uri/ /index.html;\n  }\n}\n```\n\n本来这是很普通常用的方案。但是由于内部运维平台自身的一些问题,在把新的主应用部署到生产环境的时候(测试和预发没有问题),会直接清空掉整个 Project 文件夹的内容再释放新资源,而不是单纯的覆盖。这就意味着每次更新都会清空掉内部的子应用,使得`基座发版 === 重新发布全部应用`\n\n虽然发版频率并不高(一个月两次左右),但是随着子应用的数目增加,这依旧成了一项很重的负担。更不论某些和工厂相关的应用白天不能中断,只能放到半夜一起更新,遂萌生了彻底解决问题的念头。\n\n然而,在和运维沟通后,得知现在使用的运维平台几乎无人维护,有需求要自行迁移到另一套系统。\n\n\n## 迁移过程\n\n### 发布原理\n在中台上使用容器作为构建环境,读取仓库内用户自行编写的 build.sh 进行构建,构建后将 dist 目录下的产物推送到 oss/s3 上,然后通过内部路由将 url 解析到 index.html 的 oss/s3 地址上。\n\n### 项目更新\n\n#### 编写脚本\n在项目下新增 build.sh,内容为\n```shell\n#! /bin/sh\n. ~/.profile\nyarn install --registry http://npm.xxxx.local:7001 --ignore-engines\nexport CICD_STATIC_PATH=$(echo $CICD_STATIC_PATH) && yarn build\n```\n\n构建系统会把本次构建内容的 oss 地址存储为 `CICD_STATIC_PATH` 变量,在脚本中自行获取后传递给 webpack 用以构建资源。\n\n#### 更新 Webpack\n修正 webpack.config.js 中相关资源路径\n```javascript\nconst publicPath = {\n  dev: `http://${process.env.HOST}:${process.env.PORT}/`,\n  production: process.env.CICD_STATIC_PATH\n};\n```\n\n```json\n{\n  path: __dirname + '/dist/', // 将打包好的文件放在此路径下,dev 模式中,只会在内存中存在,不会真正的打包到此路径\n  publicPath: publicPath[process.env.NODE_ENV], // 文件解析路径,index.html 中引用的路径会被设置为相对于此路径\n  filename: process.env.NODE_ENV === 'dev' ? 'bundle.js' : 'bundle-[contenthash].js' // 编译后的文件名字\n}\n```\n\n#### 更新 Nginx 配置\n```conf\nserver {\n  listen 80;\n  server_name xxx.test.demo.local;\n\n  client_max_body_size 15M;\n  access_log /var/log/nginx/halley.access.log ; # 日志输出目录\n  gzip on;\n  gzip_min_length 1k;\n\n  location ^~ / {\n    proxy_set_header X-Scheme $scheme; # 传递协议\n    proxy_set_header Host apisix-area.test.demo.com; # 传递域名\n    proxy_set_header X-Real-IP $remote_addr; # 传递 ip\n    proxy_set_header REMOTE-HOST $remote_addr;\n    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n\n    add_header X-Rewrite-Result $uri;\n    proxy_intercept_errors on;\n    error_page 400 403 404 500 = 200 /index.html;\n    proxy_pass http://apisix-area.test.demo.com/xxx/xxx-project/;\n  }\n}\n```\n其中 `http://apisix-area.test.demo.com` 由运维统一提供,静态资源路径在构建时由 shell 脚本从 `CICD_STATIC_PATH` 变量读取。\n\n更新后不再使用静态资源,而是完全通过 proxy_pass 代理到远程 oss 上的资源进行访问。由于项目是 React 构建,拥有自己的前端路由,并且 js/css 等静态资源会被自动上传到 `CICD_STATIC_PATH` 这个域名下,所以此处只需要把访问失败的请求全都代理到 oss 上的 index.html 即可。\n\n## 题外话\n配置 Nginx 的时候自行在本地用 docker 起一个服务来做测试会方便一点,免得更新服务端配置又要没完地扯皮。感觉其中很多时间都浪费在了找人和走流程上面,蛮不愉快的。\n\n",
  "attributes": [
    {
      "value": "react-project-on-oss",
      "trait_type": "xlog_slug"
    }
  ]
}