<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專(zhuān)題視頻專(zhuān)題問(wèn)答1問(wèn)答10問(wèn)答100問(wèn)答1000問(wèn)答2000關(guān)鍵字專(zhuān)題1關(guān)鍵字專(zhuān)題50關(guān)鍵字專(zhuān)題500關(guān)鍵字專(zhuān)題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專(zhuān)題關(guān)鍵字專(zhuān)題tag2tag3文章專(zhuān)題文章專(zhuān)題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專(zhuān)題3
        問(wèn)答文章1 問(wèn)答文章501 問(wèn)答文章1001 問(wèn)答文章1501 問(wèn)答文章2001 問(wèn)答文章2501 問(wèn)答文章3001 問(wèn)答文章3501 問(wèn)答文章4001 問(wèn)答文章4501 問(wèn)答文章5001 問(wèn)答文章5501 問(wèn)答文章6001 問(wèn)答文章6501 問(wèn)答文章7001 問(wèn)答文章7501 問(wèn)答文章8001 問(wèn)答文章8501 問(wèn)答文章9001 問(wèn)答文章9501
        當(dāng)前位置: 首頁(yè) - 科技 - 知識(shí)百科 - 正文

        Webpack怎樣操作緩存

        來(lái)源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 19:37:13
        文檔

        Webpack怎樣操作緩存

        Webpack怎樣操作緩存:這次給大家?guī)?lái)Webpack怎樣操作緩存,Webpack操作緩存的注意事項(xiàng)有哪些,下面就是實(shí)戰(zhàn)案例,一起來(lái)看一下。前言最近在看 webpack 如何做持久化緩存的內(nèi)容,發(fā)現(xiàn)其中還是有一些坑點(diǎn)的,正好有時(shí)間就將它們整理總結(jié)一下,讀完本文你大致能夠明白:什么是持久化
        推薦度:
        導(dǎo)讀Webpack怎樣操作緩存:這次給大家?guī)?lái)Webpack怎樣操作緩存,Webpack操作緩存的注意事項(xiàng)有哪些,下面就是實(shí)戰(zhàn)案例,一起來(lái)看一下。前言最近在看 webpack 如何做持久化緩存的內(nèi)容,發(fā)現(xiàn)其中還是有一些坑點(diǎn)的,正好有時(shí)間就將它們整理總結(jié)一下,讀完本文你大致能夠明白:什么是持久化

        這次給大家?guī)?lái)Webpack怎樣操作緩存,Webpack操作緩存的注意事項(xiàng)有哪些,下面就是實(shí)戰(zhàn)案例,一起來(lái)看一下。

        前言

        最近在看 webpack 如何做持久化緩存的內(nèi)容,發(fā)現(xiàn)其中還是有一些坑點(diǎn)的,正好有時(shí)間就將它們整理總結(jié)一下,讀完本文你大致能夠明白:

        1. 什么是持久化緩存,為什么做持久化緩存?

        2. webpack 如何做持久化緩存?

        3. webpack 做緩存的一些注意點(diǎn)。

        持久化緩存

        首先我們需要去解釋一下,什么是持久化緩存,在現(xiàn)在前后端分離的應(yīng)用大行其道的背景下,前端 html,css,js 往往是以一種靜態(tài)資源文件的形式存在于服務(wù)器,通過(guò)接口來(lái)獲取數(shù)據(jù)來(lái)展示動(dòng)態(tài)內(nèi)容。這就涉及到公司如何去部署前端代碼的問(wèn)題,所以就涉及到一個(gè)更新部署的問(wèn)題,是先部署頁(yè)面,還是先部署資源?

        先部署頁(yè)面,再部署資源:在二者部署的時(shí)間間隔內(nèi),如果有用戶(hù)訪問(wèn)頁(yè)面,就會(huì)在新的頁(yè)面結(jié)構(gòu)中加載舊的資源,并且把這個(gè)舊版本資源當(dāng)做新版本緩存起來(lái),其結(jié)果就是:用戶(hù)訪問(wèn)到一個(gè)樣式錯(cuò)亂的頁(yè)面,除非手動(dòng)去刷新,否則在資源緩存過(guò)期之前,頁(yè)面會(huì)一直處于錯(cuò)亂的狀態(tài)。

        先部署資源,再部署頁(yè)面:在部署時(shí)間間隔內(nèi),有舊版本的資源本地緩存的用戶(hù)訪問(wèn)網(wǎng)站,由于請(qǐng)求的頁(yè)面是舊版本,資源引用沒(méi)有改變,瀏覽器將直接使用本地緩存,這樣屬于正常情況,但沒(méi)有本地緩存或者緩存過(guò)期的用戶(hù)在訪問(wèn)網(wǎng)站的時(shí)候,就會(huì)出現(xiàn)舊版本頁(yè)面加載新版本資源的情況,導(dǎo)致頁(yè)面執(zhí)行錯(cuò)誤。

        所以我們需要一種部署策略來(lái)保證在更新我們線上的代碼的時(shí)候,線上用戶(hù)也能平滑地過(guò)渡并且正確打開(kāi)我們的網(wǎng)站。

        推薦先看這個(gè)回答:大公司里怎樣開(kāi)發(fā)和部署前端代碼?

        當(dāng)你讀完上面的回答,大致就會(huì)明白,現(xiàn)在比較成熟的持久化緩存方案就是在靜態(tài)資源的名字后面加 hash 值,因?yàn)槊看涡薷奈募傻?hash 值不一樣,這樣做的好處在于增量式發(fā)布文件,避免覆蓋掉之前文件從而導(dǎo)致線上的用戶(hù)訪問(wèn)失效。

        因?yàn)橹灰龅矫看伟l(fā)布的靜態(tài)資源(css, js, img)的名稱(chēng)都是獨(dú)一無(wú)二的,那么我就可以:

        1. 針對(duì) html 文件:不開(kāi)啟緩存,把 html 放到自己的服務(wù)器上,關(guān)閉服務(wù)器的緩存,自己的服務(wù)器只提供 html 文件和數(shù)據(jù)接口

        2. 針對(duì)靜態(tài)的 js,css,圖片等文件:開(kāi)啟 cdn 和緩存,將靜態(tài)資源上傳到 cdn 服務(wù)商,我們可以對(duì)資源開(kāi)啟長(zhǎng)期緩存,因?yàn)槊總€(gè)資源的路徑都是獨(dú)一無(wú)二的,所以不會(huì)導(dǎo)致資源被覆蓋,保證線上用戶(hù)訪問(wèn)的穩(wěn)定性。

        3. 每次發(fā)布更新的時(shí)候,先將靜態(tài)資源(js, css, img) 傳到 cdn 服務(wù)上,然后再上傳 html 文件,這樣既保證了老用戶(hù)能否正常訪問(wèn),又能讓新用戶(hù)看到新的頁(yè)面。

        上面大致介紹了下主流的前端持久化緩存方案,那么我們?yōu)槭裁葱枰龀志没彺婺兀?/p>

        用戶(hù)使用瀏覽器第一次訪問(wèn)我們的站點(diǎn)時(shí),該頁(yè)面引入了各式各樣的靜態(tài)資源,如果我們能做到持久化緩存的話,可以在 http 響應(yīng)頭加上 Cache-control 或 Expires 字段來(lái)設(shè)置緩存,瀏覽器可以將這些資源一一緩存到本地。

        用戶(hù)在后續(xù)訪問(wèn)的時(shí)候,如果需要再次請(qǐng)求同樣的靜態(tài)資源,且靜態(tài)資源沒(méi)有過(guò)期,那么瀏覽器可以直接走本地緩存而不用再通過(guò)網(wǎng)絡(luò)請(qǐng)求資源。

        webpack 如何做持久化緩存

        上面簡(jiǎn)單介紹完持久化緩存,下面這個(gè)才是重點(diǎn),那么我們應(yīng)該如何在 webpack 中進(jìn)行持久化緩存的呢,我們需要做到以下兩點(diǎn):

        1. 保證 hash 值的唯一性,即為每個(gè)打包后的資源生成一個(gè)獨(dú)一無(wú)二的 hash 值,只要打包內(nèi)容不一致,那么 hash 值就不一致。

        2. 保證 hash 值的穩(wěn)定性,我們需要做到修改某個(gè)模塊的時(shí)候,只有受影響的打包后文件 hash 值改變,與該模塊無(wú)關(guān)的打包文件 hash 值不變。

        hash 文件名是實(shí)現(xiàn)持久化緩存的第一步,目前 webpack 有兩種計(jì)算 hash 的方式([hash] 和 [chunkhash])

        1. hash 代表每次 webpack 在編譯的過(guò)程中會(huì)生成唯一的 hash 值,在項(xiàng)目中任何一個(gè)文件改動(dòng)后就會(huì)被重新創(chuàng)建,然后 webpack 計(jì)算新的 hash 值。

        2. chunkhash 是根據(jù)模塊計(jì)算出來(lái)的 hash 值,所以某個(gè)文件的改動(dòng)只會(huì)影響它本身的 hash 值,不會(huì)影響其他文件。

        所以如果你只是單純地將所有內(nèi)容打包成同一個(gè)文件,那么 hash 就能夠滿(mǎn)足你了,如果你的項(xiàng)目涉及到拆包,分模塊進(jìn)行加載等等,那么你需要用 chunkhash,來(lái)保證每次更新之后只有相關(guān)的文件 hash 值發(fā)生改變。

        所以我們?cè)谝环菥哂谐志没彺娴?webpack 配置應(yīng)該長(zhǎng)這樣:

        module.exports = {
         entry: __dirname + '/src/index.js',
         output: {
         path: __dirname + '/dist',
         filename: '[name].[chunkhash:8].js',
         }
        }

        上面代碼的含義就是:以 index.js 為入口,將所有的代碼全部打包成一個(gè)文件取名為 index.xxxx.js 并放到 dist 目錄下,現(xiàn)在我們可以在每次更新項(xiàng)目的時(shí)候做到生成新命名的文件了。

        如果是應(yīng)付簡(jiǎn)單的場(chǎng)景,這樣做就夠了,但是在大型多頁(yè)面應(yīng)用中,我們往往需要對(duì)頁(yè)面進(jìn)行性能優(yōu)化:

        1. 分離業(yè)務(wù)代碼和第三方的代碼:之所以將業(yè)務(wù)代碼和第三方代碼分離出來(lái),是因?yàn)闃I(yè)務(wù)代碼更新頻率高,而第三方代碼更新迭代速度慢,所以我們將第三方代碼(庫(kù),框架)進(jìn)行抽離,這樣可以充分利用瀏覽器的緩存來(lái)加載第三方庫(kù)。

        2. 按需加載:比如在使用 React-Router 的時(shí)候,當(dāng)用戶(hù)需要訪問(wèn)到某個(gè)路由的時(shí)候再去加載對(duì)應(yīng)的組件,那么用戶(hù)沒(méi)有必要在一開(kāi)始的時(shí)候就將所有的路由組件下載到本地。

        3. 在多頁(yè)面應(yīng)用中,我們往往可以將公共模塊進(jìn)行抽離,比如 header, footer 等等,這樣頁(yè)面在進(jìn)行跳轉(zhuǎn)的時(shí)候這些公共模塊因?yàn)榇嬖谟诰彺胬铮涂梢灾苯舆M(jìn)行加載了,而不是再進(jìn)行網(wǎng)絡(luò)請(qǐng)求了。

        那么如何進(jìn)行拆包,分模塊進(jìn)行加載,這就需要 webpack 內(nèi)置插件:CommonsChunkPlugin,下面我將通過(guò)一個(gè)例子,來(lái)詮釋 webpack 該如何進(jìn)行配置。

        本文的代碼放在我的 Github 上,有興趣的可以下載來(lái)看看:

        git clone https://github.com/happylindz/blog.git
        cd blog/code/multiple-page-webpack-demo
        npm install

        閱讀下面的內(nèi)容之前我強(qiáng)烈建議你看下我之前的文章:深入理解 webpack 文件打包機(jī)制,理解 webpack 文件的打包的機(jī)制有助于你更好地實(shí)現(xiàn)持久化緩存。

        例子大概是這樣描述的:它由兩個(gè)頁(yè)面組成 pageA 和 pageB

        // src/pageA.js
        import componentA from './common/componentA';
        // 使用到 jquery 第三方庫(kù),需要抽離,避免業(yè)務(wù)打包文件過(guò)大
        import $ from 'jquery';
        // 加載 css 文件,一部分為公共樣式,一部分為獨(dú)有樣式,需要抽離
        import './css/common.css'
        import './css/pageA.css';
        console.log(componentA);
        console.log($.trim(' do something '));
        // src/pageB.js
        // 頁(yè)面 A 和 B 都用到了公共模塊 componentA,需要抽離,避免重復(fù)加載
        import componentA from './common/componentA';
        import componentB from './common/componentB';
        import './css/common.css'
        import './css/pageB.css';
        console.log(componentA);
        console.log(componentB);
        // 用到異步加載模塊 asyncComponent,需要抽離,加載首屏速度
        document.getElementById('xxxxx').addEventListener('click', () => {
         import( /* webpackChunkName: "async" */
         './common/asyncComponent.js').then((async) => {
         async();
         })
        })
        // 公共模塊基本長(zhǎng)這樣
        export default "component X";

        上面的頁(yè)面內(nèi)容基本簡(jiǎn)單涉及到了我們拆分模塊的三種模式:拆分公共庫(kù),按需加載和拆分公共模塊。那么接下來(lái)要來(lái)配置 webpack:

        const path = require('path');
        const webpack = require('webpack');
        const ExtractTextPlugin = require('extract-text-webpack-plugin');
        module.exports = {
         entry: {
         pageA: [path.resolve(__dirname, './src/pageA.js')],
         pageB: path.resolve(__dirname, './src/pageB.js'),
         },
         output: {
         path: path.resolve(__dirname, './dist'),
         filename: 'js/[name].[chunkhash:8].js',
         chunkFilename: 'js/[name].[chunkhash:8].js'
         },
         module: {
         rules: [
         {
         // 用正則去匹配要用該 loader 轉(zhuǎn)換的 CSS 文件
         test: /.css$/,
         use: ExtractTextPlugin.extract({
         fallback: "style-loader",
         use: ["css-loader"]
         }) 
         }
         ]
         },
         plugins: [
         new webpack.optimize.CommonsChunkPlugin({
         name: 'common',
         minChunks: 2,
         }),
         new webpack.optimize.CommonsChunkPlugin({
         name: 'vendor',
         minChunks: ({ resource }) => (
         resource && resource.indexOf('node_modules') >= 0 && resource.match(/.js$/)
         )
         }),
         new ExtractTextPlugin({
         filename: `css/[name].[chunkhash:8].css`,
         }),
         ]
        }

        第一個(gè) CommonsChunkPlugin 用于抽離公共模塊,相當(dāng)于是說(shuō) webpack 大佬,如果你看到某個(gè)模塊被加載兩次即以上,那么請(qǐng)你幫我移到 common chunk 里面,這里 minChunks 為 2,粒度拆解最細(xì),你可以根據(jù)自己的實(shí)際情況,看選擇是用多少次模塊才將它們抽離。

        第二個(gè) CommonsChunkPlugin 用來(lái)提取第三方代碼,將它們進(jìn)行抽離,判斷資源是否來(lái)自 node_modules,如果是,則說(shuō)明是第三方模塊,那就將它們抽離。相當(dāng)于是告訴 webpack 大佬,如果你看見(jiàn)某些模塊是來(lái)自 node_modules 目錄的,并且名字是 .js 結(jié)尾的話,麻煩把他們都移到 vendor chunk 里去,如果 vendor chunk 不存在的話,就創(chuàng)建一個(gè)新的。

        這樣配置有什么好處,隨著業(yè)務(wù)的增長(zhǎng),我們依賴(lài)的第三方庫(kù)代碼很可能會(huì)越來(lái)越多,如果我們專(zhuān)門(mén)配置一個(gè)入口來(lái)存放第三方代碼,這時(shí)候我們的 webpack.config.js 就會(huì)變成:

        // 不利于拓展
        module.exports = {
         entry: {
         app: './src/main.js',
         vendor: [
         'vue',
         'axio',
         'vue-router',
         'vuex',
         // more
         ],
         },
        }

        第三個(gè) ExtractTextPlugin 插件用于將 css 從打包好的 js 文件中抽離,生成獨(dú)立的 css 文件,想象一下,當(dāng)你只是修改了下樣式,并沒(méi)有修改頁(yè)面的功能邏輯,你肯定不希望你的 js 文件 hash 值變化,你肯定是希望 css 和 js 能夠相互分開(kāi),且互不影響。

        運(yùn)行 webpack 后可以看到打包之后的效果:

        ├── css
        │ ├── common.2beb7387.css
        │ ├── pageA.d178426d.css
        │ └── pageB.33931188.css
        └── js
         ├── async.03f28faf.js
         ├── common.2beb7387.js
         ├── pageA.d178426d.js
         ├── pageB.33931188.js
         └── vendor.22a1d956.js

        可以看出 css 和 js 已經(jīng)分離,并且我們對(duì)模塊進(jìn)行了拆分,保證了模塊 chunk 的唯一性,當(dāng)你每次更新代碼的時(shí)候,會(huì)生成不一樣的 hash 值。

        唯一性有了,那么我們需要保證 hash 值的穩(wěn)定性,試想下這樣的場(chǎng)景,你肯定不希望你修改某部分的代碼(模塊,css)導(dǎo)致了文件的 hash 值全變了,那么顯然是不明智的,那么我們?nèi)プ龅?hash 值變化最小化呢?

        換句話說(shuō),我們就要找出 webpack 編譯中會(huì)導(dǎo)致緩存失效的因素,想辦法去解決或優(yōu)化它?

        影響 chunkhash 值變化主要由以下四個(gè)部分引起的:

        1. 包含模塊的源代碼

        2. webpack 用于啟動(dòng)運(yùn)行的 runtime 代碼

        3. webpack 生成的模塊 moduleid(包括包含模塊 id 和被引用的依賴(lài)模塊 id)

        4. chunkID

        這四部分只要有任意部分發(fā)生變化,生成的分塊文件就不一樣了,緩存也就會(huì)失效,下面就從四個(gè)部分一一介紹:

        一、源代碼變化:

        顯然不用多說(shuō),緩存必須要刷新,不然就有問(wèn)題了

        二、webpack 啟動(dòng)運(yùn)行的 runtime 代碼:

        看過(guò)我之前的文章:深入理解 webpack 文件打包機(jī)制 就會(huì)知道,在 webpack 啟動(dòng)的時(shí)候需要執(zhí)行一些啟動(dòng)代碼。

        (function(modules) {
         window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules) {
         // ...
         };
         function __webpack_require__(moduleId) {
         // ...
         }
         __webpack_require__.e = function requireEnsure(chunkId, callback) {
         // ...
         script.src = __webpack_require__.p + "" + chunkId + "." + ({"0":"pageA","1":"pageB","3":"vendor"}[chunkId]||chunkId) + "." + {"0":"e72ce7d4","1":"69f6bbe3","2":"9adbbaa0","3":"53fa02a7"}[chunkId] + ".js";
         };
        })([]);

        大致內(nèi)容像上面這樣,它們是 webpack 的一些啟動(dòng)代碼,它們是一些函數(shù),告訴瀏覽器如何加載 webpack 定義的模塊。

        其中有一行代碼每次更新都會(huì)改變的,因?yàn)閱?dòng)代碼需要清楚地知道 chunkid 和 chunkhash 值得對(duì)應(yīng)關(guān)系,這樣在異步加載的時(shí)候才能正確地拼接出異步 js 文件的路徑。

        那么這部分代碼最終放在哪個(gè)文件呢?因?yàn)槲覀儎偛排渲玫臅r(shí)候最后生成的 common chunk 模塊,那么這部分運(yùn)行時(shí)代碼會(huì)被直接內(nèi)置在里面,這就導(dǎo)致了,我們每次更新我們業(yè)務(wù)代碼(pageA, pageB, 模塊)的時(shí)候, common chunkhash 會(huì)一直變化,但是這顯然不符合我們的設(shè)想,因?yàn)槲覀冎皇且?common chunk 用來(lái)存放公共模塊(這里指的是 componentA),那么我 componentA 都沒(méi)去修改,憑啥 chunkhash 需要變了。

        所以我們需要將這部分 runtime 代碼抽離成單獨(dú)文件。

        module.exports = {
         // ...
         plugins: [
         // ...
         // 放到其他的 CommonsChunkPlugin 后面
         new webpack.optimize.CommonsChunkPlugin({
         name: 'runtime',
         minChunks: Infinity,
         }),
         ]
        }

        這相當(dāng)于是告訴 webpack 幫我把運(yùn)行時(shí)代碼抽離,放到單獨(dú)的文件中。

        ├── css
        │ ├── common.4cc08e4d.css
        │ ├── pageA.d178426d.css
        │ └── pageB.33931188.css
        └── js
         ├── async.03f28faf.js
         ├── common.4cc08e4d.js
         ├── pageA.d178426d.js
         ├── pageB.33931188.js
         ├── runtime.8c79fdcd.js
         └── vendor.cef44292.js

        多生成了一個(gè) runtime.xxxx.js,以后你在改動(dòng)業(yè)務(wù)代碼的時(shí)候,common chunk 的 hash 值就不會(huì)變了,取而代之的是 runtime chunk hash 值會(huì)變,既然這部分代碼是動(dòng)態(tài)的,可以通過(guò) chunk-manifest-webpack-plugin 將他們 inline 到 html 中,減少一次網(wǎng)絡(luò)請(qǐng)求。

        三、webpack 生成的模塊 moduleid

        在 webpack2 中默認(rèn)加載 OccurrenceOrderPlugin 這個(gè)插件,OccurrenceOrderPlugin 插件會(huì)按引入次數(shù)最多的模塊進(jìn)行排序,引入次數(shù)的模塊的 moduleId 越小,但是這仍然是不穩(wěn)定的,隨著你代碼量的增加,雖然代碼引用次數(shù)的模塊 moduleId 越小,越不容易變化,但是難免還是不確定的。

        默認(rèn)情況下,模塊的 id 是這個(gè)模塊在模塊數(shù)組中的索引。OccurenceOrderPlugin 會(huì)將引用次數(shù)多的模塊放在前面,在每次編譯時(shí)模塊的順序都是一致的,如果你修改代碼時(shí)新增或刪除了一些模塊,這將可能會(huì)影響到所有模塊的 id。

        最佳實(shí)踐方案是通過(guò) HashedModuleIdsPlugin 這個(gè)插件,這個(gè)插件會(huì)根據(jù)模塊的相對(duì)路徑生成一個(gè)長(zhǎng)度只有四位的字符串作為模塊的 id,既隱藏了模塊的路徑信息,又減少了模塊 id 的長(zhǎng)度。

        這樣一來(lái),改變 moduleId 的方式就只有文件路徑的改變了,只要你的文件路徑值不變,生成四位的字符串就不變,hash 值也不變。增加或刪除業(yè)務(wù)代碼模塊不會(huì)對(duì) moduleid 產(chǎn)生任何影響。

        module.exports = {
         plugins: [
         new webpack.HashedModuleIdsPlugin(),
         // 放在最前面
         // ...
         ]
        }

        四、chunkID

        實(shí)際情況中分塊的個(gè)數(shù)的順序在多次編譯之間大多都是固定的, 不太容易發(fā)生變化。

        這里涉及的只是比較基礎(chǔ)的模塊拆分,還有一些其它情況沒(méi)有考慮到,比如異步加載組件中包含公共模塊,可以再次將公共模塊進(jìn)行抽離。形成異步公共 chunk 模塊。有想深入學(xué)習(xí)的可以看這篇文章:Webpack 大法之 Code Splitting

        webpack 做緩存的一些注意點(diǎn)

        1. CSS 文件 hash 值失效的問(wèn)題

        2. 不建議線上發(fā)布使用 DllPlugin 插件

        CSS 文件 hash 值失效的問(wèn)題:

        ExtractTextPlugin 有個(gè)比較嚴(yán)重的問(wèn)題,那就是它生成文件名所用的[chunkhash]是直接取自于引用該 css 代碼段的 js chunk ;換句話說(shuō),如果我只是修改 css 代碼段,而不動(dòng) js 代碼,那么最后生成出來(lái)的 css 文件名依然沒(méi)有變化。

        所以我們需要將 ExtractTextPlugin 中的 chunkhash 改為 contenthash,顧名思義,contenthash 代表的是文本文件內(nèi)容的 hash 值,也就是只有 style 文件的 hash 值。這樣編譯出來(lái)的 js 和 css 文件就有獨(dú)立的 hash 值了。

        module.exports = {
         plugins: [
         // ...
         new ExtractTextPlugin({
         filename: `css/[name].[contenthash:8].css`,
         }),
         ]
        }

        如果你使用的是 webpack2,webpack3,那么恭喜你,這樣就足夠了,js 文件和 css 文件修改都不會(huì)影響到相互的 hash 值。那如果你使用的是 webpack1,那么就會(huì)出現(xiàn)問(wèn)題。

        具體來(lái)講就是 webpack1 和 webpack 在計(jì)算 chunkhash 值得不同:

        webpack1 在涉及的時(shí)候并沒(méi)有考慮像 ExtractTextPlugin 會(huì)將模塊內(nèi)容抽離的問(wèn)題,所以它在計(jì)算 chunkhash 的時(shí)候是通過(guò)打包之前模塊內(nèi)容去計(jì)算的,也就是說(shuō)在計(jì)算的時(shí)候 css 內(nèi)容也包含在內(nèi),之后才將 css 內(nèi)容抽離成單獨(dú)的文件,

        那么就會(huì)出現(xiàn):如果只修改了 css 文件,未修改引用的 js 文件,那么編譯輸出的 js 文件的 hash 值也會(huì)改變。

        對(duì)此,webpack2 做了改進(jìn),它是基于打包后文件內(nèi)容來(lái)計(jì)算 hash 值的,所以是在 ExtractTextPlugin 抽離 css 代碼之后,所以就不存在上述這樣的問(wèn)題。如果不幸的你還在使用 webpack1,那么推薦你使用 md5-hash-webpack-plugin 插件來(lái)改變 webpack 計(jì)算 hash 的策略。

        不建議線上發(fā)布使用 DllPlugin 插件

        為什么這么說(shuō)呢?因?yàn)樽罱信笥褋?lái)問(wèn)我,他們 leader 不讓在線上用 DllPlugin 插件,來(lái)問(wèn)我為什么?

        DllPlugin 本身有幾個(gè)缺點(diǎn):

        1. 首先你需要額外多配置一份 webpack 配置,增加工作量。

        2. 其中一個(gè)頁(yè)面用到了一個(gè)體積很大的第三方依賴(lài)庫(kù)而其它頁(yè)面根本不需要用到,但若直接將它打包在 dll.js 里很不值得,每次頁(yè)面打開(kāi)都要去加載這段無(wú)用的代碼,無(wú)法使用到 webpack2 的 Code Splitting 功能。

        3. 第一次打開(kāi)的時(shí)候需要下載 dll 文件,因?yàn)槟惆押芏鄮?kù)全部打在一起了,導(dǎo)致 dll 文件很大,首次進(jìn)入頁(yè)面加載速度很慢。

        雖然你可以打包成 dll 文件,然后讓瀏覽器去讀取緩存,這樣下次就不用再去請(qǐng)求,比如你用 lodash 其中一個(gè)函數(shù),而你用dll會(huì)將整個(gè) lodash 文件打進(jìn)去,這就會(huì)導(dǎo)致你加載無(wú)用代碼過(guò)多,不利于首屏渲染時(shí)間。

        我認(rèn)為的正確的姿勢(shì)是:

        1. 像 React、Vue 這樣整體性偏強(qiáng)的庫(kù),可以生成 vendor 第三方庫(kù)來(lái)去做緩存,因?yàn)槟阋话慵夹g(shù)體系是固定的,一個(gè)站點(diǎn)里面基本上都會(huì)用到統(tǒng)一技術(shù)體系,所以生成 vendor 庫(kù)用于緩存。

        2. 像 antd、lodash 這種功能性組件庫(kù),可以通過(guò) tree shaking 來(lái)進(jìn)行消除,只保留有用的代碼,千萬(wàn)不要直接打到 vendor 第三方庫(kù)里,不然你將大量執(zhí)行無(wú)用的代碼。

        相信看了本文案例你已經(jīng)掌握了方法,更多精彩請(qǐng)關(guān)注Gxl網(wǎng)其它相關(guān)文章!

        推薦閱讀:

        JS數(shù)值類(lèi)型數(shù)組去重

        項(xiàng)目中如何使用better-scroll插件

        聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        Webpack怎樣操作緩存

        Webpack怎樣操作緩存:這次給大家?guī)?lái)Webpack怎樣操作緩存,Webpack操作緩存的注意事項(xiàng)有哪些,下面就是實(shí)戰(zhàn)案例,一起來(lái)看一下。前言最近在看 webpack 如何做持久化緩存的內(nèi)容,發(fā)現(xiàn)其中還是有一些坑點(diǎn)的,正好有時(shí)間就將它們整理總結(jié)一下,讀完本文你大致能夠明白:什么是持久化
        推薦度:
        標(biāo)簽: 使用 如何 緩存
        • 熱門(mén)焦點(diǎn)

        最新推薦

        猜你喜歡

        熱門(mén)推薦

        專(zhuān)題
        Top
        主站蜘蛛池模板: 亚洲一区在线免费观看| 久久亚洲精品中文字幕三区| 亚洲精品欧洲精品| 免费人成在线观看视频高潮| 亚洲熟女乱综合一区二区 | 美女的胸又黄又www网站免费| 大学生一级特黄的免费大片视频 | 亚洲AV无码专区在线播放中文| 毛片基地看看成人免费| 亚洲午夜久久久影院| 97国免费在线视频| 国产V亚洲V天堂A无码| 无码成A毛片免费| 亚洲伊人久久大香线蕉苏妲己| 免费看又黄又无码的网站| 亚洲精品视频在线观看免费| 美女视频黄是免费的网址| 亚洲色大网站WWW永久网站| 在线日韩av永久免费观看| 色费女人18女人毛片免费视频| 亚洲免费日韩无码系列| 青青青国产手机频在线免费观看| 在线免费观看亚洲| 国产一精品一AV一免费孕妇| 精品亚洲福利一区二区| 亚洲综合最新无码专区| 久久综合给合久久国产免费 | 亚洲美女高清一区二区三区| 免费无码作爱视频| 亚洲一级毛片在线播放| 国产精品久免费的黄网站 | 曰批全过程免费视频播放网站| 亚洲免费人成视频观看| 免费在线观看a级毛片| 青青操视频在线免费观看| 亚洲三级在线免费观看| 日韩免费视频一区| 免费看无码特级毛片| 99999久久久久久亚洲| 亚洲国产V高清在线观看| 性色午夜视频免费男人的天堂|