摘要:但在產品模式下,我們非常有必要在的屬性里的里配置一個來變向的為靜態資源注入版本號,如下,以便上線之后頁面可以引入版本更新后的代碼。通過給靜態資源注入值來作為版本號的好處主要有兩個實現策略。
前言
webpack,作為一個處理模塊加載、資源依賴管理、構建化的工具,已經逐漸成為了前端工程化領域的新貴。其創造性的把每個靜態資源歸為一個 module(模塊)并能被其強大的 loader 所加載的這種方式,成功的開辟了前端工程界的另一大生態。基于其官網文檔的完善度較高,這篇文章就不對 webpack 的主要內容做過多的介紹,而是回歸到本文的主題,即通過介紹幾款 webpack 相關的插件,來解決一個常見的工程問題:如何做到靜態資源路徑可以在不同的環境下自動切換。
問題說明這到底是個怎樣的問題?設想一下,在使用 webpack 打包編譯之后,它會生成一個 js 文件,隨后我們需要在 html 或者模板文件里指定這個文件的路徑確保其被正確的引入,
對于開發環境下的單入口文件(稍后會介紹 webpack 打包到多個入口的解決方案 ),這個標簽內的引入文件路徑完全可以寫死,而且在 webpack-dev-server 熱替換機制的幫助下,我們也無須通過對打包生成的文件添加 hash 值來處理因瀏覽器緩存的緣故引起的引用不到最新資源。
但在產品模式下,我們非常有必要在 webpack 的 output 屬性里的 filename 里配置一個 chunkhash 來變向的為靜態資源注入版本號,如下,
output: { filename: [name].[chunkhash].js, }
以便上線之后頁面可以引入版本更新后的代碼。chunkhash 是一個基于文件內容,通過摘要算法(如md5)生成的一個被稱之為文件指紋的序號,即只有當文件內容發生改變的時候,這個值才會相應更改。
通過給靜態資源注入 hash 值來作為版本號的好處主要有兩個:
實現 long term caching 策略。當發布新版本時,我們只需要更新更改了的資源。這比起將新版資源存放在例如/v1.3/xx.js這種帶版本號的路徑或文件夾下的部署方式會顯得更科學一點:減少手動配置版本號的額外操作、已經緩存過且緩存尚未過期的瀏覽器只需請求更新過的資源,確保未變更過的資源可以依舊從緩存內讀取。
實現非覆蓋式發布策略。張云龍老師的原文中提到的這種平滑的版本升級方式更加完美的解決了靜態資源部署至CDN出現的問題。
這個時候我們再來看下線上的 script 引入,
Fine, 也許你會說我可以手動 copy/paste 這個版本號當你需要從開發切到產品環境,額額,單個入口文件這么處理雖是可以,但想象下當有多個入口文件的時候。。。(感覺我的左手大拇指肌腱炎又要犯了。。),這么經典的問題webpack早已準備好了它的解決方案。
從 webpack 的編譯數據里獲取開發與生產的資源路徑對應關系這一部分的工作可以說是解決這個問題的一個核心環節,即我們需要通過 webpack 來生成類似如下一張對應關系圖:
{ "app.js": "http://xxx.cdn.com/app.82076244596568c8c929.js" }
像在 webpack 的 plugin 屬性里配置如下,我們就可以通過返回 webpack 的編譯數據里獲取到帶有 chunkhash 的文件信息:
// webpack.config.js module.exports = { ... plugins: [ function() { this.plugin("done", function(stats) { require("fs").writeFileSync( path.join(__dirname, "..", "stats.json"), JSON.stringify(stats.toJson())); }); } ] }
將 stats.json require 到項目中,通過讀取 publicPath、 assetsByChunkName 屬性,可以得到開發與線上環境資源路徑的對應關系。
webpack 官方也推薦了幾個有同樣效果,我個人覺得更好用的插件:assets-webpack-plugin 或者 webpack-manifest-plugin 來生成出一個 JSON 對應關系文件。
切換資源路徑接下來的工作基本上就是如何利用這個對應關系來切換對應環境下的路徑。這個還要取決于你的頁面是否會涉及到服務端的渲染。
服務端渲染資源路徑
以 node 作為服務端語言,handlebars(或者ejs)為模板語言為例,我們通過編寫模板語言的 helper 來讀取由 assets-webpack-plugin 生成的 stats.json,在不同的環境下實現路徑切換:
stats.json -- webpack 跑開發配置
{ "app": { "js": "app.js" } }
stats.json -- webpack 跑生產配置
{ "app": { "js": "http://xxx.cdn.com/app.82076244596568c8c929.js" } }
example.handlebars
后臺通過 require stats.json 數據并傳入到模板即可實現根據環境動態渲染資源路徑。
如果你的后臺是使用 Rails 來搭建的話,那么這篇文章更詳細的介紹了處理這種情況下處理資源切換的問題
前端渲染頁面模板
如果你的項目不依賴任何后端渲染,那么 html-webpack-plugin 這款插件可以為你動態生成一個帶有 css、js 等資源路徑的 html 文件。
html-webpack-plugin 具體的用法可以點擊這里,其中 inject 這個屬性可以讓你將 script 標簽插入到 dom 的指定位置。為了能夠更大權限的將 webpack 編譯過的資源可以插入到 html 文件的任意位置,我們可以在 HtmlWebpackPlugin 里指定的 template 文件里寫入如下代碼:
<% for (var css in htmlWebpackPlugin.files.css) { %> <% } %>
<% for (var chunk in htmlWebpackPlugin.files.chunks) { %> <% } %>
就可以同樣實現靜態資源的切換,所以對于前端渲染模板的這種情況,我們無須再生成一個 json 文件,對于使用諸如 react、vue 這種框架,僅使用這個插件也是極好的。
htmlWebpackPlugin 具體還有哪些屬性可以配置,可以參考下這個 default template 查看完整例子
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/80670.html
摘要:將開發環境和生產環境的差異降至最低,并使用持續交付實施敏捷開發。可以在工具架構和開發流程不發生明顯變化的前提下實現擴展。我們的初衷是分享在現代軟件開發過程中發現的一些系統性問題,并加深對這些問題的認識。 簡介 如今,軟件通常會作為一種服務來交付,它們被稱為網絡應用程序,或軟件即服務(SaaS)。12-Factor 為構建如下的 SaaS 應用提供了方法論: 使用標準化流程自動配置,從...
摘要:簡單記錄一下學習時遇到的問題,將會持續更新基于的前端方案方案大概有后端模板結合型和前端后端分離型兩種,支持的包也比較多,目前尤大推薦使用的方案相對靠譜。 簡單記錄一下學習meteor時遇到的問題,將會持續更新! 基于meteor的前端方案 方案大概有后端模板結合型和前端后端分離型兩種,支持的包也比較多,目前尤大推薦使用webpack:webpack的方案相對靠譜。 博主自己寫的例子:m...
閱讀 2086·2021-11-23 10:13
閱讀 2794·2021-11-09 09:47
閱讀 2739·2021-09-22 15:08
閱讀 3317·2021-09-03 10:46
閱讀 2233·2019-08-30 15:54
閱讀 915·2019-08-28 18:09
閱讀 2431·2019-08-26 18:26
閱讀 2342·2019-08-26 13:48