webpack5文檔解析(下)

聲明:所有的文章demo都在我的倉庫

代碼分離

代碼分離的有點在於:

  1. 切割代碼,生成不同的打包文件,按需加載這些文件。
  2. 每個bundle的體積更小
  3. 控制外部資源的加載順序

常用的方法有:

  1. 入口起點:使用入口entry手動分離
  2. 防止重複:使用SplitChunksPlugin去重和分離chunk
  3. 動態導入:通過模塊的內聯函數調用分離的代碼

入口起點

新增另一個文件another-module.js文件,並在webpack.config.js中進行配置。

entry:{//打包入口
    index:'./src/index.js',
    another:'./src/another-module.js'
},

進行打包後,結果正常。

優點:常用常規的寫法。

缺點:1.如果有相同的模塊,不會去重,還是會在每個bundle中被重複的引用。2.不能將核心代碼進行分割

防止重複

入口依賴

配置dependOn選項,可以在多個chunk之間進行共享模塊。

SplitChunkPlugin

爲了解決多個bundle引入相同模塊的問題,引入這個模塊進行去重。

SplitChunkPlugin將公共的模塊引入到已有的入口中,或者提取到新的chunk。

相關配置如下:

//webpack.config.js
optimization:{
    splitChunks:{
        chunks:'all'
    }
},

SplitChunkPlugin創建了新的chunk,如下圖所示,shared.bundle.js。將我其他頁面所使用的js引入的lodash模塊引入這個文件中。

*** 以上代碼在webpack-demo5

緩存

通常部署文件是將webpack打包出來的/dist文件,部署到server上,客戶端通過訪問server的網站及資源。

由於客戶端訪問server時,非常耗時和耗流量,於是瀏覽器採用緩存技術,可以直接從緩存中獲取相關的內容,降低了請求的速度和流量。但是這也有一個缺點:如果文件名跟之前的一致,瀏覽器會認爲這個文件沒有做修改,還是會從緩存中獲取相關內容。

我們想要的現象是:文件沒做修改時,瀏覽器從緩存中獲取,文件修改了,重新獲取。

輸出文件的文件名

webpack提供了一個substitution(可替換的模版字符串)的方式,通過帶括號字符串來模版化文件名。其中的[contenthash]是根據資源內容創建唯一的hash。當資源內容變化時,[contenthash]也會發生變化。

相關配置如下:

entry:'./src/index.js',
output:{//打包出口
    filename:"[name].[contenthash].js",//打包後的文件名稱
    path:path.resolve(__dirname,'dist')//路徑
}, 

使用contenthash,將內容變化直接反應打包輸出文件的變化。

文件不做修改,再次運行npm run build時,文檔描述如下:

在我的實際操作中,我的打包文件是不變的。

第一次:

第二次:

可能跟webpack版本的關係所致。。。

模塊的概念

runtime:每個模塊的加載和模塊的解析邏輯。

manifest:解析和映射模塊之間的聯繫

提取引導模版

runtime代碼,提取到一個單獨的chunk中。optimization.runtimeChunk:'single'表示爲所有的chunk創建一個runtime bundle

代碼如下:

optimization:{
    runtimeChunk:'single'
},

將所有的第三方庫,如lodash/react等提取到單獨的vendor chunk文件中。由於這些第三方庫不會去頻繁的修改源代碼,所以可以讓更少的向server發請求。

配置如下:

const path=require('path');
const {CleanWebpackPlugin}=require('clean-webpack-plugin')
const HtmlWebpackPlugin=require('html-webpack-plugin')

module.exports={
    mode:'development',
    entry:'./src/index.js',
    output:{//打包出口
        filename:"[name].[contenthash].js",//打包後的文件名稱
        path:path.resolve(__dirname,'dist')//路徑
    }, 
    devtool: 'inline-source-map',
    devServer:{
        contentBase:'./dist'
    },
    optimization:{
        runtimeChunk:'single',
        splitChunks:{
            cacheGroups:{
                vendor:{
                    test:/[\\/]node_modules[\\/]/,
                    name:'vendor',
                    chunks:'all'
                }
            }
        }
    },
    plugins:[
        new CleanWebpackPlugin({
            cleanStaleWebpackAssets:false
        }),
        new HtmlWebpackPlugin({
            title:'管理輸出'
        })
    ]
}

結果會出現一個帶有vendor的文件。

main文件裏,不再含有來自node_modulevendor代碼,而且體積也減少了。

模塊標識符

新增print模塊,並在index中進行引入,最終打包的結果跟之前比較結果如下:

我本地打包只有main的文件進行了變化----符合預期

然而官網上展示的例子是不一樣,引出了需要引入optimization.moduleIds:'hashed'---苦笑不得

*** 以上代碼在webpack-demo6

環境變量

可以在package.json中配置相關的命令行,可以快速的執行開發環境生產環境

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "start": "webpack serve --env development"
},

表示執行development環境。

模塊熱替換(HMR)

模塊熱替換(HMR--hot module replacement):在程序運行過程中,若有替換/添加/刪除模塊,只更新修改的部分,不需要更新整個頁面。

此功能暫不支持生產環境。

代碼配置如下:

devServer:{
    contentBase:'./dist',
    hot:true
},

在index頁面加入代碼

if(module.hot){
  module.hot.accept('./print.js',function(){
    console.log('update the module1');
    Print()
  })
}

注意:執行時使用npm run start,啓動服務,可查看熱更替。

*** 以上代碼在webpack-demo7

模塊熱更替跟熱更新是兩回事。模塊熱更新是指修改了某個部分代碼,不會刷新頁面,而是在頁面更新這個模塊。熱更新是指及時刷新頁面。

Tree shaking

概念

是指在打包的時候,剔除沒有用到的代碼。

但是隻支持ES module的import和export用法。

實踐

打包過程分成3部分:

  1. import會被打包成/* harmony import */做前綴,表明這段是import進來的
  2. export會被打包成/* harmony export */做前綴,表明這段是export
  3. 純函數,會被打包成/*#__PURE__*/,表明這個函數是純函數,可以被tree shaking

代碼如下:

package.json

"name": "webpack-demo8",
"sideEffects":false,

webpack.config.js

optimization:{
    usedExports:true
}

*** 以上代碼在webpack-demo8

我的倉庫地址,github,歡迎star~~

(完)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章