大公司是怎麼發佈靜態資源的

靜態資源(Static Resources): js、css、img 等非服務器動態運行生成的文件。css

在通常的網站中,靜態資源使用頻率高,流量佔用大。對於有追求(訪問量稍大)的網站,都會把靜態資源放置到 CDN 服務器,不佔用業務服務器的網絡帶寬,而達到更好的用戶體驗。那大公司的靜態資源是怎麼發佈的呢?html

發佈要求

1. 靜態資源必須走 CDN

如非自建 CDN,推薦 又拍雲,阿里雲,七牛雲。前端

2. 平滑升級--非覆蓋式發佈

在不修改線上靜態資源的狀況下,發佈新的靜態資源。即 CDN 上的靜態資源必須共存多個靜態資源版本webpack

負責百度 FIS 的核心功能開發者張雲龍已經給出了 部署的方案非覆蓋式發佈。他的文中提到:nginx

  1. 先部署頁面,再部署資源:在兩者部署的時間間隔內,若是有用戶訪問頁面,就會在新的頁面結構中加載舊的資源,而且把這個舊版本的資源當作新版本緩存起來,其結果就是:用戶訪問到了一個樣式錯亂的頁面,除非手動刷新,不然在資源緩存過時以前,頁面會一直執行錯誤。git

  2. 先部署資源,再部署頁面:在部署時間間隔以內,有舊版本資源本地緩存的用戶訪問網站,因爲請求的頁面是舊版本的,資源引用沒有改變,瀏覽器將直接使用本地緩存,這種狀況下頁面展示正常;但沒有本地緩存或者緩存過時的用戶訪問網站,就會出現舊版本頁面加載新版本資源的狀況,致使頁面執行錯誤,但當頁面完成部署,這部分用戶再次訪問頁面又會恢復正常了。github

3. 精確的緩存控制——文件版本號

更新靜態資源,只更新修改的部分。不能修改未更新的資源的引用。web

在 CDN 的配置中,會把緩存的時間設置很長。文件的更新就須要一種靈活的機制,也不能每次發佈版本就把全部文件更新一遍,全量更新靜態資源對於用戶和服務提供者來講都是很是不友好的,極度浪費 CDN 資源和用戶的流量。
好比: a.html 頁面引用了 100 個靜態資源文件,可是本次發版本只修改了一個a.js文件。那麼就只能修改 a.js 文件的引用,可能修改成 a.hash.js算法

解決辦法:根據文件的內容算出一個值,若是文件內容不改變,那麼這個值就不會改變。gulp

張雲龍的文章中給出了『精確的緩存控制』的原理————咱們會很天然的聯想到利用 數據摘要要算法 對文件求摘要信息,摘要信息與文件內容一一對應,就有了一種能夠精確到單個文件粒度的緩存控制依據了。

Grunt,gulp 也有對應的插件用來解決這個問題。若是你使用 webpack,那麼能夠配置下 chunkhash 或者 hash。更厲害的,文章末尾還有相關的解決方案。

發佈和問題

1. 發佈流程

靜態資源發佈流程圖

若是咱們把靜態資源的實際訪問域名設置爲 res.company.com

  1. 功能開發結束後,開發人員把靜態資源提交到測試環境 Git 倉庫。

  2. 測試人員在測試環境經過綁定 host 的方式測試,測試經過後,進入發佈階段,須要靜態資源代碼提交到產品環境 Git 倉庫。(使用測試和產品兩個倉庫,是爲了測試和產品環境徹底隔離)

  3. 源站(origin.res.company.com)從產品環境 Git 拉取靜態資源的代碼,而且爲靜態資源提供訪問服務(nginx 等),該域名不提供文件緩存服務,僅僅做爲 CDN 的回源地址。因此代碼中必定不要寫源站的信息。

  4. 在 CDN 服務商提供的空間中,將回源地址配置爲源站(origin.res.company.com)。

  5. CDN 服務器會提供一個默認的訪問域名,好比 cdn-1.res.cdn_company.com, 而後把實際需求訪問的靜態資源域名 res.company.com CNAME 到 cdn-1.res.cdn_company.com

  6. 代碼發佈完畢。用戶訪問的時候,會訪問到最近的 CDN 階段。CDN 結點去文件中心取文件,若是不存在文件則回源到源站,獲取文件。(有些 CDN 產品提供文件存儲功能,異地備份)

  7. 經過這樣的流程,就能讓用戶訪經過 CDN 訪問到咱們的實際資源。

2. 怎麼作到多個項目共存

結論:咱們會按照目錄來劃分業務的靜態資源。

res.company.com 域名下面會共存多個業務。A 業務、B 業務都是使用一樣的發佈方案。
好比某靜態資源的訪問路徑爲:http://res.company.com/:業務名/js/test.de5b0b0c.js

多個團隊可使用同一個靜態資源倉庫,res.git,而後按照目錄來區分業務。web 服務器直接指向到 res/便可。靜態資源更新只須要 pull 代碼便可,而不需求作其餘改動。

3. 是否同步源站文件到 CDN

結論:同步源站文件到 CDN 能確保實現非覆蓋式發佈。

又拍雲等 CDN 服務商都提供了這些貼心的服務,就算你提交了新的同名文件,那也是不會生效的。

CDN 回源

  1. 終端用戶就近訪問 CDN 加速節點上的資源

  2. 若 CDN 加速節點上不存在資源,則回源獲取資源

  3. 回源獲取的資源持久化存儲到 CDN

  4. 返回資源內容給終端用戶

  5. 當終端用戶再次訪問相同的資源時,CDN 的加速節點將直接返回資源內容,不須要從新回源獲取

另外我還作了測試,在未作源站遷移的狀況下,刪掉源站文件,會出現大面積的 404 響應。
未作源站遷移

推薦工具

  1. 超厲害的 CDN 服務商——又拍雲

  2. 微信出品的前端工程化工具——tmt-workflow

  3. 百度團隊出品——FIS

  4. 京東的非官方——JDF

  5. 能打造最牛逼的工程化工具——webpack

參考文檔

  1. 大公司裏怎樣開發和部署前端代碼?

  2. 前端工程精粹(一):靜態資源版本更新與緩存

  3. 又拍雲【功能介紹】源站資源遷移

相關文章
相關標籤/搜索