在开发的时候会时经常使用到第三方的库或者框架,好比耳熟能详的jquery
。借助它们能提升开发效率,可是如何在webpack
中使用呢。这篇文章介绍两个东西,如何使用第三方库以及如何提取第三方库。javascript
安装jQuerycss
npm i jquery -S
目录结构如图:html
package.json
内容以下:java
{ "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
内容以下:node
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
内容以下:jquery
<!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
内容以下:webpack
#box{ width: 800px; height: 500px; border: 5px solid #999; color: #00f; background: url(../images/img_01.jpg); }
index.js
内容以下:web
import '../css/index.css'; import $ from 'jquery'; //引入jquery $('ul li:last-child').css('background','green');
npm run build
后打开页面会看到最后一个li
标签有了一个绿色的背景。若是你打开index.js
文件后会发现jquery
的代码也被压缩了进来。npm
这是引入第三方库的一种方式,但这种方式会有一个问题,若是我仅仅只是引入而并无使用,在打包的时候依然会把第三方库打包进来。若是你的代码由第二位同窗接手,他为了不出错并不会直接把import
删掉,而会把使用这个库的代码删掉,假如这个库的代码只剩下了import
,那打包后的文件体积依然很大,即是一种浪费json
修改index.js
以下:
import '../css/index.css'; import $ from 'jquery'; //引入jquery //$('ul li:last-child').css('background','green');
npm run build
后打开index.js
,你会发现jquery
的代码依然被打包了
- 自动加载模块,而没必要用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
的内容并无被打包进来。这种方式比上一种方式就智能的很,会根据你是否使用库而决定是否打包。
对于提取第三方库有两种形式,第一种是在一个页面里引入了多个库,最终全部的代码都会打包到一个文件里,若是引入的库很是之多,那文件会很是大,不利于加载。第二种就是在多个页面里都引入了同一个库,那会把这个库打包屡次,形成资源浪费。因此就须要把第三方库单独提取出来,优化资源。
接着上面的代码,再添加一个库,这个库的名字叫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 缓存组
- 能被提取的条件
一、模块被重复引用或者来自node_modules中的模块 二、模块压缩前至少有30kb 三、按需(异步)请求的数量小于5个 四、初始化加载时,并行请求数量小于等于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/plugin...
还有另外一种形式,像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
的内容已经所有写完~