整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          關(guān)于html緩存的思考

          、html頁(yè)面會(huì)緩存嗎?

          單純的html頁(yè)面不會(huì)緩存,htm是一種標(biāo)記語(yǔ)言,用來(lái)描述和標(biāo)記的,不能實(shí)現(xiàn)緩存。html里面的JavaScript代碼是當(dāng)這個(gè)html頁(yè)面加載時(shí)瀏覽器解釋執(zhí)行,也不可以實(shí)現(xiàn)數(shù)據(jù)緩存。

          二、html 頁(yè)面怎么對(duì)緩存進(jìn)行設(shè)置

          根據(jù)服務(wù)器系統(tǒng)環(huán)節(jié)的不同設(shè)置方法不一樣

          1、在Apache環(huán)境下

          可以通過(guò)在.htaccess文件中添加下面的代碼,設(shè)置圖片的HTTP緩存和有效期(需要開(kāi)啟apache的headers模塊支持):

          其中max-age后面這個(gè)數(shù)字就是設(shè)置的緩存有效期(以秒為單位),比如上面的代碼設(shè)置了網(wǎng)站的圖片使用為期一年(秒)的HTTP緩存。

          2、在Nginx下

          可以通過(guò)修改nginx.conf配置文件,來(lái)修改緩存設(shè)置:

          location~*\.(flv|gif|jpg|jpeg|png|ico|swf)${;access_logoff;break;}

          注意:同樣的方法,可以給js和css文件設(shè)置緩存。

          html緩存:html5 應(yīng)用程序緩存和瀏覽器緩存有什么區(qū)別

          應(yīng)用程序緩存是會(huì)預(yù)加載的,保證齊全地供應(yīng)和保存。瀏覽器緩存沒(méi)有這些控制,不能作為程序緩存使用。不幸地,應(yīng)用程序緩存過(guò)於簡(jiǎn)單,導(dǎo)致效率不彰,預(yù)期將會(huì)被ServiceWorker取代。

          存是個(gè)老生長(zhǎng)談的問(wèn)題,對(duì)于前端工程師來(lái)講更是我們的必修課。或許很多人會(huì)說(shuō)我的項(xiàng)目并沒(méi)有問(wèn)題,根本不需要聊什么緩存。如果真的是這樣,只能證明你前端道路才剛剛開(kāi)始。

          背景

          小郭今天分享緩存的原因在于:公司的一個(gè)核心APP中嵌入了SPA,而且應(yīng)用核心都分布在SPA中,功能復(fù)雜且重。問(wèn)題出現(xiàn)了:應(yīng)用核心頁(yè)面打開(kāi)一直處于加載狀態(tài),排除掉弱網(wǎng)環(huán)境的原因,重點(diǎn)就在于沒(méi)有緩存,每次進(jìn)入頁(yè)面都需要重載DOM和數(shù)據(jù),拖慢頁(yè)面打開(kāi)速度。

          那應(yīng)該處理緩存問(wèn)題呢?接下來(lái)小郭從三個(gè)方向來(lái)講解。

          瀏覽器緩存策略

          在了解瀏覽器緩存前,我們需要先了解一下相關(guān)的概念:cache-control,expires,last-Modified,ETag。

          瀏覽器通過(guò)請(qǐng)求頭實(shí)現(xiàn)緩存,關(guān)鍵的請(qǐng)求頭有cache-control,expires,last-Modified,ETag等。我們從時(shí)間和空間兩個(gè)角度來(lái)看瀏覽器緩存。

          時(shí)間

          瀏覽器發(fā)送第一次請(qǐng)求:不緩存,服務(wù)端根據(jù)設(shè)定的緩存策略返回相應(yīng)的header,如:cache-control,expires,last-Modified,ETag。

          瀏覽器發(fā)送第二次請(qǐng)求:

          • 強(qiáng)緩存策略:不需要和服務(wù)端通信就決定是否使用緩存,cache-control優(yōu)先級(jí)大于expires① 有cache-control且不過(guò)期,返回本地磁盤緩存,狀態(tài)值200;② 有expires且不過(guò)期,返回本地磁盤緩存,狀態(tài)值200。
          • 協(xié)商緩存策略:需要和服務(wù)端通信決定是否用緩存,Etag優(yōu)先級(jí)大于last-Modified。① 有Etag,請(qǐng)求頭添加If-None-Match,值就是上次返回的Etag值,然后發(fā)送給服務(wù)端。服務(wù)端對(duì)比If-None-Match與現(xiàn)有的Etag值是否一樣;一樣的話只返回header,狀態(tài)碼304,瀏覽器從本地磁盤獲取緩存信息;不一樣走正常流程,返回header+body,狀態(tài)碼200;② 有l(wèi)ast-Modified,添加請(qǐng)求頭If-Modified-Since,值是上次返回的last-Modified,然后發(fā)送給服務(wù)端。服務(wù)端對(duì)比If-Modified-Since與現(xiàn)有的是否一樣;一樣的話返回只返回header,狀態(tài)碼304,瀏覽器從本地磁盤獲取緩存信息;不一樣走正常流程,返回header+body,狀態(tài)碼200
          • 無(wú)緩存

          空間

          • 瀏覽器和服務(wù)端:服務(wù)端需要決定使用哪種緩存策略并在響應(yīng)頭返回;前端不需要設(shè)置,是瀏覽器本身機(jī)制。
          • html和靜態(tài)資源:通常html不設(shè)置緩存,因?yàn)槠渌Y源的入口都是html文件;靜態(tài)資源(js,css,圖片等)會(huì)設(shè)置緩存

          部署時(shí)緩存的問(wèn)題

          如果緩存就按理論上設(shè)置,那就太簡(jiǎn)單了。在實(shí)際應(yīng)用有個(gè)嚴(yán)重的問(wèn)題,我們不僅要緩存代碼,還需要更新代碼。如果靜態(tài)資源名字不變,怎么讓瀏覽器即能緩存又能在有新代碼時(shí)更新。最簡(jiǎn)單的解決方式就是靜態(tài)資源路徑添加一個(gè)版本值,版本不變就走緩存策略,版本變了就加載新資源。如下:

          <script src="xx/xx.js?v=24334452"></script>

          然而這種處理方式在部署時(shí)有問(wèn)題。

          解決方法:靜態(tài)資源和頁(yè)面是分開(kāi)部署

          • 先部署頁(yè)面再部署靜態(tài)資源,會(huì)出現(xiàn)用戶訪問(wèn)到舊的資源
          • 先部署靜態(tài)資源再部署頁(yè)面,會(huì)出現(xiàn)沒(méi)有緩存用戶加載到新資源而報(bào)錯(cuò)

          這些問(wèn)題的本質(zhì)是以上的部署方式是“覆蓋式發(fā)布”,解決方式是“非覆蓋式發(fā)布”。即用靜態(tài)資源的文件摘要信息給文件命名,這樣每次更新資源不會(huì)覆蓋原來(lái)的資源,先將資源發(fā)布上去。這時(shí)候存在兩種資源,用戶用舊頁(yè)面訪問(wèn)舊資源,然后再更新頁(yè)面,用戶變成新頁(yè)面訪問(wèn)新資源,就能做到無(wú)縫切換。簡(jiǎn)單來(lái)說(shuō)就是給靜態(tài)文件名加hash值

          那如何實(shí)現(xiàn)呢?

          現(xiàn)在前端代碼都用webpack之類的構(gòu)建工具打包,那么結(jié)合webpack該怎么做,怎么才能做到持久化緩存?

          webpack持久化緩存

          一、webpack給文件名添加hash值是很簡(jiǎn)單的,但hash/chunkhash/contenthash要用哪個(gè)呢?

          官方定義

          hash: unique hash generated for every build

          chunkhash: hashes based on each chunks' content

          contenthash: hashes generated for extracted content

          根據(jù)分析,contenthash才是我們需要的,內(nèi)容有更新,hash值才會(huì)更新。

          二、webpack會(huì)打包業(yè)務(wù)代碼、第三方庫(kù)及運(yùn)行時(shí)代碼,為保證緩存互不干擾,應(yīng)該將它們提取出來(lái)。

          第三方庫(kù)提取方式是設(shè)置optimization的splitChunks的cacheGroups。splitChunks能提取模塊,cacheGroups能緩存模塊,并且cacheGroups的配置會(huì)覆蓋splitChunks相同配置,既能提取又能緩存,故只需設(shè)置cacheGroups。

          運(yùn)行時(shí)代碼的提取方式為配置runtimeChunk,默認(rèn)為false,表示運(yùn)行時(shí)代碼嵌入到不同的chunk文件中;現(xiàn)在將運(yùn)行時(shí)代碼提取出來(lái),并命名為manifest。

          module.exports = {
            entry: {
              index: "./src/index.js",
              bar: "./src/bar.js"
            },
            output: {
              filename: "[name].[contenthash].js"
            },
            optimization: {
              splitChunks: {
                cacheGroups: {
                  vendor: {
                    test:/[\\/]node_modules[\\/]/,
                    name: "vendors",
                    chunks: "all"
                  }
                }
              },
              runtimeChunk: {
                name: "manifest"
              }
            }
          };

          三、 moduleName 和 chunkName 對(duì)文件的影響

          module:就是js模塊

          chunk:webpack編譯過(guò)程中由多個(gè)module組成的文件

          bundle:bundle是chunk文件的最終狀態(tài),是webpack編譯后的結(jié)果

          一個(gè)文件被分離為3個(gè)文件,文件間怎么相互依賴的,會(huì)影響彼此打包,解決方法是將moduleId和chunkId改成按照文件路徑生成。

          optimization: {
            moduleIds: 'hashed',
            namedModules: true,
            namedChunks: true
          }

          這樣子moduleId在編譯后的文件是文件目錄的hash值,更加安全。這也是namedChunks在production默認(rèn)為false的原因,不想依賴的文件路徑在編譯后的文件直接展示,但是為了持久性緩存,這里也只能打開(kāi)。

          四、CSS文件緩存

          當(dāng)css代碼提取成單獨(dú)文件,當(dāng)我們改變css時(shí),怎么保證不影響引用它的js文件呢?配置如下:

          plugins: [
            new MiniCssExtractPlugin({
              filename: "[contenthash].css"
            })
          ]

          webpack持久化緩存目標(biāo)是當(dāng)且僅當(dāng)該文件內(nèi)容變動(dòng)才改變?cè)撐募值膆ash值

          const MiniCssExtractPlugin = require("mini-css-extract-plugin");
          module.exports = { 
            output: { 
              filename: [name].[contenthash].js, // 讓hash值只在內(nèi)容變動(dòng)時(shí)更新 
              chunkFilename: [name].[contenthash].js // 動(dòng)態(tài)引入的模塊命名,同上 
            }, 
            module: { 
              rules: [ { 
                test: /\.css$/, 
                use: [ 
                  "loader: MiniCssExtractPlugin.loader", // 提取出來(lái)css "css-loader" 
                ] 
              } ] 
            }, 
            optimization: { 
              moduleIds: "hashed", // 混淆文件路徑名 
              runtimeChunk: { name: 'manifest' }, // 提取runtime代碼命名為manifest 
              namedModules: true, // 讓模塊id根據(jù)路徑設(shè)置,避免每增加新模塊,所有id都改變,造成緩存失效的情況 
              namedChunks: true, // 避免增加entrypoint,其他文件都緩存失效 
              cacheGroups: { 
                vendor: { // 提取第三方庫(kù)文件 
                  test: /[\\/]node_modules[\\/]/, 
                  name: 'vendors', chunks: 'all', 
                }, 
              },
            } 
            plugins: [ 
              new webpack.HashedModuleIdsPlugin(), // 與namedModules: true作用一樣 
              new MiniCssExtractPlugin({ 
                filename: "[contenthash].css", // css文件也是按contenthash命名 
                chunkFilename: "[contenthash].css", // 動(dòng)態(tài)引入的css命名,同上 
              }) 
            ], 
          }

          總結(jié)

          瀏覽器有其緩存機(jī)制,想要既能緩存又能在部署時(shí)沒(méi)有問(wèn)題,需要給靜態(tài)文件名添加hash值。在webpack中,有些配置能讓我們實(shí)現(xiàn)持久化緩存。感興趣的同學(xué)可以自行去測(cè)試哦!

          有任何問(wèn)題可以在下方留言,想了解更多前端知識(shí)歡迎關(guān)注公眾號(hào)“一郭鮮”,文章也將同步于公眾號(hào),前端學(xué)習(xí)不迷路

          用場(chǎng)景:

          無(wú)論我們用PC端瀏覽網(wǎng)站還是用的移動(dòng)端,網(wǎng)站都會(huì)緩存一些CSS,JS等文件。尤其是JS,我們常會(huì)寫(xiě)些代碼,我之前曾在蘋果手機(jī)上多番嘗試都沒(méi)辦法清除緩存的文件。后面通過(guò)在JS后面增加版本號(hào)即可解決問(wèn)題。


          那么,我們先來(lái)看看重現(xiàn)問(wèn)題,我們寫(xiě)的JS引用,如下圖:


          以上是沒(méi)有版本號(hào)的,如果你修改了tool.min.js文件,并上傳到服務(wù)器。刷新該頁(yè)面后,仍然對(duì)新修改的不會(huì)有任何響應(yīng),因?yàn)榫彺媪恕?/p>

          解決辦法:

          在后面加上?V=xxx,版本號(hào),那么瀏覽器就會(huì)把它當(dāng)作一個(gè)新的文件,重新加載,如下圖:


          當(dāng)然,我們作為一些長(zhǎng)期維護(hù)的網(wǎng)站,我們的版本號(hào)很可能更多的是這樣:

          <script type="text/javascript" src="https://acstatic-dun.126.net/tool.min.js?v=2022031701"></script>

          其中:

          1)20220317代表的是今天的日期

          2)最后兩位數(shù)字代碼的是當(dāng)天更新的第幾次。

          這樣做了之后,無(wú)論我們?cè)谝苿?dòng)端還是PC端就不會(huì)出現(xiàn)緩存的現(xiàn)象。

          當(dāng)然緩存這塊完全看瀏覽器,不排除有些瀏覽器仍然沒(méi)生效,那就只有清除瀏覽器緩存了。

          不過(guò)怎么主流的IE瀏覽器,微信瀏覽器,GOOGLE器不會(huì)出現(xiàn)這個(gè)問(wèn)題。

          歡迎加我,一起分享開(kāi)發(fā)的思路與代碼


          主站蜘蛛池模板: 麻豆视频一区二区三区| 日韩免费一区二区三区在线播放 | 亚洲AV日韩精品一区二区三区| 国精无码欧精品亚洲一区| 国产视频一区在线播放| 免费播放一区二区三区| 精品久久久久一区二区三区| 免费在线视频一区| 免费无码一区二区三区蜜桃大| 91福利一区二区| 久久91精品国产一区二区| 丝袜人妻一区二区三区| 久久综合一区二区无码| 一区二区国产在线观看| 无码国产亚洲日韩国精品视频一区二区三区| 亚洲乱码av中文一区二区| 在线播放一区二区| 国产一区二区三区影院| 国产99久久精品一区二区| 亚洲中文字幕一区精品自拍 | 精品无人乱码一区二区三区| 亚洲一区无码中文字幕乱码| 麻豆国产一区二区在线观看| 日韩一区二区超清视频| 日本免费一区尤物| 精品一区二区三区四区电影| 国产一区二区三区视频在线观看| 精品乱码一区二区三区在线| 四虎一区二区成人免费影院网址| 日本一区二区三区在线视频| 久久精品无码一区二区日韩AV| 国产免费一区二区三区不卡| 日韩精品无码一区二区中文字幕| 91亚洲一区二区在线观看不卡| 亚洲日韩AV一区二区三区四区| 国产在线无码视频一区| 一区二区乱子伦在线播放| 日本片免费观看一区二区| 国产一区风间由美在线观看| 国产精品 一区 在线| 亚洲一区二区在线视频|