摘要:關於使用 Nginx 開啟靜態網站 Gzip 壓縮的教程已經有很多了,但是好像沒幾個講怎麼在物件儲存的靜態網站中開啟 Gzip 壓縮。其實也不復雜,我們一起來看下~
本文分享自華為雲社群《將 Vue.js 專案部署至靜態網站託管,並開啟 Gzip 壓縮》,作者:雲端儲存開發者支援團隊。
關於使用 Nginx 開啟靜態網站 Gzip 壓縮的教程已經有很多了,但是好像沒幾個講怎麼在物件儲存的靜態網站中開啟 Gzip 壓縮。其實也不復雜,我們一起來看下~
1.打包專案
1.1 先安裝 compression-webpack-plugin 外掛:
npm install compression-webpack-plugin --save-dev
1.2 在 vue.config.js 中開啟壓縮外掛(專案下沒有此檔案可以在根目錄下建立):
const CompressionWebpackPlugin = require('compression-webpack-plugin'); module.exports = defineConfig({ transpileDependencies: true, configureWebpack: config => { config.externals = {} if (process.env.NODE_ENV === 'production') { return { plugins: [new CompressionWebpackPlugin({ test: /\.js$|\.html$|\.css/, // 壓縮檔案的字尾 threshold: 1024, // 對超過 1k 的檔案進行壓縮 deleteOriginalAssets: true, // 不需要保留壓縮前檔案 })] } } } })
1.3 執行 npm run build 打包專案,打包後開啟打包產物目錄,可以看到檔案字尾有 .gz
2.開啟靜態網站託管並上傳網站
2.1 建立桶並開啟靜態網站託管
進入物件儲存控制檯,點選右上角建立桶。
這裡桶名需要注意下,全域性唯一,不能與其他人的重複,桶策略選擇公共讀
注意:開啟公共讀後,任何人均能訪問你桶內的資料!!強烈建議這個桶僅用作靜態網站託管,不要存放隱私資料
注意:開啟公共讀後,任何人均能訪問你桶內的資料!!強烈建議這個桶僅用作靜態網站託管,不要存放隱私資料
注意:開啟公共讀後,任何人均能訪問你桶內的資料!!強烈建議這個桶僅用作靜態網站託管,不要存放隱私資料
建立後點選桶名,進入桶配置,點選靜態網站託管,配置靜態網站
此處示例專案比較簡單,預設首頁和預設 404 頁面均填寫 index.html,不需要配置重定向規則
這個網址即是網站地址
此時點選開啟會提示 404,因為我們還沒有上傳網站檔案,接下來會上傳網站檔案並配置 Gzip 壓縮。
2.1.1 配置域名解析
在配置靜態網站時,可以看到有提示從 22 年 3 月開始 OBS 禁止透過預設域名(桶訪問域名或靜態網站訪問域名)使用靜態網站託管功能。如果是新建立的桶,必須要配置桶域名才能訪問。
點選左側域名管理,點選繫結使用者域名
設定完成後,需要去自己的域名供應商處將域名 CNAME 指向 OBS 桶域名,等待一會兒解析生效。
2.2 上傳靜態網站並配置 Gzip 壓縮
這裡先講兩個錯誤步驟和錯誤的原因原因,太長不看可跳轉 # 2.2.2 正確方案 ,更推薦直接參考 # 3 更進一步--自動設定後設資料
2.2.1 試錯手動方案
由於物件儲存的物件名強唯一的,即並不會自動把 xxx.js 指向 xxx.js.gz,此時如果直接把 dist 目錄下檔案上傳到物件儲存並開啟靜態網站託管,會發現瀏覽器找不到 .gz 檔案,會報錯 404,頁面一片空白。
手動版解決方法非常粗暴,直接上傳前把檔名字尾 .gz 去掉再上傳就行,這裡需要記下來都改了哪些檔案的字尾,一會兒要用到。
去除字尾後,請求沒報錯 404 了,但是頁面還是一片空白,這又是為啥?
原因是瀏覽器是根據伺服器發來的請求頭來判斷收到的檔案到底是什麼型別,再決定該如何處理,如果內容被壓縮了,就必須要顯示的告訴瀏覽需要解壓後才能使用。Nginx 配置後,會自動給響應加上說明告知瀏覽器,但是物件儲存不會主動告知,需要我們處理。
手動處理方法也很粗暴,挨個去設定後設資料新增 Content-Encoding: gzip,此處使用 OBS Browser+ 工具,瀏覽器操作類似。
2.2.2 正確方案
- 手動將所有物件的 .gz 字尾去掉
- 挨個去給去過字尾的物件新增後設資料:Content-Encoding: gzip
3. 更進一步 —— 自動設定後設資料
本文用的示例專案比較簡單,只有三個檔案需要改,手工改還不麻煩,但是對與複雜專案可能要幾十上百個檔案,處理起來就非常麻煩,程式設計師的思路就是能程式碼解決就不要動手,這裡我們使用 資料工坊 DWR 服務自動改檔名 + 改字尾。這裡的介紹比較簡單,如果想使用 DWR 進行更為複雜的操作,可以參考這篇博文
3.1 建立函式
首先進入 FunctionGraph 服務,建立一個修改檔名和後設資料的 Serverless 函式。記得切換下 region,選擇目標 OBS 桶所在 Region。
函式內容為
# -*- coding:utf-8 -*- from urllib.parse import unquote_plus from obs import ObsClient, SetObjectMetadataHeader def handler(event, context): # 獲取桶名與物件名 region_id, bucket_name, object_name = get_obs_obj_info(event.get("Records", None)[0]) context.getLogger().info(f"bucket name: {bucket_name}, object key: {object_name}") ak = context.getAccessKey() sk = context.getSecretKey() server = 'obs.' + region_id + '.myhuaweicloud.com' obs_client = ObsClient(access_key_id=ak, secret_access_key=sk, server=server) # 獲取物件 object_content = obs_client.getObject(bucket_name, object_name, loadStreamInMemory=False) # 去掉 .gz 字尾 new_object_name = object_name[:-3] # 重新上傳 resp = obs_client.putObject(bucket_name, new_object_name, content=object_content.body.response) # 設定後設資料 headers = SetObjectMetadataHeader(contentEncoding="gzip") obs_client.setObjectMetadata(bucket_name, new_object_name, headers=headers) context.getLogger().info("Upload Success") return def get_obs_obj_info(record): if 's3' in record: s3 = record['s3'] return record["eventRegion"], s3['bucket']['name'], unquote_plus(s3['object']['key']) else: obs_info = record['obs'] return record["eventRegion"], obs_info['bucket']['name'], \ unquote_plus(obs_info['object']['key'])
新增 OBS SDK 依賴包
3.2 建立工作流
進入DWR 服務控制檯,點選建立工作流
在左側運算元目錄找到自定義,拖到中間新增連線線並在右側選擇函式,點選儲存
儲存後會進入到工作流管理,點選建立觸發器
桶名選擇靜態網站託管的桶,事件源型別為 ObjectCreated,即任何上傳行為均會觸發,字尾填寫 .gz,即只有壓縮型別的檔案才會觸發。
3.3 上傳檔案
重新在 Vue 專案根目錄執行 npm run build 打包專案,這次不需要再去手動改字尾了,直接把打包後結果整個拖入到上傳框點選上傳
4. 驗證已開啟 Gzip 壓縮
配置完成後,再次訪問靜態網站地址,發現已經成功,分析請求響應內容也都是壓縮後的