道阻且长

道阻且长

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

前端項目 OSS 訪問部署踩坑記錄

事件背景#

部門內同時有多項業務的存在,為了便於訪問和管理,整個系統採用乾坤架構,每個業務開發自己的子應用,然後統一掛載到基座應用使用。其大致結構如下:

  專案樹
.
├── ASCM
   └── index.html
├── OSCM
   └── index.html
├── PSCM
   └── index.html
├── TMS
   └── index.html
├── VSCM
   └── index.html
├── assets
   ├── dist.css
   └── dist.js
└── index.html

7 個目錄,8 個文件

在過去相當長的一段時間裡,我們的全部應用都是在編譯機器上編譯打包後上傳,然後 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 起一個服務來做測試會方便一點,免得更新服務端配置又要沒完地扯皮。感覺其中很多時間都浪費在了找人和走流程上面,蠻不愉快的。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。