1.webpack的概念及主要功能
概念: WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。
功能
- 编译,包括JavaScript的编译,Css的编译;
- 文件的压缩,打包,合并,公共模块图区等;
- 图片资源的处理,如压缩;
- Tree-shaking等优化Javascript工具;
- Webpack-dev-sever、Eslint、热更新等帮助开发的工具
2.webpack的安装
在安装webpack之前首先要安装node
本文中所使用的webpack版本为4.35.2,webpack-cli为3.2.3
2.1 全局安装
安装命令 npm install webpack@4.35.2 -g
版本4之后还需要搭配一个cli
npm install webpack@4.35.2 webpack-cli@3.2.3 -g
2.2 局部安装
安装命令 npm install webpack@4.35.2 --save-dev
版本4+ npm install webpack@4.35.2 webpack-cli@3.2.3 --save-dev
建议在使用的时候建议大家进行局部安装,因为我们做项目时可能有多个,每一个webpack的版本各不相同,有些可能是很久以前的版本,如果全局安装的话,会造成打包编译出现问题。
2.3 初始化
我们创建一个test文件夹,并进入其中,使用命令npm init -y
进行package.json文件初始化,这个时候我们会发现test文件夹中多了package.json文件
其中main属性为编译的入口文件,然后我们在test根目录下进行webpack局部安装
js
npm install webpack@4.35.2 webpack-cli@3.2.3 --save-dev
安装成功之后我们会发现package.json中多了webpack和webpack-cli对应的版本号,并且test目录下多了package-lock.json和node_modules依赖
2.3 webpack的核心概念
- entry
- output
- loader
- plugin
在下文有详细介绍
3.用webpack打包一次
3.1 创建入口文件
package.json文件中的main属性,为打包文件的入口,那我们在test文件夹下创建index.js文件,并写入一段代码
3.2创建配置打包文件
在test文件夹下创建webpack.config.js文件,并写入对应代码
js
module.exports={
}
注意 当我们没有指定打包配置文件时,webpack.config.js文件即为默认配置文件,webpack会默认在根目录下寻找webpack.config.js文件作为配置文件
3.2.1 entry
entry为文件入口,代码从这里进行编译,程序开始的起点,其写法有几种
js
module.exports={
// entry:'./index.js', //以index.js为入口
// entry:['./index.js','./index2.js'],//将两个入口文件打包成一个入口,如果要这么写需要在加上对应的入口文件
//两个会打包成两个以app、app2为入口单应用页面程序
//entry:{
// app: './index.js',
// app2:'./index2.js'
//},
//常用
entry:{
app: './index.js'
},
}
3.2.2 output
output为文件的出口,最终的打包结果会根据output的定义输出,会影响到资源的路径 其中output中的filename是出口的文件名
3.3如何使用局部webpack进行打包
我们使用的是局部webpack,这个时候直接使用webpack命令进行打包会优先使用全局的webpack进行编译,这个时候需要我们在package.json的scripts中添加一行命令
build可以改成任意的名字,
3.4webpack的第一次打包
然后我们在控制台输入npm run build
,如果输入别名了就是npm run <别名> ,这样就会执行webpack命令,但是和在终端中直接输入webpack是有区别的,scripts中的webpack默认会先使用局部的webpack,再去找全局的webpack ,然后会看到控制台如下图输出,并且我们test文件夹下会多出dist文件夹里边有一个app.js文件,这个时候我们的第一次打包代表成功了
3.3output中的filename
注意 除了在3.2.2中output中的filename那种固定的写法外,我们还有不固定的写法,如下
js
module.exports={
entry:'./index.js', //入口文件
output:{//出口
filename:'./js/[name].[hash].js' //即可打包如main.jasidjasidji.js,该文件会在dist/js下
}
}
name为文件名,指entry中的key值,默认为main;hash为一串字符串 hash也可以进行截取,如
js
module.exports={
entry:'./index.js', //入口文件
output:{//出口
filename:'./js/[name].[hash:4].js' //即可打包如main.jasi.js,改hash只有4位
}
}
也可以写成下例:path为打包的地址, __dirname代表项目绝对路径
js
module.exports={
entry:{
app:'./index.js' //入口文件
},
output:{//出口
// name为entry中的key,也就是现在的app
// __dirname代表项目绝对路径
path:__dirname + '/src/mybundle',//打包到指定路径中,若不填写则默认到dist文件夹下
filename:'./js/[name].[hash:4].js'
}
}
重新打包后会生成src/mybundle/app.7aa1.js,name变成了app,hash只有4为,文件存放地址在test目录下的src/mybundle
4.webpack中js编译
4.1编译es6
4.1.1 Babel-loader
编译需要安装的loader:babel-loader,babel/core
babel-loader为编译es6要用到的loader,babel/core 为babel-loader的编译核心,babel-loader是利用babel/core来进行编译的
js
//安装命令 局部安装babel-loader
npm install babel-loader @babel/core --save-dev
安装好之后会在package.json中写入
然后在index.js文件写入es6的语法
js
//index.js文件
setTimeout(()=>{
console.log(1)
},1000)
在webpack.config.js中编写配置
loader是写在module中rules数组下,每个itme为一条loader,test为匹配规则(现在写的是以.js结尾的文件),use中写需要使用的loader
js
module.exports={
entry:{
app:'./index.js' //入口文件
},
output:{//出口
// name为entry中的key,也就是现在的app
// __dirname代表项目绝对路径
//path:__dirname + '/src/mybundle',//打包到指定路径中,若不填写则默认到dist文件夹下
filename:'./js/[name].[hash:4].js'
},
module:{
rules:[{
test: /\.js$/, //匹配规则,以.js结尾的文件
use: 'babel-loader'
}]
},
}
再去打包后,发现我们的代码并没有转成es5,是我们的babel-loader没有生效吗?并不是的,只是我们缺少一些配置,babel默认只转换新的 JavaScript 语法,比如箭头函数、扩展运算(spread)。不转换新的 API,例如Iterator
、Generator
、Set
、Maps
、Proxy
、Reflect
、Symbol
、Promise
等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign
)都不会转译。如果想使用这些新的对象和方法,则需要为当前环境提供一个垫片(polyfill)
4.1.2 Babel-preset
配置中缺少Babel-preset,babel-preset是储存javascript不同标准的插件,通过使用正确的presets,告诉babel按照哪个规范编译
js
//安装命令
npm install @babel/preset-env --save-dev
Babel-prese中的targets配置
targets是preset的核心配置,告诉preset编译的具体目标
- targets可以:以browsers(浏览器)为目标(通常情况)
- 以node的版本为目标
- 以特定的浏览器为目标
js
//webpack.config.js文件
module.exports={
entry:{
app:'./index.js' //入口文件
},
output:{//出口
// name为entry中的key,也就是现在的app
// __dirname代表项目绝对路径
// path:__dirname + '/src/mybundle',//打包到指定路径中,若不填写则默认到dist文件夹下
filename:'./js/[name].[hash:4].js'
},
module:{
rules:[{
test:/\.js$/, //匹配规则,以.js结尾的文件
use:{
loader:'babel-loader',
options:{
presets:[
//编译es6的语法,对es6的方法是无能为力的
["@babel/preset-env",{
"targets":{
"browsers":["> 0%"] //写1%>无法正常进行转换,以大于市场份额0%的浏览器作为编译目标
}
}]
]
},
}
}]
},
}
打包好了之后进入打包文件,会发现已经对es6语法进行了编译
4.1.3 Babel-polyfill & Babel-transform-runtime
注意Babel-preset只能对es6的语法进行处理,对es6的方法就无能为力了,这个时候我们可以使用babel-polyfill或者babel-transform-runtime这两种方式来解决。
两者的区别
babel-polyfill | babel-transform-runtime |
---|---|
生成一个全局对象 | 生成一个局部对象 |
一般用于项目的开发 | 一般用于框架开发 |
4.1.3.1 Babel-polyfill的安装及使用
js
//安装命令
npm install babel-polyfill --save-dev
在index.js文件中引入使用,并且使用es6的方法,如果不引用会发现该方法无法被解析
打包后会发现该文件体积明显增大,在打包的代码里生成一个全局对象,这个对象里定义了我们一些es6api的实现,也就是说把我们需要用到的需要编译的es6方法全部用我们的es5来实现一遍,放到这个全局对象里,这样我们在代码里写的es6方法实际上是使用的babel-polyfill里写的方法
不在index.js中引用,也可以写到我们的webpack.config.js文件的entry上,效果是一样的。
4.1.3.2 Babel-transform-runtime的安装及使用
Babel为了解决Babel-polyfill的问题,提供了单独的包babel-runtime用以提供编译模块的工具函数,启用插件babel-plugin-transform-runtime后,Babel就会使用babel-runtime下的工具函数。
babel-runtime插件能够将这些工具函数的代码转换成require语句,指向为对babel-runtime的引用。每当要转译一个api时都要手动加上require('babel-runtime')
。简单说 babel-runtime 更像是一种按需加载的实现,比如你哪里需要使用 Promise,只要在这个文件头部 require Promise from 'babel-runtime/core-js/promise'
就行了。
为了方便使用 babel-runtime,解决手动 require 的苦恼。babel-plugin-transform-runtime会分析我们的 javascript 中,是否有引用 babel-rumtime 中的垫片(通过映射关系),如果有,就会在当前模块顶部插入我们需要的垫片。
transform-runtime 是利用 plugin 自动识别并替换代码中的新特性,你不需要再引入,只需要装好 babel-runtime 和 配好 plugin 就可以了。
好处是按需替换,检测到你需要哪个,就引入哪个 polyfill,如果只用了一部分,打包完的文件体积对比 babel-polyfill 会小很多。而且 transform-runtime 不会污染原生的对象,方法,也不会对其他 polyfill 产生影响。
所以 transform-runtime 的方式更适合开发工具包,库,一方面是体积够小,另一方面是用户(开发者)不会因为引用了我们的工具,包而污染了全局的原生方法,产生副作用。
js
//安装命令
npm install @babel/plugin-transform-runtime @babel/runtime --save-dev
js
//配置
"plugins:[
["@babel/transform-runtime"]
]
在写法上与Babel-polyfill有所不同,它作为Babel的插件是写在plugins里。需要注意的是,使用@babel/plugin-transform-runtime
,不会对实例方法比如"foobar".includes("foo")
进行转换,因为这将需要对已存在的内置对象进行修。
我们先修改一下index.js文件,添加一个async函数
安装好后,我们先禁用掉Babel-polyfill,配置plugin-transform-runtime,进行打包。
打包后我们会发现文件体积相比之前使用Babel-polyfill(90多kb)小了很多,并且成功加入了相关的垫片。
小结
babel-loader,babel-core,babel-preset的关系
编译ES6需要的 babel-loader 与 @babel/core ,@babel/core 是 babel-loader 的核心。babel-preset 是储存 javascript 不同标准的插件,通过使用正确的 babel-presets ,告诉 babel 按照哪个规范编译。否则 babel-loader 不会进行ES6的编译。
.babelrc
如果我们的webpack.config.js中的options越写越多,就会看起来不美观,也不方便维护,这时我们可以写成一个单独的文件,在test文件夹下新建一个.babelrc的文件,必须是这个名字,我们的babel会自动读取这个文件下的内容。
4.2 编译ts
js
//安装命令
npm install typescript@2.9.2 ts-loader@4.5.0 --save-dev
注意 此处安装typescript和ts-loader要注意版本,如果版本和当前webpack不太适配的话,打包会报错,同学们可以安装一下其它版本试试。 安装成功后package.json会写入。 新增一个test.ts文件,并书写一段ts代码,然后再index.js引用
webpack.config.js中写入ts-loader
js
{
test:/\.tsx?$/, // /\.tsx?$/ ts文件有以ts后缀或者tsx后缀 所以此处写tsx?
use:'ts-loader'
}
新增tsconfig.json文件,并写入配置
js
//tsconfig.json文件
{
//编译配置
"compilerOptions": {
"module": "commonjs",//使用什么样的模块化规范
"target": "es5" //编译成什么语法
},
"exclude": ["./node_modules"] //不处理什么文件
}
进行打包后就可以看到我们所写的ts语法已经被处理
5.css的编译和处理
5.1 css的第一次打包
webpack是以js文件为入口进行打包的,那么项目的css怎么办?如何引入css?
css可以通过js文件引入,但必须使用相应的loader
- css-loader,让css可以被js正确的引入;
- style-loader,让css被引入后可以被正确的以一个style标签插入到页面;
- 两者的顺序很重要,要先经过css-loader的处理,再由style-loader处理。
js
//安装命令,需要安装适合webpack版本的
npm install style-loader@0.23.1 css-loader@3.0.0 --save-dev
新增test.css和test2.css,并写入简单的样式
css
/* test.css文件 */
*{
background-color: red;
}
css
/* test2.css文件 */
body{
font-size: 20px;
}
.fzcolor{
color: blue;
}
index.js入口文件引入test.css和test2.css
js
import "./test.css"
import "./test2.css"
console.log(123)
新增index.html文件,其中script标签的src地址是我们webpack.config.js文件中output打包固定的地址名称
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="mydiv">
<!-- 此处src引用的是打包好的js文件,app.bundle.js
是在webpack.config.js中output固定的filename -->
<script text="text/javascript" src="./dist/js/app.bundle.js"></script>
</div>
</body>
</html>
书写webpack.config.js中的loader配置
js
module.exports={
entry:{
// app:['babel-polyfill','./index.js'] //入口文件
app:['./index.js'] //入口文件
},
output:{//出口
// name为entry中的key,也就是现在的app
// __dirname代表项目绝对路径
// path:__dirname + '/src/mybundle',//打包到指定路径中,若不填写则默认到dist文件夹下
filename:'./js/[name].bundle.js'
},
module:{
rules:[{
test:/\.js$/, //匹配规则,以.js结尾的文件
use:{
loader:'babel-loader',
}
},{
test:/\.tsx?$/, // /\.tsx?$/ ts文件有以ts后缀或者tsx后缀 所以此处写tsx?
use:'ts-loader'
},{
test:/\.css$/,
use:[{
loader:'style-loader',
},{
loader:'css-loader',
}]
}]
},
}
注意use是多个的话可以写成数组形式;上文讲到要先经过css-loader的处理,再由style-loader处理,但是在use里是从下往上加载,所以要先写style-loader。
打包之后,直接在浏览器打开我们的index.html,会发现我们的样式已经生效。
5.2 核心配置
style-loader的核心配置
- instertAt :style标签插入再header哪一块区域或某个div;
- insertInto:插入指定的dom
- singleton:是否合并为一个style标签
- transform:在浏览器环境下,插入style到页面前,用js对css进行操作
js
module.exports={
entry:{
app:['./index.js']
},
output:{
filename:'./js/[name].bundle.js'
},
module:{
rules:[{
test:/\.css$/,
use:[{
loader:'style-loader',
options:{
// instertAt:'top',//'bottom'style标签插入再header那一块区域
// instertAt:{
// before:'#mydiv'
// }
insertInto:'#mydiv', //插入指定的dom
singleton:true ,//是否合并为一个style标签
transform:'./transform.js'//在浏览器环境下,插入style到页面前,用js对css进行操作
}
},{
loader:'css-loader',
}]
}]
},
}
在transform配置上写的是一个文件地址,那我们在text目录下新增transform.js文件
js
//transform.js
module.exports = function(css){
if(window.screen.width<500){
//宽度小于500时将红色替换为黄色
css = css.replace('red','yellow')
}
return css //必须要将处理过后的css return出去
}
//style标签在插入浏览器生效之前最后一次对css进行修改
重新打包后,浏览器初始背景为红色,切换到手机模式,小屏500内后重新刷新,会发现背景变为黄色。
css-loader的核心配置
- minimize:是否压缩css,webpack4中已移除
- module:是否使用css模块化,类似与less可以使用变量
- alias:css中的全局别名,webpack4中已移除
开始配置css-loader
css
{
loader:'css-loader',
options:{
modules:true,
}
}
在test.css和test2.css文件中新增一些样式,global定义全局样式,local定义局部样式,composes继承
css
/* test.css */
*{
background-color: red;
}
.border-yellow{
border: 4px solid yellow;
}
:global .box{
border: 4px solid green;
}
css
/* test2.css */
body{
font-size: 20px;
}
.fzcolor{
color: blue;
}
:global .borders{
border: 4px solid white;
}
:local .div1{
width: 50px;
height: 50px;
background-color: pink;
composes: fzcolor; /* 这种无法使用global定义的,并且只能是当前文件的样式 */
composes: box from global;/*可以使用global,包括其他文件*/
composes: border-yellow from './test.css';/*使用其他文件的普通样式*/
}
然后我们重新进行打包,会发现所写的样式名称已经变成了一串编码,但是并没有引入到mydiv中,所以没有生效。并且可以发现这里只有对设置为local或者没有任何设置的类型进行了编码,对global或者是标签之类的没有进行编码。
所以我们需要通过js来控制我们的类名,接下来在index.js中进行一下修改
js
// 之前的引用方式
// import "./test.css"
// import "./test2.css"
//modules后的书写方式
import test from './test.css'
import test2 from './test2.css'
document.getElementById('mydiv').setAttribute('class',test2.div1)
然后我们重新进行打包,会发现样式已经成功生效。
但是这个类名难以阅读理解,我们可以在webpack.config.js文件中对css-loader进行一下处理,然后重新进行打包
js
{
loader:'css-loader',
options:{
modules:{
//path name 文件名,local 初始类名, hash 哈希值
localIdentName:'[path][name]_[local]_[hash:4]'
}
}
}
less、sass等预处理语言的编译
less、sass编译所需loader
- less: less、less-loader
- sass: sass-loader、node-sass
less
js
//安装命令,因为使用的webpack是版本4,所以此处对less和less-loader的版本有所要求
npm install less@3.9.0 less-loader@5.0.0 --save-dev
然后更改test.css和test2.css为test.less和test2.less文件,并更改index.js文件中的引用,test.less文件中增加一个less写法的变量并使用,test2.less文件并引用对应的样式
css
/* test.css */
@base: green;
* {
background-color: red;
}
.border-yellow {
border: 4px solid @base;
}
:global .box {
border: 4px solid green;
}
css
/* test2.css */
body {
font-size: 20px;
}
.fzcolor {
color: blue;
}
:global .borders {
border: 4px solid white;
}
:local .div1 {
width: 50px;
height: 50px;
background-color: pink;
composes: border-yellow from "./test.less";
}
更改webpack.config.js中相关配置,将test:/\.css$/
改为test:/\.less$/
并加入配置{loader:'less-loader'}
这里依旧要注意顺序,我们less-loader将less文件处理成css文件将会交给css-loader进行处理、然后在由style-loader处理
js
{
test:/\.less$/,
// npm install style-loader@0.23.1 css-loader@3.0.0 --save-dev
use:[{
loader:'style-loader',
options:{
insertInto:'#mydiv', //插入指定的dom
singleton:true ,//是否合并为一个style标签
transform:'./transform.js'//在浏览器环境下,插入style到页面前,用js对css进行操作
}
},{
loader:'css-loader',
options:{
modules:{
localIdentName:'[path][name]_[local]_[hash:4]'
}
}
},{
loader:'less-loader',
}]
重新打包后会发现div有了绿色边框已经生效。
提取css代码为单独文件
- 安装对应的插件(extract-text-webpack-plugin)
- 改造loader处的写法,把use改为使用extract-text-webpack-plugin
- 在plugin处添加(把extract-text-webpack-plugin加入到plugin里)
js
//安装命令,注意安装适配当前webpack的版本
npm install extract-text-webpack-plugin@4.0.0-beta.0 --save
在webpack.config.js中引入extract-text-webpack-plugin插件,改写use,并加入plugin
js
var extractTextCss = require('extract-text-webpack-plugin')
module.exports = {
entry: {
// app:['babel-polyfill','./index.js'] //入口文件
app: ['./index.js'] //入口文件
},
output: {//出口
// name为entry中的key,也就是现在的app
// __dirname代表项目绝对路径
// path:__dirname + '/src/mybundle',//打包到指定路径中,若不填写则默认到dist文件夹下
filename: './js/[name].bundle.js'
},
module: {
rules: [{
test: /\.js$/, //匹配规则,以.js结尾的文件
use: {
loader: 'babel-loader',
}
}, {
test: /\.tsx?$/, // /\.tsx?$/ ts文件有以ts后缀或者tsx后缀 所以此处写tsx?
use: 'ts-loader'
}, {
test: /\.less$/,
// npm install style-loader@0.23.1 css-loader@3.0.0 --save-dev
use: extractTextCss.extract({
fallback: {
loader: 'style-loader',
options: {
insertInto: '#mydiv', //插入指定的dom
singleton: true,//是否合并为一个style标签
transform: './transform.js'//在浏览器环境下,插入style到页面前,用js对css进行操作
}
},
use: [{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[path][name]_[local]_[hash:4]'
}
}
}, {
loader: 'less-loader',
}]
})
}]
},
plugins:[
new extractTextCss({
filename:'[name].min.css'
})
]
}
然后重新打包,会发现额外的增加了app.min.css文件,然后我们需要在index.html中手动通过link标签引入app.min.css文件
postcss和postcss-loader
js
//安装命令autoprefixer 属于postcss第三方插件需要单独安装
npm install postcss@7.0.17 postcss-loader@3.0.0 autoprefixer@9.6.1 --save
更改webpack.config.js配置增加postcss-loader,注意顺序 ,并在test.less文件中增加display:flex
样式
js
use: extractTextCss.extract({
fallback: {
loader: 'style-loader',
options: {
insertInto: '#mydiv', //插入指定的dom
singleton: true,//是否合并为一个style标签
transform: './transform.js'//在浏览器环境下,插入style到页面前,用js对css进行操作
}
},
use: [{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[path][name]_[local]_[hash:4]'
}
}
},{
loader: 'postcss-loader',
options:{
ident:'postcss',
plugins:[
require('autoprefixer')({
"overrideBrowserslist":[
">1%",'last 2 versions' //需要指定浏览器编译目标 类似于babel
]
})
]
}
},{
loader: 'less-loader',
}]
})
css
/* test.css */
@base: green;
* {
background-color: red;
}
.border-yellow {
border: 4px solid @base;
display: flex;
}
:global .box {
border: 4px solid green;
}
然后重新打包,打开app.min.css文件会发现给display:flex
增加了对应前缀
总结
我们在大量使用loader时都需要配置Browserslist,这样会造成大量重复且容易不统一,那么有两种方式可以统一配置
- 在package.json配置中增加browserslist(推荐 )
- 增加.browserslistrc文件,类似于.babelrc
6.html的编译和处理
在上文中都是手动引入js、css文件,其实在webpack中可以自动帮我们引入,需要用到html-webpack-plugin插件。
js
//安装命令
npm install html-webpack-plugin@3.2.0 --save-dev
相关配置
- filename: 打包生成后的html文件的名字(必填)
- tmplate: 指定一个html文件作为模板(必填)
- minify: 压缩html
- inject: 是否把js、css文件插入到html,插入到哪里
- chunks: 多入口时指定引入chunks 在webpack.config.js配置中引入该插件,然后添加到plugin中
6.1 filename、tmplate
js
var htmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry:{ //*** },
//***
plugins:[
//***
new htmlWebpackPlugin({
filename:'index.html',
template:'./index.html'
})
]
}
我们在删掉index.html中之前手动引入的js和css,然后进行打包,这个时候我们会发现dist中新增加了index.html文件,打开盖文件可看到里边已经自动引入可我们打包的js和css文件。
6.2 minify、inject
压缩时配置minify参数,接受的是一个对象,但是webpack也是使用的第三方,所以该对象是给第三方使用的
js
var htmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry:{ //*** },
//***
plugins:[
//***
new htmlWebpackPlugin({
filename:'index.html',
template:'./index.html',
minify:{
collapseWhitespace:true
},
inject: true, //默认为true,设置false时不引入js、css
})
]
}
6.3 chunks
配置chunks,如果我们的entry是多入口时,这个时候不指定chunks那么就会将js都打包进去
js
module.exports={
entry:{
app: './index.js',
app2:'./index2.js'
},
//***
plugins:[
//***
new htmlWebpackPlugin({
filename:'index.html',
template:'./index.html',
minify:{
collapseWhitespace:true
}
chunks:['index']
})
]
}
通过该配置我们生成的打包结果只会将index.js打包到index.html中