欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

webpack實(shí)現(xiàn)靜態(tài)資源緩存的方法

 更新時(shí)間:2021年08月20日 16:21:03   作者:wonyun  
本文主要介紹了webpack實(shí)現(xiàn)靜態(tài)資源緩存的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

引言

靜態(tài)資源緩存是前端性能優(yōu)化的一個(gè)點(diǎn),所以在前端開(kāi)發(fā)過(guò)程中,一般會(huì)最大限度的利用緩存(這里主要是強(qiáng)緩存)?;氐奖疚闹黝},在使用webpack構(gòu)建的項(xiàng)目中,稍有不慎的話,即使服務(wù)器設(shè)置了緩存策略,可能構(gòu)建的項(xiàng)目無(wú)法實(shí)現(xiàn)靜態(tài)資源緩存。那么webpack怎樣才能達(dá)到使用緩存的效果呢,下面就來(lái)談?wù)勥@個(gè)問(wèn)題。

區(qū)分一下幾種不同的hash

我們都知道,webpack有各種hash值,包括每次項(xiàng)目構(gòu)建hash,不同入口的chunkhash、文件的內(nèi)容contenthash,這么多hash,它們有什么區(qū)別呢?

hash

hash是跟整個(gè)webpack構(gòu)建項(xiàng)目相關(guān)的,每次項(xiàng)目構(gòu)建hash對(duì)應(yīng)的值都是不同的,即使項(xiàng)目文件沒(méi)有做“任何修改”。

其實(shí)是有修改的,因?yàn)槊看蝫ebpack打包編譯都會(huì)注入webpack的運(yùn)行時(shí)代碼,導(dǎo)致整個(gè)項(xiàng)目有變化,所以每次hash值都會(huì)變化的。

以本人項(xiàng)目代碼為例,代碼兩次構(gòu)建前后沒(méi)有做任何修改的對(duì)比圖

可以看出,前后兩次對(duì)應(yīng)項(xiàng)目構(gòu)建hash改變了。由此推斷使用該方式是無(wú)法達(dá)到緩存的,因?yàn)槊看蝖ash都會(huì)變化。

chunkhash

chunkhash,從字面上就能猜出它是跟webpack打包的chunk相關(guān)的。具體來(lái)說(shuō)webpack是根據(jù)入口entry配置文件來(lái)分析其依賴項(xiàng)并由此來(lái)構(gòu)建該entry的chunk,并生成對(duì)應(yīng)的hash值。不同的chunk會(huì)有不同的hash值。一般在項(xiàng)目中把公共的依賴庫(kù)和程序入口文件隔離并進(jìn)行單獨(dú)打包構(gòu)建,用chunkhash來(lái)生成hash值,只要依賴公共庫(kù)不變,那么其對(duì)應(yīng)的chunkhash就不會(huì)變,從而達(dá)到緩存的目的。

一般在項(xiàng)目中對(duì)webpack的entry使用chunkhash,具體表現(xiàn)在output配置項(xiàng)上:

moudule.exports = {
  entry: {
   app: './src/main.js',
   vendor: ['react', 'redux', 'react-dom', 'react-redux', 'react-router-redux']
  },
  output: {
    path:path.join(__dirname, '/dist/js'),
    filename: '[name].[chunkhash].js'
  }
 ...
}

最后app和vendor的chunkhash編譯結(jié)果如下圖

contenthash

contenthash表示由文件內(nèi)容產(chǎn)生的hash值,內(nèi)容不同產(chǎn)生的contenthash值也不一樣。在項(xiàng)目中,通常做法是把項(xiàng)目中css都抽離出對(duì)應(yīng)的css文件來(lái)加以引用。比方在webpack配置這樣來(lái)用:

module.exports = {
  ...
  plugins: [
     new ExtractTextPlugin({
	filename: 'static/[name]_[chunkhash:7].css',
	disable: false,
	allChunks: true
     })
  ...
  ]

上面配置有一個(gè)問(wèn)題,因?yàn)槭褂昧薱hunkhash,它與依賴它的chunk共用chunkhash。

比方在上面app chunk例子中依賴一個(gè)index.css文件,index.css的hash是跟著app的chunkhash走的,只要app文件變更的話,那么即使index.css文件沒(méi)有變化,它的hash值也是會(huì)跟著變化的,導(dǎo)致緩存失效。

那么這時(shí)我們可以使用extra-text-webpack-plugin里的contenthash值,保證即使css文件所處的模塊里就算其他文件內(nèi)容改變,只要css文件內(nèi)容不變,它的hash值就不會(huì)變。

實(shí)現(xiàn)js緩存

webpack插件CommonsChunkPlugin的主要作用是抽取webpack項(xiàng)目入口chunk的公共部分,具體的用法就不做過(guò)多介紹,不太了解可以參考webpack官網(wǎng)介紹;

該插件是webpack項(xiàng)目常用的一個(gè)優(yōu)化功能,幾乎在每個(gè)webpack項(xiàng)目中都會(huì)用到。使用該插件帶來(lái)的好處:

  • 提升webpack打包速度和項(xiàng)目體積:將webpack入口的chunk文件中所有公共的代碼提取出來(lái),減少代碼體積;同時(shí)提升webpack打包速度。
  • 利用緩存機(jī)制:依賴的公共模塊文件一般很少更改或者不會(huì)更改,這樣獨(dú)立模塊文件提取出可以長(zhǎng)期緩存。

但是在項(xiàng)目中,若插件打開(kāi)方式不正確的話,上面的第二點(diǎn)其實(shí)是無(wú)法實(shí)現(xiàn),因?yàn)檫@種情況下:

沒(méi)有被修改過(guò)的公有代碼或庫(kù)代碼打包出的Entry Chunk,會(huì)隨著其他業(yè)務(wù)代碼的變化而變化,導(dǎo)致頁(yè)面上的長(zhǎng)緩存機(jī)制失效。

那么,下面就來(lái)開(kāi)啟CommonsChunkPlugin正確的打開(kāi)方式。

CommonsChunkPlugin不正確用法

假如將我們項(xiàng)目的公共庫(kù)如react、react-dom、react-router與業(yè)務(wù)代碼隔離,將其提取為vendor chunk,webpack配置如下:

const webpack = require("webpack");
const path = require('path');
module.exports = {
  entry: {
    app: "./src/main.js",
    vendor: ["react","react-dom", "redux", "react-redux", "react-router-redux"]
  },
  output: {
    path: path.resolve(__dirname, 'output'),
    filename: "[name].[chunkhash].js"
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({names: ["vendor"]})
  ]
};

上面將項(xiàng)目一些基礎(chǔ)庫(kù)打包成一個(gè)名為vendor的chunk中,并將業(yè)務(wù)相關(guān)的代碼打包到一個(gè)名為app的chunk中;

webpack打包編譯后的結(jié)果如下:

我們對(duì)其中的業(yè)務(wù)代碼app.js進(jìn)行修改后,重新編譯結(jié)果如下:

可以發(fā)現(xiàn),在CommonsChunkPlugin這種配置下,當(dāng)業(yè)務(wù)代碼app發(fā)生變化,而庫(kù)代碼也跟著變化,vender的chunkhash也跟著變化,這樣vendor的引用的名稱跟著變化,導(dǎo)致瀏覽器端的長(zhǎng)緩存機(jī)制失效。

引起問(wèn)題的原因

引起webpack每次打包編譯時(shí)vendor跟著變化的原因:

webpack每次build的時(shí)候都會(huì)生成一些運(yùn)行時(shí)代碼。當(dāng)只有一個(gè)文件時(shí),運(yùn)行時(shí)代碼直接塞到這個(gè)文件中。當(dāng)有多個(gè)文件時(shí),運(yùn)行時(shí)代碼會(huì)被提取到公共文件中,也就是上面CommonsChunkPlugin配置的vendor chunk中。

webpack每次編譯時(shí)產(chǎn)生的運(yùn)行時(shí)代碼,包括全局webpackJsonp方法的定義和維護(hù)模塊依賴關(guān)系,具體可以參考這里>>

所以,上面webpack的CommonsChunkPlugin配置中,每次編譯時(shí)這些代碼都會(huì)打包到vendor中,導(dǎo)致每次vendor的chunkhash每次都會(huì)變化。

那么,我們可以在對(duì)vendor chunk進(jìn)行配置,抽取其中的公共代碼,即webpack運(yùn)行時(shí)代碼,這樣就可以將項(xiàng)目依賴的基礎(chǔ)庫(kù)模塊與業(yè)務(wù)模塊隔離開(kāi)來(lái),因?yàn)椴粫?huì)對(duì)這些文件進(jìn)行修改,所以這些文件可達(dá)到長(zhǎng)緩存的作用。具體配置如下:

module.exports = {
  entry: {
    app: "./app.js",
    vendor: ["react","react-dom", "redux", "react-redux", "react-router-redux"]
  },
  ....
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({names: ["vendor"]}),
    new webpack.optimize.CommonsChunkPlugin({
        name: 'manifest',
        chunks: ['vendor']
    })
  ]
};

這樣,即使修改業(yè)務(wù)app代碼,項(xiàng)目依賴的基礎(chǔ)庫(kù)vendor chunk也不會(huì)發(fā)生變化;只是抽取的manifest chunk每次還會(huì)變化,但是這個(gè)文件體積非常小,相比vendor來(lái)說(shuō)這種方式的收益更大。如下圖:

修改app代碼后的打包編譯結(jié)果如下,可以看到vendor的chunkhash沒(méi)有變化

在webpack中配置CommonsChunkPlugin時(shí)需要注意幾點(diǎn):

1、 配置webpack的output項(xiàng)時(shí),其filenamechunkFilename必須使用chunkhash。不要使用hash,否則即使按照上面的配置也不能達(dá)到預(yù)期的效果。至于hash與chunkhash的區(qū)別,可參考github的回答

2、對(duì)于圖片、字體等靜態(tài)資源抽離使用的file-loader,其配置的hash表示的是靜態(tài)文件的內(nèi)容hash值,不是webpack每次打包編譯生成的hash值, 切記?。?!

3、對(duì)于抽取的css樣式文件,需要使用contenthash, 與file-loader中的hash意義相同。此處不能為chunkhash,否則其與抽取該樣式文件的entry chunk的chunkhash保持一致,打不到緩存的目的。

實(shí)現(xiàn)css的緩存

webpack實(shí)現(xiàn)css的緩存,就是使用上面介紹過(guò)的contenthash,該hash屬性值其實(shí)是extra-text-webpack-plugin計(jì)算的。具體實(shí)現(xiàn)css的緩存,其實(shí)就像下面一樣使用contenthash即可

module.exports = {
  ...
  plugins: [
     new ExtractTextPlugin({
	filename: 'static/[name]_[contenthash:7].css',
	disable: false,
	allChunks: true
     })
  ...
  ]

實(shí)現(xiàn)圖片/字體的緩存

對(duì)于圖片、字體等靜態(tài)資源,在使用webpack構(gòu)建提取時(shí),其實(shí)是使用了file-loader來(lái)完成的,生成對(duì)應(yīng)的文件hash值也就是由對(duì)應(yīng)的file-loader來(lái)計(jì)算的。那么這些靜態(tài)文件的hash值使用的是什么hash值呢,其實(shí)就是hash屬性值。如下面代碼所示:

module.exports = {
 ...
 rules: [
   ...
    {
      test: /\.(gif|png|jpe?g)(\?\S*)?$/,
      loader: require.resolve('url-loader'),
      options: {
        limit: 10000,
        name: path.posix.join('static',  '[name]_[hash:7].[ext]')
      }
    },
    font: {
      test: /\.otf|ttf|woff2?|eot(\?\S*)?$/,
      loader: require.resolve('url-loader'),
      options: {
        limit: 10000,
        name: path.posix.join('static', '[name]_[hash:7].[ext]')
      }
    }
 ]
}

可以看到上面使用的是hash屬性值,此hash非webpack每次項(xiàng)目構(gòu)建的hash,它是由file-loader根據(jù)文件內(nèi)容計(jì)算出來(lái)的,不要誤認(rèn)為是webpack構(gòu)建的hash。

參考

1、webpack之CommonsChunkPlugin正確打開(kāi)方式
2、webpack 填坑之路--提取獨(dú)立文件(模塊)
3、webpack代碼分割技巧
4、聽(tīng)說(shuō)你用webpack處理文件名的hash?那么建議你看看你生成的hash對(duì)不對(duì)
5、chunkhash
6、multiple-commons-chunks
7、用 webpack 實(shí)現(xiàn)持久化緩存
8、Webpack中hash與chunkhash的區(qū)別,以及js與css的hash指紋解耦方案

到此這篇關(guān)于webpack實(shí)現(xiàn)靜態(tài)資源緩存的方法的文章就介紹到這了,更多相關(guān)webpack 靜態(tài)資源緩存內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 擴(kuò)展String功能方法

    擴(kuò)展String功能方法

    擴(kuò)展String功能方法...
    2006-09-09
  • JavaScript模板字符串用法實(shí)例

    JavaScript模板字符串用法實(shí)例

    在ES6之前我們都使用單引號(hào)或者雙引號(hào)來(lái)包裹字符串,當(dāng)我們想要在字符串中加入變量時(shí),不能直接寫在字符串里,而是需要通過(guò)字符串拼接的方式來(lái)往字符串中加入變量,這篇文章主要給大家介紹了關(guān)于JavaScript模板字符串用法的相關(guān)資料,需要的朋友可以參考下
    2022-11-11
  • JS實(shí)現(xiàn)仿蘋果底部任務(wù)欄菜單效果代碼

    JS實(shí)現(xiàn)仿蘋果底部任務(wù)欄菜單效果代碼

    這篇文章主要介紹了JS實(shí)現(xiàn)仿蘋果底部任務(wù)欄菜單效果代碼,可實(shí)現(xiàn)鼠標(biāo)滑過(guò)顯示大圖標(biāo)功能,涉及javascript鼠標(biāo)事件及頁(yè)面元素遍歷并修改屬性的技巧,需要的朋友可以參考下
    2015-08-08
  • js 右側(cè)浮動(dòng)層效果實(shí)現(xiàn)代碼(跟隨滾動(dòng))

    js 右側(cè)浮動(dòng)層效果實(shí)現(xiàn)代碼(跟隨滾動(dòng))

    因?yàn)轫?xiàng)目上有這樣的需求,在網(wǎng)上也查了些東西,之前是想找個(gè)差不多類似的套用一下。后來(lái)發(fā)覺(jué)沒(méi)有合適的,因時(shí)間緊迫就自己動(dòng)手寫了一個(gè)簡(jiǎn)單的 ,示例代碼如下 兼容火狐和IE7+
    2015-11-11
  • js文件中調(diào)用js的實(shí)現(xiàn)方法小結(jié)

    js文件中調(diào)用js的實(shí)現(xiàn)方法小結(jié)

    JavaScript文件引用JavaScript文件的方法,需要的朋友可以參考下。
    2009-10-10
  • 重載toString實(shí)現(xiàn)JS HashMap分析

    重載toString實(shí)現(xiàn)JS HashMap分析

    用過(guò)Java的都知道,里面有個(gè)功能強(qiáng)大的數(shù)據(jù)結(jié)構(gòu)——HashMap,它能提供鍵與值的對(duì)應(yīng)訪問(wèn)。不過(guò)熟悉JS的朋友也會(huì)說(shuō),JS里面到處都是hashmap,因?yàn)槊總€(gè)對(duì)象都提供了map[key]的訪問(wèn)形式。
    2011-03-03
  • 利用Print.js實(shí)現(xiàn)打印pdf、HTML及圖片(可設(shè)置樣式可分頁(yè))

    利用Print.js實(shí)現(xiàn)打印pdf、HTML及圖片(可設(shè)置樣式可分頁(yè))

    在我們需要在頁(yè)面中打印某個(gè)區(qū)域的內(nèi)容或者生成pdf的時(shí)候,我們可以直接用printJs庫(kù),這篇文章主要給大家介紹了關(guān)于利用Print.js實(shí)現(xiàn)打印pdf、HTML及圖片的相關(guān)資料,可設(shè)置樣式可分頁(yè),需要的朋友可以參考下
    2024-05-05
  • JS實(shí)現(xiàn)清除指定cookies的方法

    JS實(shí)現(xiàn)清除指定cookies的方法

    這篇文章主要介紹了JS實(shí)現(xiàn)清除指定cookies的方法,在web程序設(shè)計(jì)中非常實(shí)用,需要的朋友可以參考下
    2014-09-09
  • layui導(dǎo)出Excel表格的方法代碼舉例

    layui導(dǎo)出Excel表格的方法代碼舉例

    使用了layui自帶的導(dǎo)出功能后,真的是超級(jí)便捷,下面這篇文章主要給大家介紹了關(guān)于layui導(dǎo)出Excel表格的方法代碼,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-11-11
  • JavaScript編寫Chrome擴(kuò)展實(shí)現(xiàn)與瀏覽器的交互及時(shí)間通知

    JavaScript編寫Chrome擴(kuò)展實(shí)現(xiàn)與瀏覽器的交互及時(shí)間通知

    得益于API,我們可以用JavaScript編寫Chrome擴(kuò)展實(shí)現(xiàn)與瀏覽器的交互及時(shí)間通知。值得一提的是現(xiàn)在Chrome擁有后臺(tái)進(jìn)程可以使通知在前臺(tái)瀏覽器關(guān)閉的情況下依然能夠生效.
    2016-05-05

最新評(píng)論