靜態資源(Static Resources): js、css、img 等非服務器動態運行生成的文件。css
在通常的網站中,靜態資源使用頻率高,流量佔用大。對於有追求(訪問量稍大)的網站,都會把靜態資源放置到 CDN 服務器,不佔用業務服務器的網絡帶寬,而達到更好的用戶體驗。那大公司的靜態資源是怎麼發佈的呢?html
如非自建 CDN,推薦 又拍雲,阿里雲,七牛雲。前端
在不修改線上靜態資源的狀況下,發佈新的靜態資源。即 CDN 上的靜態資源必須共存多個靜態資源版本。webpack
負責百度 FIS 的核心功能開發者張雲龍已經給出了 部署的方案,非覆蓋式發佈。他的文中提到:nginx
先部署頁面,再部署資源:在兩者部署的時間間隔內,若是有用戶訪問頁面,就會在新的頁面結構中加載舊的資源,而且把這個舊版本的資源當作新版本緩存起來,其結果就是:用戶訪問到了一個樣式錯亂的頁面,除非手動刷新,不然在資源緩存過時以前,頁面會一直執行錯誤。git
先部署資源,再部署頁面:在部署時間間隔以內,有舊版本資源本地緩存的用戶訪問網站,因爲請求的頁面是舊版本的,資源引用沒有改變,瀏覽器將直接使用本地緩存,這種狀況下頁面展示正常;但沒有本地緩存或者緩存過時的用戶訪問網站,就會出現舊版本頁面加載新版本資源的狀況,致使頁面執行錯誤,但當頁面完成部署,這部分用戶再次訪問頁面又會恢復正常了。github
更新靜態資源,只更新修改的部分。不能修改未更新的資源的引用。web
在 CDN 的配置中,會把緩存的時間設置很長。文件的更新就須要一種靈活的機制,也不能每次發佈版本就把全部文件更新一遍,全量更新靜態資源對於用戶和服務提供者來講都是很是不友好的,極度浪費 CDN 資源和用戶的流量。
好比: a.html
頁面引用了 100 個靜態資源文件,可是本次發版本只修改了一個a.js
文件。那麼就只能修改 a.js
文件的引用,可能修改成 a.hash.js
。算法
解決辦法:根據文件的內容算出一個值,若是文件內容不改變,那麼這個值就不會改變。gulp
張雲龍的文章中給出了『精確的緩存控制』的原理————咱們會很天然的聯想到利用 數據摘要要算法 對文件求摘要信息,摘要信息與文件內容一一對應,就有了一種能夠精確到單個文件粒度的緩存控制依據了。
Grunt,gulp 也有對應的插件用來解決這個問題。若是你使用 webpack,那麼能夠配置下 chunkhash 或者 hash。更厲害的,文章末尾還有相關的解決方案。
若是咱們把靜態資源的實際訪問域名設置爲 res.company.com
。
功能開發結束後,開發人員把靜態資源提交到測試環境 Git 倉庫。
測試人員在測試環境經過綁定 host 的方式測試,測試經過後,進入發佈階段,須要靜態資源代碼提交到產品環境 Git 倉庫。(使用測試和產品兩個倉庫,是爲了測試和產品環境徹底隔離)
源站(origin.res.company.com)從產品環境 Git 拉取靜態資源的代碼,而且爲靜態資源提供訪問服務(nginx 等),該域名不提供文件緩存服務,僅僅做爲 CDN 的回源地址。因此代碼中必定不要寫源站的信息。
在 CDN 服務商提供的空間中,將回源地址配置爲源站(origin.res.company.com)。
CDN 服務器會提供一個默認的訪問域名,好比 cdn-1.res.cdn_company.com
, 而後把實際需求訪問的靜態資源域名 res.company.com
CNAME 到 cdn-1.res.cdn_company.com
。
代碼發佈完畢。用戶訪問的時候,會訪問到最近的 CDN 階段。CDN 結點去文件中心取文件,若是不存在文件則回源到源站,獲取文件。(有些 CDN 產品提供文件存儲功能,異地備份)
經過這樣的流程,就能讓用戶訪經過 CDN 訪問到咱們的實際資源。
結論:咱們會按照目錄來劃分業務的靜態資源。
res.company.com
域名下面會共存多個業務。A 業務、B 業務都是使用一樣的發佈方案。
好比某靜態資源的訪問路徑爲:http://res.company.com/:業務名/js/test.de5b0b0c.js
。
多個團隊可使用同一個靜態資源倉庫,res.git
,而後按照目錄來區分業務。web 服務器直接指向到 res/
便可。靜態資源更新只須要 pull 代碼便可,而不需求作其餘改動。
結論:同步源站文件到 CDN 能確保實現非覆蓋式發佈。
又拍雲等 CDN 服務商都提供了這些貼心的服務,就算你提交了新的同名文件,那也是不會生效的。
終端用戶就近訪問 CDN 加速節點上的資源
若 CDN 加速節點上不存在資源,則回源獲取資源
回源獲取的資源持久化存儲到 CDN
返回資源內容給終端用戶
當終端用戶再次訪問相同的資源時,CDN 的加速節點將直接返回資源內容,不須要從新回源獲取
另外我還作了測試,在未作源站遷移的狀況下,刪掉源站文件,會出現大面積的 404 響應。