標籤:split mode run 開啟 多少 red group meta oca
在開發的時候會時常用到第三方的庫或者架構,比如耳熟能詳的
jquery
。藉助它們能提高開發效率,但是如何在
webpack
中使用呢。這篇文章介紹兩個東西,如何使用第三方庫以及如何提取第三方庫。
使用第三方庫1、在入口檔案當中直接匯入
安裝jQuery
npm i jquery -S
目錄結構
package.json
內容如下:
{ "name": "webpack-demo", "version": "1.0.0", "description": "", "main": "webpack.config.js", "scripts": { "build": "webpack --mode production", "dev": "webpack-dev-server --mode development" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "css-loader": "^1.0.0", "file-loader": "^1.1.11", "html-webpack-plugin": "^3.2.0", "mini-css-extract-plugin": "^0.4.1", "url-loader": "^1.0.1", "webpack": "^4.16.3", "webpack-cli": "^3.1.0", "webpack-dev-server": "^3.1.5" }, "dependencies": { "jquery": "^3.3.1" }}
webpack.config.js
內容如下:
const path=require(‘path‘);const HtmlWebpackPlugin=require(‘html-webpack-plugin‘);const MiniCssExtractPlugin=require(‘mini-css-extract-plugin‘);module.exports={ entry:‘./src/js/index.js‘, output:{ path:path.resolve(__dirname,‘dist‘), filename:‘js/index.js‘ }, plugins:[ new HtmlWebpackPlugin({ title:‘陳學輝‘, template:‘./src/template.html‘, filename:‘index.html‘ }), new MiniCssExtractPlugin({ filename:‘css/index.css‘ }), ], devServer:{ host:‘localhost‘, port:1573, open:true }, module:{ rules:[ { test:/\.css$/, use:[ { loader:MiniCssExtractPlugin.loader, options:{ publicPath:‘../‘ } }, ‘css-loader‘, ] }, { test:/\.(jpg|png|gif)$/, use:[ { loader:‘url-loader‘, options:{ limit:5 * 1024, outputPath:‘images‘ } } ] } ] }}
templage.html
內容如下:
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <div id="box"> <p>這是內建的div</p> <ul> <li><a href="#">red</a></li> <li><a href="#">green</a></li> <li><a href="#">blue</a></li> </ul> </div> </body></html>
index.css
內容如下:
#box{ width: 800px; height: 500px; border: 5px solid #999; color: #00f; background: url(../images/img_01.jpg);}
index.js
內容如下:
import ‘../css/index.css‘;import $ from ‘jquery‘; //引入jquery$(‘ul li:last-child‘).css(‘background‘,‘green‘);
npm run build
後開啟頁面會看到最後一個li
標籤有了一個綠色的背景。如果你開啟index.js
檔案後會發現jquery
的代碼也被壓縮了進來。
這是引入第三方庫的一種方式,但這種方式會有一個問題,如果我僅僅只是引入而並沒有使用,在打包的時候依然會把第三方庫打包進來。如果你的代碼由第二位同學接手,他為了避免出錯並不會直接把import
刪掉,而會把使用這個庫的代碼刪掉,假如這個庫的代碼只剩下了import
,那打包後的檔案體積依然很大,便是一種浪費
修改index.js
如下:
import ‘../css/index.css‘;import $ from ‘jquery‘; //引入jquery//$(‘ul li:last-child‘).css(‘background‘,‘green‘);
npm run build
後開啟index.js
,你會發現jquery
的代碼依然被打包了
2、webpack.ProvidePlugin
- 自動載入模組,而不必用import或require
- 如果載入的模組沒有使用,則不會被打包
- 載入的模組為全域模組,在全域都可以使用
修改webpack.config.js
如下:
const path=require(‘path‘);const HtmlWebpackPlugin=require(‘html-webpack-plugin‘);const MiniCssExtractPlugin=require(‘mini-css-extract-plugin‘);const webpack=require(‘webpack‘); //引入webpack模組,ProvidePlugin是webpack身上的一個外掛程式module.exports={ entry:‘./src/js/index.js‘, output:{ path:path.resolve(__dirname,‘dist‘), filename:‘js/index.js‘ }, plugins:[ new HtmlWebpackPlugin({ title:‘陳學輝‘, template:‘./src/template.html‘, filename:‘index.html‘ }), new MiniCssExtractPlugin({ filename:‘css/index.css‘ }), new webpack.ProvidePlugin({ //它是一個外掛程式,所以需要按外掛程式的用法new一個 $:‘jquery‘, //接收名字:模組名 }), ], devServer:{ host:‘localhost‘, port:1573, open:true } ...
修改index.js
內容如下:
import ‘../css/index.css‘;$(‘ul li:last-child‘).css(‘background‘,‘green‘);
npm run build
後開啟index.html
可以看到一樣的效果
再次修改index.js
內容如下:
import ‘../css/index.css‘;//$(‘ul li:last-child‘).css(‘background‘,‘green‘);
npm run build
後開啟index.js
可以看到jquery
的內容並沒有被打包進來。這種方式比上一種方式就智能的很,會根據你是否使用庫而決定是否打包。
提取第三方庫
對於提取第三方庫有兩種形式,第一種是在一個頁面裡引入了多個庫,最終所有的代碼都會打包到一個檔案裡,如果引入的庫非常之多,那檔案會非常大,不利於載入。第二種就是在多個頁面裡都引入了同一個庫,那會把這個庫打包多次,造成資源浪費。所以就需要把第三方庫單獨提取出來,最佳化資源。
1、一個頁面引入多個庫
接著上面的代碼,再添加一個庫,這個庫的名字叫underscore
,它裡面封裝了很多關於數組與對象的方法,我拿其中一個方法進行示範
npm i underscore -S
修改webpack.config.js
裡的外掛程式:
new webpack.ProvidePlugin({ //它是一個外掛程式,所以需要按外掛程式的用法new一個 $:‘jquery‘, //接收名字:模組名 _:‘underscore‘ //引入underscore庫}),
修改index.js
如下
import ‘../css/index.css‘;$(‘ul li:last-child‘).css(‘background‘,‘green‘);console.log(_([1,2,3]).map(v=>v*3)); //使用underscore庫裡的map方法,此方法為迴圈數組裡每一位元據,並把每位元據都乘以3,返回新數組
npm run build
後開啟index.html
能看到控制台有輸出了[3, 6, 9]
,說明underscore
庫已經被打包到index.js
裡。可以分別注釋jquery
與underscore
的使用代碼,npm run build
後對比index.js
的大小就能看出區別
提取第三方庫
optimization 最佳化
- splitChunks 緩衝組
- 能被提取的條件
1、模組被重複引用或者來自node_modules中的模組
2、模組壓縮前至少有30kb
3、按需(非同步)請求的數量小於5個
4、初始化載入時,並行請求數量小於等於3
修改webpack.config.js
裡的moudle.exports
module.exports={ entry:{ index:‘./src/js/index.js‘, //要把入口檔案與第三方庫分開,所以要單獨的給名字 }, output:{ path:path.resolve(__dirname,‘dist‘), filename:‘js/[name].js‘ //以key做為輸出的名字 }, plugins:[ //... new webpack.ProvidePlugin({ $:‘jquery‘, _:‘underscore‘ }), ], devServer:{ //... }, module:{ //... }, optimization:{ //最佳化 splitChunks:{ cacheGroups:{//緩衝組,一個對象。它的作用在於,可以對不同的檔案做不同的處理 commonjs:{ name:‘vender‘, //輸出的名字(提出來的第三方庫) test: /\.js/, //通過條件找到要提取的檔案 chunks:‘initial‘ //只對入口檔案進行處理 } } } }}
npm run build
之後有兩個檔案,index.js
與vender.js
,其中vender.js
裡放的就是jquery
與underscore
的代碼。
說明:
optimization
是webpack
的另一個配置參數,它的意義在於最佳化。裡面的splitChunks
參數值用來放提取第三方庫的一些設定,比如:要提取同步還是非同步模組,這個模組的引用次數達到多少能被提取等。但是放在這裡的參數會對所有要提取的模組生效。如果不同的公用模組要不同的對待的話就需要在splitChunks.cacheGroups
裡去定義
cacheGroups
翻譯過來就是緩衝組,可以理解為針對不同的要提取的公用部分進行單獨設定,比如上面例子中要針對js進行提取,所以就起了個名字叫commonjs
,那它是個對象,裡面放的就是單獨的配置參數
詳細說明請參考:https://webpack.js.org/plugins/split-chunks-plugin/
2、多個頁面同時引入一個庫
還有另一種形式,像jquery
,它在多個頁面裡都被引入了,因為打包只能針對單頁面進行打包,那就會在每個頁面裡都打包一次jquery
,造成資源浪費
建立a.js
與b.js
,內容如下:
a.js
import $ from ‘jquery‘;console.log(‘這是a.js‘);console.log($(‘ul‘));
b.js
import $ from ‘jquery‘;console.log(‘這是b.js‘);console.log($(‘ul li‘));
可以看到兩個js
檔案都引入了jquery
檔案
修改webpack.config.js
檔案的module.exports
module.exports={ entry:{ a:‘./src/js/a.js‘, b:‘./src/js/b.js‘ }, output:{ path:path.resolve(__dirname,‘dist‘), filename:‘js/[name].js‘ }, plugins:[ //需要兩個頁面,所以寫兩個new HtmlWebpackPlugin /*new HtmlWebpackPlugin({ title:‘陳學輝‘, template:‘./src/template.html‘, filename:‘index.html‘ }),*/ new HtmlWebpackPlugin({ title:‘a頁面‘, template:‘./src/template.html‘, filename:‘a.html‘, chunks:[‘a‘], //引入對應的js,需要用到chunks }), new HtmlWebpackPlugin({ title:‘b頁面‘, template:‘./src/template.html‘, filename:‘b.html‘, chunks:[‘b‘], }), new MiniCssExtractPlugin({ filename:‘css/index.css‘ }), //jquery已經單獨在a與b檔案裡引入了,這裡就不需要了 /*new webpack.ProvidePlugin({ $:‘jquery‘, //接收名字:模組名 _:‘underscore‘ }),*/ ], devServer:{ //... }, module:{ //... },}
npm run build
後結構如,在dist
下的js
目錄裡分別看一下a.js
與b.js
的大小,這兩個檔案裡都包含了jquery
。再分別開啟a.html
與b.html
頁面正常運行,控制台裡列印出了想要的內容。
這樣就是一種浪費了,我們完全可以把jquery單獨提取出來,在兩個頁面裡分別引入。如果是多個頁面都引入同一個庫,那提取公用庫就會是剛需。
修改webpack.config.js
的module.exports
module.exports={ entry:{ a:‘./src/js/a.js‘, b:‘./src/js/b.js‘ }, output:{ path:path.resolve(__dirname,‘dist‘), filename:‘js/[name].js‘ //以key做為輸出的名字 }, plugins:[ new HtmlWebpackPlugin({ title:‘a頁面‘, template:‘./src/template.html‘, filename:‘a.html‘, chunks:[‘a‘,‘vender‘], //vender為提取出的公用部分,需要在頁面裡引入 }), new HtmlWebpackPlugin({ title:‘b頁面‘, template:‘./src/template.html‘, filename:‘b.html‘, chunks:[‘b‘,‘vender‘], }), new MiniCssExtractPlugin({ filename:‘css/index.css‘ }), ], devServer:{ //... }, module:{ //... }, optimization:{ splitChunks:{ cacheGroups:{ common:{ name:‘vender‘, test: /\.js/, chunks:‘initial‘ } } } }}
npm run build
後結構目錄如,再次看一下a.js
與b.js
的大小,相比前面是否小了很多?公用的jquery
已經被提取出來了並放到了vender.js
中。查看a.html
與b.html
頁面源碼發現vender.js
已經被引入了。
至此Webpack 4.X
的內容已經全部寫完~
源碼下載:https://pan.baidu.com/s/1h9PSkbkrhQ1IX7rzOQqk9Q
Webpack 4.X 從入門到精通 - 第三方庫(六)