webpack4---模塊化打包工具(二)

接着上一篇文章繼續

一、關於Tree Shaking

問題的引出:創建一個js文件,文件中有兩個方法,但是在index.js中只引入一個方法

前面說過了npm run start 在執行時,會啓動服務器,並將打包好的dist目錄存在內存中,所以項目中看不到,要想看到dist文件就要用npx webpack,在打包後的結果中我麼看到:即使只用了一個方法,結果webpack將兩個方法都打包了,這樣使文件的大小大大增加了

所以這時候我們就會發現,這樣是沒有必要的,所謂tree shaking 就是樹的搖動,一個模塊相當於一棵樹,吧沒有用到的東西都搖晃掉了,注意的是tree shaking僅支持ES Moudle引入,不支持commonJS

接下來進行配置,首先在development開發模式下

//webpack.config.js

optimization:{
    usedExports:true
}

//package.json

"sideEffects":false,

如果你想讓一個css文件不遵循不使用就不引入的規則,那就修改配置項

//package.json

"sideEffects":[
    "*.css"
]

但如果development環境變成prodution下,就不用寫optimization了

二、關於development模式和production模式的區別

現在我們分別配置兩個在不同模式下的webpack.config.js文件,並且修改打包的命令,最後我們將兩個文件中相同的部分提取到一個共同的文件webpack.common.js,但是我們需要一個第三方的插件講這些配置文件進行合併

npm install webpack-merge -D

並在文件中引入,使用他

接下來,將這三個配置文件放在build文件夾下

需要修改一下package.json文件夾下的打包命令

"scripts": {
    "dev": "webpack-dev-server --config ./build/webpack.dev.js",
    "build": "webpack --config ./build/webpack.prod.js"
  },

但是,這樣修改完也不行,因爲我們發現打包的dist文件被打包到了build目錄下,因爲好多配置項我們沒有同步的變更,所以現在修改一下:因爲十一打包的配置文件爲基準來生成目錄的,因爲我們的webpack.common.js是在build目錄下,所以認爲生成的dist目錄也要放在配置文件同一級的build文件下,所以在網上以及纔是我們要的位置

output:{
		filename: '[name].js',
		path:path.resolve(__dirname,'../dist')
	}

三、SplitChunksPlugin (Webpack 和 Code Splitting)

將webpack 和code splitting進行了綁定,在webpack中直接加參數就可以,以前我們都需要自己去考慮哪一項是公用的代碼,然後進行分割,webpack他可以自己去識別,例如引入一個lodash第三方庫,這樣我們每次改變index.js中的內容,lodash.js就不用二次加載了

npm install lodash --save

 引入babel官網提供的動態引入的插件

npm install --save-dev @babel/plugin-syntax-dynamic-import

在.babelrc中進行配置

{
    "plugins": [["@babel/plugin-transform-runtime",{
        "corejs": 2,
        "helpers": true,
        "regenerator": true,
        "useESModules": false
    }]],
    "plugins": ["@babel/plugin-syntax-dynamic-import"]
} 

在index.js中分別舉一個同步載入模塊的例子,一個異步載入模塊的例子

//test.js中的內容
export default {
	name:'aaa'
}



//index.js文件中的代碼

//同步引入
import test from './test.js'
console.log(test.name);


//異步模塊引入
function getComponent(){
        //注意下邊的註釋,是自己規定了打包後文件的名字,例如這樣寫完後他就變成vendors~lodash.js
	return import(/* webpackChunkName:"lodash" */ 'lodash').then( ({ default: _ } ) => {
		var element = document.createElement('div');
		element.innerHTML = _.join(['l','y','y'], '-');
		return element;
	})
} 
getComponent().then(element => {
	document.body.appendChild(element);
})

接下來我們來一一解釋一下webpack官網上的所有參數(webpack.common.js)

optimization:{
		splitChunks: {
	        chunks: 'all',
	        minSize: 0,
	        maxSize: 0,
	        minChunks: 1,
	        maxAsyncRequests: 5,
	        maxInitialRequests: 3,
	        automaticNameDelimiter: '~',
	        name: true,
	        cacheGroups: {
	            vendors: {
	                test: /[\\/]node_modules[\\/]/,
	                priority: -10,
	                name:'vendors'
	            },
	            default: {
	                minChunks: 1,
	                priority: -20,
	                reuseExistingChunk: true,
	                name:'test'
	            }
	        }
        }
    },

chunks: 'async',代表只有異步載入模塊時才做代碼分割,chunks: 'all'表示不管異步還是同步都進行代碼分割

minSize: 30000,只有當引入的模塊大於30KB時纔會進行代碼分割

minChunks: 1,模塊至少被引用了一次,進行代碼分割

automaticNameDelimiter: '~',如果沒有配置特定的輸出文件名他都是vendors~lodash.js這些文件的連接符

maxAsyncRequests: 5,
maxInitialRequests: 3表示拆分成幾個文件,一般不改變參數

name:底下的自定義的name是否可以生效

cacheGroups:緩衝組,所有的拆分模塊都遵循以下的原則

vendors中的配置項:表示凡是你引入的模塊在node_modules文件中,引入的模塊均打包到lodash.js中,這樣寫上name的特點是,不管你引入多少個第三方的模塊,均打包到一個叫lodash.js的文件中,priority是優先級,數字越大優先級越高,按照優先級高的要求來打包

reuseExistingChunk:如果以前已經打包過A這個模塊,B文件有引入了這個模塊,則B中的A就不在被打包了,直接在緩存中拿取

總結一下:

    (1)首先我們先打包test.js這個同步的模塊,將下邊的異步模塊註釋掉,我們發現他不在node_modules中,所以遵循default的打包規範,最終打包出一個叫test.js的文件

    (2)接下來將異步模塊打開,將同步模塊註釋掉,他便遵循vendors中的規則,最終打包到vendors.js文件中

四、打包分析 Prefetching/Preloading modules

可以查看相應的官方文檔

進行配置,在打包命令哪一行加點東西

"scripts": {
    "dev-build": "webpack --profile --json > stats.json --config ./build/webpack.dev.js",
    "dev": "webpack-dev-server --config ./build/webpack.dev.js",
    "build": "webpack --config ./build/webpack.prod.js"
  },

再次打包,會發現多處一個stats.json文件,這個文件中記錄了整個打包的流程,當然了不是讓我們自己來看這個文件分析,是藉助一些工具進行分析,點開官網上面的那個鏈接會跳轉到相應的分析工具頁面,將剛纔打包生成的json文件放進去就可以了

當然了,除了github官網上給出來的工具我們也可以打開webpack官網 DOCUMENTION-----GUIDES------Code Splitting-----Bundle Annlyse  右側有一些webpack提供的工具也可以使用

接下來介紹一下Prefetching/Preloading modules同樣是在官方文檔的相同位置

由一個例子引出這兩個概念,將index.js中的內容變成

document.addEventListener('click', () => {
	const element = document.createElement('div');
	element.innerHTML = '123';
	document.body.appendChild(element);
});

打包後打開dist/index.html,在瀏覽器控制檯部分快捷鍵 ctrl+shift+p輸入coverage點開第一個,啓動最左邊的原點錄製按鈕,刷新一次頁面,看到下邊的內容

點開下面的index.js文件我們會發現我箭頭的部分是紅色的,紅色代表的是未執行的代碼當我們點擊了頁面之後,屏幕輸出‘123’並且變成綠色了,表示這個代碼已經執行了 ,後面的百分之多少代表的是代碼利用率

name問題來了,這樣加載文件是不是會影響網頁的性能呢,這個還未點擊之前我們便將這大段的代碼加載進來了,完全沒有必要,那萬一用戶就一直不點擊網頁,一直不需要執行這段代碼,那你一開始就加載進來有什麼用呢?反倒會浪費網頁的資源,我們只需要在用戶點擊了頁面之後在加載這部分代碼即可,接下來進行改進

我們在創建一個異步文件,讓他一開始不加載,只有在用戶點擊時才加載

這時候我們在打開網頁,還是按照上邊的操作步驟

一開始刷新過後不會加載click.js文件,只有點擊了之後纔會加載click.js文件

通過以上的例子我們應該明白其實提升性能並不是通過提取緩存中的內容,而是按需加載,即需要時才加載,也就是代碼的使用率,代碼的利用率越接近100%越說明這個頁面性能越好

舉一個例子,比如說你登錄一個網站,你一開始不需要登錄,那麼一進來頁面就不需要加載登錄這塊的邏輯代碼,但是那如果我需要的時候在加載豈不是很慢,還要等一會,所以最好的解決辦法是先把首頁需要的加載完,然後在偷偷的加載登錄代碼,這樣就在點擊登錄的時候能看到一個立刻彈出的效果了,這個功能的實現就引出了我們要介紹的Prefetching/Preloading modules了,我們配置以下,在我們剛剛寫的index.js的import後加這樣一行代碼

document.addEventListener('click', () => {
	//這裏的default後的fun便是click.js文件導出的那個方法
	import(/* webpackPrefetch:true */'./click.js').then( ({default: func}) => {
		func();
	})
});

五、css模塊的分離打包

經過上邊的配置,我們發現所引入的css文件會被打包到index.js中但是我們希望他被單獨打包出一個css文件,接下來就進行配置

npm install --save-dev mini-css-extract-plugin

按照官網進行引入和配置:注意的點,不僅plugins要配置,loader的style-loader部分也要替換成他給的內容

有一個點需要注意下,之前我們配過 tree shaking ,這裏我們要在package.json文件中將sideEffects中的false改成.css這樣就不會將css文件搖下去了

{
  "name": "webpack-test",
  "sideEffects": [
    "*.css"
  ],
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "dev-build": "webpack --config ./build/webpack.dev.js",
    "dev": "webpack-dev-server --config ./build/webpack.dev.js",
    "build": "webpack --config ./build/webpack.prod.js"
  },

打包後我們發現dist文件下多了一個main.css文件,這裏css文件的名字是entry入口的名字

加入我們想將兩個css文件合併到一個文件中,並且壓縮css文件,那就需要另一個插件

npm install optimize-css-assets-webpack-plugin -D

參照官網進行配置,但是如果想合併代碼必須要在生產環境中才其效果 我們這裏的配置就是運行npm run build

六、webpack與緩存

正常情況下,用戶第一次進頁面會在本地將加載的文件進行緩存,當你不是強制刷新而是普通刷新的時候,頁面會自動去找緩存中的同名文件,如果緩存中有就不在重新請求加載了,只有這個文件沒有的時候纔會去加載

假如一個場景,用戶在第一次打開頁面之後,我們該了一下頁面,如果保證用戶刷新便能重新加載新文件,那就需要給修改過的文件一個hash值,凡是文件的內容變了,文件的hash值也變了,

注意這個場景模擬的四打包上線,所以用npm run build,並且配置文件,將webpck.common.js中的output重新在兩個不同的文件中配置

當index.js中的內容不變時,兩次打包生成的hash值相同,當改變index.js中的內容時,此時的hash值就會變化了

七、shimming墊片

墊片用到的場景非常多,如果我們想改變webpack自身的屬性就需要配置他了

先拋出一個例子,加入我們想用jquery這個庫

先安裝jquery

npm install jquery -D

然後在需要的模塊中引入

var $ = require('jquery');  //  import $ from 'jquery';

 

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