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