摘要:瀏覽器緩存簡(jiǎn)單介紹下面來(lái)簡(jiǎn)單介紹一下瀏覽器緩存,以及為何我要在標(biāo)題中強(qiáng)調(diào)該去則去,該留則留。但后來(lái)我還是反轉(zhuǎn)了自己,這種方法雖然能留下瀏覽器緩存,卻做不到該去則去。
本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請(qǐng)勿轉(zhuǎn)載。前言
原文地址:https://segmentfault.com/a/1190000010317802
如果您對(duì)本系列文章感興趣,歡迎關(guān)注訂閱這里:https://segmentfault.com/blog/array_huang
一個(gè)成熟的項(xiàng)目,自然離不開(kāi)迭代更新;那么在部署前端這一塊,我們免不了總是要顧及到瀏覽器緩存的,本文將介紹如何在 webpack (架構(gòu))的幫助下,妥善處理好瀏覽器緩存。
實(shí)際上,我很早以前就想寫(xiě)這一part了,只是苦于當(dāng)時(shí)我所掌握的方案不如人意,便不敢獻(xiàn)丑了;而自從
webpack 升級(jí)到 v2 版本后,以及第三方plugin的日益豐富,我們也有了更多的手段來(lái)處理cache。
下面來(lái)簡(jiǎn)單介紹一下瀏覽器緩存,以及為何我要在標(biāo)題中強(qiáng)調(diào)“該去則去,該留則留”。
瀏覽器緩存是啥?瀏覽器緩存(Browser Cache),是瀏覽器為了節(jié)省網(wǎng)絡(luò)帶寬、加快網(wǎng)站訪問(wèn)速度而推出的一項(xiàng)功能。瀏覽器緩存的運(yùn)行機(jī)制是這樣的:
用戶(hù)使用瀏覽器第一次訪問(wèn)某網(wǎng)站頁(yè)面,該頁(yè)面上引入了各種各樣的靜態(tài)資源(js/css/圖片/字體……),瀏覽器會(huì)把這些靜態(tài)資源,甚至是頁(yè)面本身(html文件),都一一儲(chǔ)存到本地。
用戶(hù)在后續(xù)的訪問(wèn)中,如果需要再次請(qǐng)求同樣的靜態(tài)資源(根據(jù) url 進(jìn)行匹配),且靜態(tài)資源沒(méi)有過(guò)期(服務(wù)器端有一系列判別資源是否過(guò)期的策略,比如Cache-Control、Pragma、ETag、Expires、Last-Modified),則直接使用前面本地儲(chǔ)存的資源,而不需要重復(fù)請(qǐng)求。
由于webpack只負(fù)責(zé)構(gòu)建生成網(wǎng)站前端的靜態(tài)資源,不涉及服務(wù)器,因此本文不討論以HTTP Header為基礎(chǔ)的緩存控制策略;那我們討論什么呢?
很簡(jiǎn)單,由于瀏覽器是根據(jù)靜態(tài)資源的url來(lái)判斷該靜態(tài)資源是否已有緩存,而靜態(tài)資源的文件目錄又是相對(duì)固定的,那么重點(diǎn)明顯就在于靜態(tài)資源的文件名了;我們就通過(guò)操控靜態(tài)資源的文件名,來(lái)決定靜態(tài)資源的“去留”。
瀏覽器緩存,該留不留會(huì)怎么樣?每次部署上線新版本,靜態(tài)資源的文件名若有變化,則瀏覽器判斷是第一次讀取這個(gè)靜態(tài)資源;那么,即便這個(gè)靜態(tài)資源的內(nèi)容跟上一版的完全一致,瀏覽器也要重新下載這個(gè)靜態(tài)資源,浪費(fèi)網(wǎng)絡(luò)帶寬、拖慢頁(yè)面加載速度。
瀏覽器緩存,該去不去會(huì)怎么樣?每次部署上線新版本,靜態(tài)資源的文件名若沒(méi)有變化,則瀏覽器判斷可加載之前緩存下來(lái)的靜態(tài)資源;那么,即便這個(gè)靜態(tài)資源的內(nèi)容跟上一版的有所變化,瀏覽器也察覺(jué)不到,使用了老版本的靜態(tài)資源。那這會(huì)造成什么樣的影響呢?可大可小,小至用戶(hù)看到的依然是老版的資源,達(dá)不到上線更新版本的目的;大至造成網(wǎng)站運(yùn)行報(bào)錯(cuò)、布局錯(cuò)位等問(wèn)題。
如何通過(guò)操控靜態(tài)資源的文件名達(dá)到控制瀏覽器緩存的目的呢?在webpack關(guān)于文件名命名的配置中,存在一系列的變量(或者理解成命名規(guī)則也可),通過(guò)這些變量,我們可以根據(jù)所要生成的文件的具體情況來(lái)進(jìn)行命名,而不必預(yù)設(shè)好一個(gè)固定的名稱(chēng)。在緩存處理這一塊,我們主要用到[hash]和[chunkhash]這兩個(gè)變量。關(guān)于這兩個(gè)變量的介紹,我在之前的文章 —— 《webpack配置常用部分有哪些?》就已經(jīng)解釋過(guò)是什么意思了,這里就不再累述。
這里總結(jié)下[hash]和[chunkhash]這兩個(gè)變量的用法:
用[hash]的話,由于每次使用 webpack 構(gòu)建代碼的時(shí)候,此 hash 字符串都會(huì)更新,因此相當(dāng)于強(qiáng)制刷新瀏覽器緩存。
用[chunkhash]的話,則會(huì)根據(jù)具體 chunk 的內(nèi)容來(lái)形成一個(gè) hash 字符串來(lái)插入到文件名上;換句說(shuō), chunk 的內(nèi)容不變,該 chunk 所對(duì)應(yīng)生成出來(lái)的文件的文件名也不會(huì)變,由此,瀏覽器緩存便能得以繼續(xù)利用。
有哪些資源是需要兼顧瀏覽器緩存的?理論上來(lái)說(shuō),除了HTML文件外(HTML文件的路徑需要保持相對(duì)固定,只能從服務(wù)器端入手),webpack生成的所有文件都需要處理好瀏覽器緩存的問(wèn)題。
js在 webpack 架構(gòu)下,js文件也有不同類(lèi)型,因此也需要不同的配置:
入口文件(Entry):在webpack配置中的output.filename參數(shù)中,讓生成的文件名中帶上[chunkhash]即可。
異步加載的chunk:output.chunkFilename參數(shù),操作同上。
通過(guò)CommonsChunkPlugin生成的文件:在CommonsChunkPlugin的配置參數(shù)中有filename這一項(xiàng),操作同上。但需要注意的是,如果你使用[chunkhash]的話,webpack 構(gòu)建的時(shí)候可是會(huì)報(bào)錯(cuò)的哦;那可咋辦呢,用[hash]的話,這common chunk不就每次上線新版本都強(qiáng)制刷新了嗎?這其實(shí)是因?yàn)?,webpack 的 runtime && manifest 會(huì)統(tǒng)一保存在你的common chunk里,解決的方法,就請(qǐng)看下面關(guān)于“webpack 的 runtime && manifest”的部分了。
css對(duì)于css來(lái)說(shuō),如果你是用style-loader直接把css內(nèi)聯(lián)到里的,那么,你管好引入該css的js文件的瀏覽器緩存就好了。
而如果你是使用extract-text-webpack-plugin把css獨(dú)立打包成css文件的,那么在文件名的配置上,同樣加上[chunkhash]即可加上[contenthash]即可(感謝@FLYiNg_hbt 提醒)。這個(gè)[contenthash]是什么東西呢?其實(shí)就是extract-text-webpack-plugin為了與[chunkhash]區(qū)分開(kāi),而自定義的一個(gè)命名規(guī)則,其實(shí)際含義跟[chunkhash]可以說(shuō)是一致的,只是[chunkhash]已被占用作為 chunk 的內(nèi)容 hash 字符串了,繼續(xù)用[chunkhash]會(huì)造成下述問(wèn)題。
如《聽(tīng)說(shuō)webpack連圖片和字體也能打包?》里介紹的,處理這類(lèi)靜態(tài)資源一般使用url-loader或file-loader。
對(duì)于url-loader來(lái)說(shuō),就不需要關(guān)心瀏覽器緩存了,因?yàn)樗前鸯o態(tài)資源轉(zhuǎn)化成 dataurl 了,而并非獨(dú)立的文件。
而對(duì)于file-loader來(lái)說(shuō),同樣是在文件名的配置上加上[chunkhash]即可。另外需要注意的是,url-loader一般搭配有降級(jí)到file-loader的配置(使用loader加載的文件大于一個(gè)你設(shè)定的值就降級(jí)到使用file-loader來(lái)加載),同樣需要在文件名的配置上加上[chunkhash]。
webpack 的runtime && manifest所謂的runtime,就是幫助 webpack 編譯構(gòu)建后的打包文件在瀏覽器運(yùn)行的一些輔助代碼段,換句話說(shuō),打包后的文件,除了你自己的源碼和npm庫(kù)外,還有 webpack 提供的一點(diǎn)輔助代碼段。
而 manifest,則是 webpack 用以查找 chunk 真實(shí)路徑所使用的一份關(guān)系表,簡(jiǎn)單來(lái)說(shuō),就是 chunk 名對(duì)應(yīng) chunk 路徑的關(guān)系表。manifest 一般來(lái)說(shuō)會(huì)被藏到 runtime 里,因此我們查看 runtime 的時(shí)候,雖然能找得到 manifest,但一般都不那么直觀,形如下面這一段(僅common chunk部分):
u.type = "text/javascript", u.charset = "utf-8", u.async = !0, u.timeout = 12e4, n.nc && u.setAttribute("nonce", n.nc), u.src = n.p + "" + e + "." + { 0: "e6d1dff43f64d01297d3", 1: "7ad996b8cbd7556a3e56", 2: "c55991cf244b3d833c32", 3: "ecbcdaa771c68c97ac38", 4: "6565e12e7bad74df24c3", 5: "9f2774b4601839780fc6" }[e] + ".bundle.js";runtime && manifest被打包到哪里去了?
那么,這runtime && manifest的代碼段,會(huì)被放到哪里呢?一般來(lái)說(shuō),如果沒(méi)有使用CommonsChunkPlugin生成common chunk,runtime && manifest會(huì)被放在以入口文件為首的chunk(俗稱(chēng)“大包”)里,如果是我們這種多頁(yè)(又稱(chēng)多入口)應(yīng)用,則會(huì)每個(gè)大包一份runtime && manifest;這夸張的冗余我們自然是不能忍的,那么
用上CommonsChunkPlugin后,runtime && manifest就會(huì)統(tǒng)一遷到common chunk了。
雖說(shuō)把runtime && manifest遷到common chunk后,代碼冗余的問(wèn)題算是解決了,但卻造成另一問(wèn)題:由于我們?cè)谏鲜龅撵o態(tài)資源的文件名命名上都采用了[chunkhash]的方案,因此也使得只要我們稍一改動(dòng)源代碼,就會(huì)有起碼一個(gè) chunk 的命名會(huì)產(chǎn)生變化,這就會(huì)導(dǎo)致我們的runtime && manifest也產(chǎn)生變化,從而導(dǎo)致我們的common chunk也發(fā)生變化,這或許就是 webpack 規(guī)定含有runtime && manifest的common chunk不能使用[chunkhash]的原因吧(反正chunkhash肯定會(huì)變的,還不如不用呢是不是)。
要解決上述問(wèn)題(這問(wèn)題很?chē)?yán)重啊我摔,common chunk怎么能用不上緩存啊,這可是最大的chunk啊),我們就需要把runtime && manifest給獨(dú)立出去。方法也很簡(jiǎn)單,在用來(lái)打包common chunk的CommonsChunkPlugin后,再加一CommonsChunkPlugin:
/* 抽取出所有通用的部分 */ new webpack.optimize.CommonsChunkPlugin({ name: "commons/commons", // 需要注意的是,chunk的name不能相同?。?! filename: "[name]/bundle.[chunkhash].js", // 由于runtime獨(dú)立出去了,這里便可以使用[chunkhash]了 minChunks: 4, }), /* 抽取出webpack的runtime代碼,避免稍微修改一下入口文件就會(huì)改動(dòng)commonChunk,導(dǎo)致原本有效的瀏覽器緩存失效 */ new webpack.optimize.CommonsChunkPlugin({ name: "webpack-runtime", filename: "commons/commons/webpack-runtime.[hash].js", // 注意runtime只能用[hash] }),
這樣一來(lái),runtime && manifest代碼段就會(huì)被打包到這個(gè)名為webpack-runtime的 chunk 里了。這是什么原理呢?據(jù)說(shuō)是在使用CommonsChunkPlugin的情況下, webpack 會(huì)把runtime && manifest打包到最后面的一個(gè)CommonsChunkPlugin生成的 chunk 里,而如果這個(gè)chunk沒(méi)有其它代碼,那么自然就達(dá)到了把runtime && manifest獨(dú)立出去的目的了。
需要注意的是,如果你用了html-webpack-plugin來(lái)生成html頁(yè)面,記得要把這runtime && manifest的 chunk 插入到html頁(yè)面上,不然頁(yè)面報(bào)錯(cuò)了可不怪我哦。
至此,由于runtime && manifest獨(dú)立出去成一個(gè)chunk了,于是common chunk的命名便可以使用[chunkhash]了,也就是說(shuō),common chunk現(xiàn)在也能做到公共模塊內(nèi)容有更新了,才更新文件名;另一方面,這個(gè)獨(dú)立出去的 runtime && manifest chunk,是每次 webpack 打包構(gòu)建的時(shí)候都會(huì)更新了。
有必要把 manifest 從 runtime && manifest chunk 中獨(dú)立出去嗎?是的,不用驚訝,的確是有這么一個(gè)騷操作。
把 manifest 獨(dú)立出去的理由是這樣的:manifest 獨(dú)立出去后,runtime 的部分基本上就不會(huì)有變動(dòng)了;到這里,我們就知道,runtime && manifest里實(shí)際上就是 manifest 在變;因此把 manifest 獨(dú)立出去,也是進(jìn)一步地利用瀏覽器緩存(可以把 runtime 的緩存保留下來(lái))。
具體是怎么做的呢?主流有倆方案:
利用chunk-manifest-webpack-plugin把 manifest 生成一個(gè)json文件,然后由 webpack 異步加載。
如果你是用html-webpack-plugin來(lái)生成html頁(yè)面的話,還可以利用inline-chunk-manifest-html-webpack-plugin(html-webpack-plugin作者推薦)來(lái)把manifest直接輸出到html頁(yè)面上,這樣就能省一個(gè) Http 請(qǐng)求了。
我試用過(guò)第二種方案,好使,但最終還是放棄了,為什么呢?
把 manifest 獨(dú)立出去后,只剩下 runtime 的 chunk 的命名還是只能用[hash],而不能利用[chunkhash],這就導(dǎo)致我們根本沒(méi)法利用瀏覽器緩存。后來(lái),我又想出一個(gè)折衷的辦法,連[hash]也不要了,直接寫(xiě)死一個(gè)文件名;這樣的話,的確瀏覽器緩存就能保存下來(lái)了。但后來(lái)我還是反轉(zhuǎn)了自己,這種方法雖然能留下瀏覽器緩存,卻做不到“該去則去”。或許大家會(huì)有疑問(wèn),你不是說(shuō) runtime 不會(huì)變的嗎,那留下緩存有什么關(guān)系呀?是的,在同一 webpack 環(huán)境下 runtime 的確不會(huì)變,但難保 webpack 環(huán)境改變后,這runtime會(huì)怎么樣呀。比如說(shuō) webpack 的版本升級(jí)了、 webpack 的配置改了、loader & plugin 的版本升級(jí)了,在這些情況下,誰(shuí)敢保證 runtime 永遠(yuǎn)不會(huì)變?。窟@ runtime 一用錯(cuò)了過(guò)期的緩存,那很可能整個(gè)系統(tǒng)都會(huì)崩潰的啊,這個(gè)險(xiǎn)我實(shí)在是冒不起,所以只能作罷。
不過(guò)我看了下Array-Huang/webpack-seed的runtime && manifest chunk,也才 2kb 而已嘛,你們管好自己的強(qiáng)迫癥和代碼潔癖好嗎?!
緩存問(wèn)題雜項(xiàng) 模塊id帶來(lái)的緩存問(wèn)題webpack 處理模塊(module)間依賴(lài)關(guān)系時(shí),需要給各個(gè)模塊定一個(gè) id 以作標(biāo)識(shí)。webpack 默認(rèn)的 id 命名規(guī)則是根據(jù)模塊引入的順序,賦予一個(gè)整數(shù)(1、2、3……)。當(dāng)你在源碼中任意增添或刪減一個(gè)模塊的依賴(lài),都會(huì)對(duì)整個(gè)
id 序列造成極大的影響,可謂是“牽一發(fā)而動(dòng)全身”了。那么這對(duì)我們的瀏覽器緩存會(huì)有什么樣直接的影響呢?影響就是會(huì)造成,各個(gè)chunk中都不一定有實(shí)質(zhì)的變化,但引用的依賴(lài)模塊id卻都變了,這明顯就會(huì)造成 chunk 的文件名的變動(dòng),從而影響瀏覽器緩存。
webpack 官方文檔里推薦我們使用一個(gè)已內(nèi)置進(jìn) webpack2 里的 plugin:HashedModuleIdsPlugin,這個(gè) plugin 的官方文檔在這里。
webpack1 時(shí)代便有一個(gè)NamedModulesPlugin,它的原理是直接使用模塊的相對(duì)路徑作為模塊的 id,這樣只要模塊的相對(duì)路徑,模塊 id 也就不會(huì)變了。那么這個(gè)HashedModuleIdsPlugin對(duì)比起NamedModulesPlugin來(lái)說(shuō)又有什么進(jìn)步呢?
是這樣的,由于模塊的相對(duì)路徑有可能會(huì)很長(zhǎng),那么就會(huì)占用大量的空間,這一點(diǎn)是一直為社區(qū)所詬病的;但這個(gè)HashedModuleIdsPlugin是根據(jù)模塊的相對(duì)路徑生成(默認(rèn)使用md5算法)一個(gè)長(zhǎng)度可配置(默認(rèn)截取4位)的字符串作為模塊的 id,那么它占用的空間就很小了,大家也就可以安心服用了。
To generate identifiers that are preserved over builds, webpack supplies the NamedModulesPlugin (recommended for development) and HashedModuleIdsPlugin (recommended for production).
從上可知,官方是推薦開(kāi)發(fā)環(huán)境用NamedModulesPlugin,而生產(chǎn)環(huán)境用HashedModuleIdsPlugin的,原因似乎是與熱更新(hmr)有關(guān);不過(guò)就我看來(lái),僅在生產(chǎn)環(huán)境用HashedModuleIdsPlugin就行了,開(kāi)發(fā)環(huán)境還管啥瀏覽器緩存啊,俺開(kāi) chrome dev-tool 設(shè)置了不用任何瀏覽器緩存的。
用法也挺簡(jiǎn)單的,直接加到plugin參數(shù)就成了:
plugins: { // 其它plugin new webpack.HashedModuleIdsPlugin(), }由某些 plugin 造成的文件改動(dòng)監(jiān)測(cè)失敗
有些 plugin 會(huì)生成獨(dú)立的 chunk 文件,比如CommonsChunkPlugin或ExtractTextPlugin(從js中提取出css代碼段并生成獨(dú)立的css文件) 。
這些 plugin 在生成 chunk 的文件名時(shí),可能沒(méi)料想到后續(xù)還會(huì)有其它 plugin (比如用來(lái)混淆代碼的UglifyJsPlugin)會(huì)對(duì)代碼進(jìn)行修改,因此,由此生成的 chunk 文件名,并不能完全反映文件內(nèi)容的變化。
另外,ExtractTextPlugin有個(gè)比較嚴(yán)重的問(wèn)題,那就是它生成文件名所用的[chunkhash]是直接取自于引用該css代碼段的 js chunk ;換句話說(shuō),如果我只是修改 css 代碼段,而不動(dòng) js 代碼,那么最后生成出來(lái)的css文件名依然沒(méi)有變化,這可算是非常嚴(yán)重的瀏覽器緩存“該去不去”問(wèn)題了。
2017-07-26 改動(dòng):改用[contenthash]便不會(huì)出現(xiàn)此問(wèn)題,上見(jiàn)css部分
有一款 plugin 能解決以上問(wèn)題:webpack-plugin-hash-output。
There are other webpack plugins for hashing out there. But when they run, they don"t "see" the final form of the code, because they run before plugins like webpack.optimize.UglifyJsPlugin. In other words, if you change webpack.optimize.UglifyJsPlugin config, your hashes won"t change, creating potential conflicts with cached resources.The main difference is that webpack-plugin-hash-output runs in the last compilation step. So any change in webpack or any other plugin that actually changes the output, will be "seen" by this plugin, and therefore that change will be reflected in the hash.
簡(jiǎn)單來(lái)說(shuō),就是這個(gè)webpack-plugin-hash-output會(huì)在 webpack 編譯的最后階段,重新對(duì)所有的文件取文件內(nèi)容的 md5 值,這就保證了文件內(nèi)容的變化一定會(huì)反映在文件名上了。
用法也比較簡(jiǎn)單:
plugins: { // 其它plugin new HashOutput({ manifestFiles: "webpack-runtime", // 指定包含 manifest 在內(nèi)的 chunk }), }總結(jié)
瀏覽器緩存很重要,很重要,很重要,出問(wèn)題了怕不是要給領(lǐng)導(dǎo)追著打。另外,這一塊的細(xì)節(jié)特別多,必須方方面面都顧到,不然哪一方面出了紕漏就全局泡湯。
示例代碼諸位看本系列文章,搭配我在Github上的腳手架項(xiàng)目食用更佳哦(笑):Array-Huang/webpack-seed(https://github.com/Array-Huang/webpack-seed)。
附系列文章目錄(同步更新)webpack多頁(yè)應(yīng)用架構(gòu)系列(一):一步一步解決架構(gòu)痛點(diǎn)
webpack多頁(yè)應(yīng)用架構(gòu)系列(二):webpack配置常用部分有哪些?
webpack多頁(yè)應(yīng)用架構(gòu)系列(三):怎么打包公共代碼才能避免重復(fù)?
webpack多頁(yè)應(yīng)用架構(gòu)系列(四):老式j(luò)Query插件還不能丟,怎么兼容?
webpack多頁(yè)應(yīng)用架構(gòu)系列(五):聽(tīng)說(shuō)webpack連less/css也能打包?
webpack多頁(yè)應(yīng)用架構(gòu)系列(六):聽(tīng)說(shuō)webpack連圖片和字體也能打包?
webpack多頁(yè)應(yīng)用架構(gòu)系列(七):開(kāi)發(fā)環(huán)境、生產(chǎn)環(huán)境傻傻分不清楚?
webpack多頁(yè)應(yīng)用架構(gòu)系列(八):教練我要寫(xiě)ES6!webpack怎么整合Babel?
webpack多頁(yè)應(yīng)用架構(gòu)系列(九):總有刁民想害朕!ESLint為你阻擊垃圾代碼
webpack多頁(yè)應(yīng)用架構(gòu)系列(十):如何打造一個(gè)自定義的bootstrap
webpack多頁(yè)應(yīng)用架構(gòu)系列(十一):預(yù)打包Dll,實(shí)現(xiàn)webpack音速編譯
webpack多頁(yè)應(yīng)用架構(gòu)系列(十二):利用webpack生成HTML普通網(wǎng)頁(yè)&頁(yè)面模板
webpack多頁(yè)應(yīng)用架構(gòu)系列(十三):構(gòu)建一個(gè)簡(jiǎn)單的模板布局系統(tǒng)
webpack多頁(yè)應(yīng)用架構(gòu)系列(十四):No復(fù)制粘貼!多項(xiàng)目共用基礎(chǔ)設(shè)施
webpack多頁(yè)應(yīng)用架構(gòu)系列(十五):論前端如何在后端渲染開(kāi)發(fā)模式下夾縫生存
webpack多頁(yè)應(yīng)用架構(gòu)系列(十六):善用瀏覽器緩存,該去則去,該留則留
本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請(qǐng)勿轉(zhuǎn)載。
原文地址:https://segmentfault.com/a/1190000010317802
如果您對(duì)本系列文章感興趣,歡迎關(guān)注訂閱這里:https://segmentfault.com/blog/array_huang
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/84271.html
摘要:瀏覽器緩存簡(jiǎn)單介紹下面來(lái)簡(jiǎn)單介紹一下瀏覽器緩存,以及為何我要在標(biāo)題中強(qiáng)調(diào)該去則去,該留則留。但后來(lái)我還是反轉(zhuǎn)了自己,這種方法雖然能留下瀏覽器緩存,卻做不到該去則去。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請(qǐng)勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/1190000010317802如果您對(duì)本系列文章感興趣,歡迎關(guān)注訂閱這里:h...
摘要:在上一篇文章多頁(yè)應(yīng)用架構(gòu)系列二配置常用部分有哪些中,我介紹了如何配置多頁(yè)應(yīng)用的入口,然而,如果僅僅如此操作,帶來(lái)的后果就是,打包生成出來(lái)的每一個(gè)入口文件都會(huì)完整包含所有代碼。的初始化常用參數(shù)有哪些,給這個(gè)包含公共代碼的命個(gè)名唯一標(biāo)識(shí)。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請(qǐng)勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/1190...
摘要:本文首發(fā)于的技術(shù)博客實(shí)用至上,非經(jīng)作者同意,請(qǐng)勿轉(zhuǎn)載。原文地址如果您對(duì)本系列文章感興趣,歡迎關(guān)注訂閱這里這系列文章講什么本系列文章主要介紹如何用這一當(dāng)前流行的構(gòu)建工具來(lái)設(shè)計(jì)一個(gè)多頁(yè)應(yīng)用的架構(gòu)。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請(qǐng)勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/1190000006843916如果您對(duì)本系列文章...
摘要:前端日?qǐng)?bào)精選刺破的心臟之響應(yīng)式源碼分析語(yǔ)法樹(shù)與代碼轉(zhuǎn)化實(shí)踐,,的區(qū)別被多數(shù)人誤解的可編程代碼說(shuō)明文檔的幾種選擇中文技術(shù)周刊期中的變量和作用域?qū)W習(xí)筆記教程中的掘金又一個(gè)模板引擎掘金的雙向性學(xué)習(xí)筆記十之掘金學(xué)習(xí)筆記源碼閱讀掘 2017-07-24 前端日?qǐng)?bào) 精選 刺破 Vue 的心臟之——響應(yīng)式源碼分析JavaScript 語(yǔ)法樹(shù)與代碼轉(zhuǎn)化實(shí)踐IaaS,PaaS,SaaS 的區(qū)別被多數(shù)人誤...
摘要:本文首發(fā)于的技術(shù)博客實(shí)用至上,非經(jīng)作者同意,請(qǐng)勿轉(zhuǎn)載。如果你使用了,或類(lèi)似的,那么,通過(guò)編譯前后的代碼相差就很大了,這會(huì)造成兩個(gè)問(wèn)題以為例把你的代碼轉(zhuǎn)成什么樣你自己是無(wú)法控制的,這往往導(dǎo)致無(wú)法通過(guò)的審查。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請(qǐng)勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/1190000007030775如果您...
閱讀 3769·2021-09-02 15:11
閱讀 4777·2021-08-16 10:47
閱讀 1662·2019-08-29 18:35
閱讀 3181·2019-08-28 17:54
閱讀 2933·2019-08-26 11:37
閱讀 1574·2019-08-23 16:51
閱讀 1897·2019-08-23 14:36
閱讀 1879·2019-08-23 14:21