webpack学习笔记
- webpack模块打包工具的安装
- webpack配置文件的使用
- loader
- 使用plugins让打包更便捷
- Entry 与 Output 的基础配置
- SourceMap的配置
- 使用WebpackDevServe提升开发效率
- Hot Module Replacement 热模块更新
- 使用Babel处理ES6语法
- Tree Shaking
- Development和Production模式的区分打包
- Webpack 和 Code Splitting
- SplitChunksPlugin配置参数
- Lazy Loading懒加载,chunk是什么
- 打包分析,preloading,prefetching
- CSS文件的代码分割
- webpack与浏览器缓存
- Shimming的作用
- 环境变量的使用方法
- Library的打包
- PWA的打包配置
- 使用WebpackDevServer实现请求转发
- WebpackDevServer 解决单页面应用路由问题
- ESLint在Webpack中的配置
- webpack的性能优化
- 多应用打包配置
webpack模块打包工具的安装
npm init --------------------此时产生package.json文件
npm install webpack webpack-cli -g 进行全局安装webpack及webpack-cli
webpack-cli 使得我们可以在命令行使用webpack这个命令
此时通过控制台输入webpack -v可以查看其版本号,但不推荐全局安装webpack及webpack-cli,因为当两个项目的webpack版本不同时,不可以同时运行两个项目,只可运行webpack对应版本的项目。因此,建议只在单个工程(项目)中安装,运行
npm uninstall webpack webpack-cli -g 卸载全局安装。
进入项目,运行
npm install webpack webpack-cli -D 进行单个项目的webpack及cli的安装
产生node_modules文件,输入npx webpack -v查看其版本号。PS:必须带npx(由node提供),全局下找不到webpack 。
npm install webpack@4.16.5 webpack-cli -D 安装webpack固定版本
npm info webpack 查看所有版本
webpack配置文件的使用
1.单个项目安装webpack (需用npx命令)
没有配置文件时,需指明打包入口 npx webpack index.js,运行该命令即可对index.js进行打包
有了打包配置文件,执行npx webpack 即可,默认以webpack.config.js为名的配置文件进行打包。
webpack.config.js
const path = require('path'); //Commonjs 语法,node核心模块path
module.exports = {
mode:'production', //默认打包模式,生成的代码会压缩
// mode:'development', //生成的代码不会压缩
entry:'./index.js', //打包入口(简写,省略main)
// entry:{
// main:'./index.js'
// }
output:{
filename:'bundle.js', //在dist文件夹下生成最终打包好的文件,默认名为main.js
path:path.resolve(_dirname,'dist') //与该文件同级生成dist文件夹
}
}
npx webpack --config webpackconfig.js 以webpackconfig.js配置文件进行打包
2. npm scripts
对于单个项目来说,由于总是需要执行npx webpack进行打包,因此可以简化命令:
在 package.json 文件中
{
"scripts":{
"bundle":"webpack" //不用写npx,优先在node_module找webpack包
}
}
此时运行npm run bundle =运行npx webpack
3.全局安装webpack
webpack index.js,运行该命令即可对index.js进行打包
loader
webpack只会对js文件进行打包,而对图片,css是不识别的,因此要使用loader
loader是当webpack不认识某个文件进行打包时,所用的一种策略
在配置文件中,loader是由下到上,由右至左的顺序进行加载的。
1.loader打包图片
使用file-loader
file-loader将该图片备份到dist目录下,并对打包后的图片重新起名
module:{
rules:[{
test:/\.(jpg|png|gif)$/,
use:{
loader:' file-loader',
//配置打包后的图片名与原图片名一致
// options:{
// //placeholders
// name:'[name].[ext]',
// }
}
}]
}
使用url-loader
module:{
rules:[{
test:/\.(jpg|png|gif)$/,
use:{
loader:'url-loader',
options:{ //对使用的loader进行配置
name:'[name]_[hash].[ext]', //打包后新生成的图片名字与原名字相同,并且加了hash值
outputPath:'images/', //在dist下生成images文件,将打包生成的文件放在images下
limit:10240
}
}
}]
}
使用url-loader进行对图片的打包,其将小于10240KB的图片进行BIT64位编码,写入最终的js文件中。
当图片大于10240KB时,图片将以file-loader策略进行打包,即将会在dist的目录下新建images目录,由于配置了name,图片将以原名重新再images目录下生成,index.html将以路径的形式进行引用,而不是在js中用bit64编码图片。
2.loader打包静态资源(样式篇)
对样式css进行打包时, style-loader, css-loader 必须同时使用。
loader是从下到上,从右到左的执行顺序。
{
test:/\.scss$/,
use:[
'style-loader', //4.挂在到html的head上<style>上
{
loader:'css-loader', //3.处理css
options:{
importLoaders:2, //保证index.scss引入的其他scss文件也经过1,2loader处理
modules:true //开启样式模块化,只作用于局部。配合在index.scss中import style from './avartar.scss( import './avartar.scss'为全局作用)
}
}
'sass-loader' //2.将sass翻译成css
‘postcss-loader’ //1.在样式中增加浏览器厂商前缀,以适用于不同浏览器--------->PS:这个loader需要一个配置文件postcss.config.js
]
}
postcss.config.js
module.exports = {
plugins:[
require('autoprefixer')
]
}
3.打包字体(icon-font)篇
{
test: /\.(eot | ttf | svg)$/,
use:{
loader:'file-loader'
}
}
使用plugins让打包更便捷
plugin 可以在webpack运行到某个时刻的时候,帮你做一些事情,有点像vue中生命周期钩子
htmlWebpackPlugin
htmlWebpackPlugin 会在打包结束后,自动在dist目录下生成一个html文件,并把打包生成的js自动引入到这个html文件中。
npm install --save-dev html-webpack-plugin
webpack.config.js
var HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
plugins: [new HtmlWebpackPlugin({
template:'src/index.html' //建立一个模板进行生成
})]
}
cleanWebpackPlugin
该插件是个第三方插件
plugins:[new cleanWebpackPlugin(['dist'])] //当打包之前,使用该插件,帮助删除上次生成dist下的所有内容
Entry 与 Output 的基础配置
entry:{
main:'./src/index.js', //默认为main,这里添加key来对多个文件进行打包
sub:'./src/index,js'
},
output:{
publicPath:'http://cdn.com.cn', //打包后生成的js在引入html时自动添加前缀
filename:'[name].js', //利用占位符对两个文件进行打包,对应在dist目录下生成main.js及sub.js文件,由于使用htmlWebpackPlugin插件,两个js均会注入到html文件中
path:path.resolve(_dirname,'dist')
}
SourceMap的配置
module.exports={
mode:'development', //该模式下默认将SouceMap配置进去了
devtool:'none' //关闭SouceMap
devtool:'source-map' //dist下产生main.js.map映射文件
devtool:’inline-source-map' //无main.js.map文件,加上inline,映射文件(BASE64)写在main.js中,报错精确到行到字符
devtool:’cheap-inline-source-map' //同inline-source-map,但只精确到行,可以提升打包性能,且只管业务代码,不管第三方
devtool:’cheap-module-inline-source-map' //继承上面的特性,不只管业务代码错误,还管第三方,loader等错误
devtool:'eval' //无main.js.map文件,在main.js中不是以base64进行编码,而是代码--->路径,
比如eval("consele.log('hello world'),\n\n//#sourceURl=webpack......)
devtools:'cheap-module-eval-source-map' //开发环境下推荐该种方式
devtools:'cheap-module-source-map' //生产环境下推荐该种方式
}
sourceMap
现在知道dist目录下main.js文件96行出错
sourceMap 它是一个映射关系,他知道dist目录下main.js文件96实际上对应的是src目录下index.js文件中的第一行
当前其实是index.js中第一行代码出错了
使用WebpackDevServe提升开发效率
1.配置package.json
{
"scripts":{
"watch":"webpack --watch"
}
}
运行npm run watch,当源码src目录有变化时,自动重新打包,刷新页面为最新效果
2.配置webpack.config.js(最推荐)
npm install webpack-dev-server -D
webpack.config.js中
devServer:{
contentBase:'./dist', //起服务器的根路径
open:true //自动的打开浏览器运行
port:8080
}
package.json中
{
"scripts":{
"watch":"webpack --watch",
"start":"webpack-dev-server"
}
}
运行npm run start,服务起在localhost:8080,并且当要打包文件变化时,重新打包,浏览器自动刷新页面
且如果不用devServer,则项目是以file进行运行的,不能发送ajax请求
利用devServer打包不会生成dist目录,打包结果是在内存里的,提升打包速度
3.自己写devServer
npm intall express webpack-dev-middleware -D
与src及webpack.config.js同级下新建server.js
const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const config = require('./webpack.config.js');
//在node中直接使用webpack
const complier = webpack(config);
const app = express(); //起node服务器实例
app.use(webpackDevMiddleware(complier,{
publicPath:config.output.publicPath
}));
app.listen(3000,() => {
console.log('server is running');
});
package.json中
{
"scripts":{
"middleware":"node server.js"
}
}
Hot Module Replacement 热模块更新
css发生改变时
devServer:{
hot:true, //不刷新页面,只更新css
hotOnly:true, //即使HMP不生效,浏览器也不自动刷新
},
plugins:[new webpack.HotModuleReplacementPlugin()]
number.js发生改变时,index.js中
import number from './number';
if(module.hot){
module.hot.accept('./number',() => {
document.body.removeChild(document.getElementById('number'));
number();
})
}
css中不写这段js是因为,css-loader已经内置了。
使用Babel处理ES6语法
1.只写业务代码时要设置presets+引用babel/polyfill
module: {
rules: [
{ test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader" //打通webpack与babel桥梁
options:{
"presets": ["@babel/preset-env"] //包含ES6翻译成ES5的语法,会打包所有语法
}
}
]
}
上述配置后,有些函数浏览器还是不能识别,因此还要用,babel/polyfill
链接: babel/polyfill.
{
"presets": [
["@babel/preset-env", {
"targets": {
"chrome": "58", //项目运行在chrome版本大于58时,根据浏览器性质,翻译其不能识别的ES6
"ie": "11"
},
useBuiltIns:‘usage’ //只引用翻译业务代码用到的ES6语法,减小打包体积。
}]
]
}
2.引用/开发第三方类库时用babel/plugin-transform-runtime插件
使用该插件,避免全局污染
options:{
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"corejs": 2, //npm install --save @babel/runtime-corejs2
"helpers": true,
"regenerator": true,
"useESModules": false
}
]
]
}
由于options配置较多,可以新建.babelrc文件,将options对象写入,原配置文件就不用再写options了
{
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"corejs": 2,
"helpers": true,
"regenerator": true,
"useESModules": false
}
]
]
}
Tree Shaking
描述移除 JavaScript 上下文中的未引用代码,只适用于ES module(底层是静态),不支持CommonJS
开发环境
webpack.config.js中
{ mode:'development', //该模式下默认没有tree shaking功能
optimization:{
usedExports:true //开启tree shaking
}
}
package.json中
"sideEffects":false, //对所有的都tree shaking
//"sideEffects":['*.css','@babel/polly-fill'], //一般情况下css,babel/polly-fill都没有导出,但是需要使用,因此要配置css,babel/polly-fill不使用tree shaking
开发环境下还会保留未使用的代码,只会在打包生成的js中提示哪些使用了,在生产环境下则不保留未使用的函数。
生产环境中
不需要配置optimization,只需配置package.json文件下的sideEffects
Development和Production模式的区分打包
webpack.dev.js,webpack.prod.js
package.json
{
"scripts":{
"dev":"webpack-dev-server --config webpack.dev.js"
"build":"webpack --config webpack.prod.js"
}
}
新建一个webpack.common.js提取两个配置文件公共部分
安装
npm install webpack-merge -D
合并
Webpack 和 Code Splitting
代码分割,和webpack无关
同步代码
optimization:{
splitChunks:{
chunks:'all'
}
}
import _ from 'lodash';
//业务代码
异步代码(import)
无需做任何配置,会自动进行代码分割
function getComponent(){
return import('lodash').then(({default:_}) => {
var element = document.createElement('div');
element.innerHTML = _.join(['Dell','Lee'],'_');
return element;
})
}
getComponent().then(element => {
document.body.appendChild(element);
})
实验性语法,需要安装下面这个插件
npm install babel-plugin-dynamic-import-webpack --save-dev
在.babelrc中
plugins:["dynamic-import-webpack"]
SplitChunksPlugin配置参数
不论异步还是同步,要打包出来的文件名为lodash都要配置optimization
babel-plugin-dynamic-import-webpack是非官方插件,不支持magic comment,用
链接: link.
function getComponent(){
return import(/* webpackChunkName:"lodash" */ 'lodash').then(({default:_}) => {
var element = document,createElement('div');
element.innerHTML = _.join(['Dell','Lee'],'_');
return element;
})
}
optimization:{
splitChunks:{
chunks:'all',
cacheGroups:{
vendors:false,
default:false
}
}
}
默认设置
optimization: {
splitChunks: {
chunks: 'async', //只对异步代码进行分割(all,initial),
minSize: 30000, //大于30kb才进行分割
maxSize:50000, //一般不配置,会对引入的内容二次,多次分割
minRemainingSize: 0,
maxSize: 0,
minChunks: 1, //引入多少次才进行分割
maxAsyncRequests: 6, //只生成六个分割文件,一般用默认
maxInitialRequests: 4, //首页引入的模块数进行分割,最多是四个,一般用默认
automaticNameDelimiter: '~', //文件生成时名称连接符
automaticNameMaxLength: 30,
cacheGroups: { //与上述参数配合使用
vendors: {
test: /[\\/]node_modules[\\/]/, // 从node_modules引入的打包到vendors.js
priority: -10, //所有的引入都符合default,但要打包到vendor组时,需要配置该参数,值越大,优先级越高
filename:'vendors.js'
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true //已经被打包过的不需要再打包,直接用
}
}
}
}
Lazy Loading懒加载,chunk是什么
懒加载--------------- 当某一个时机时,利用import异步加载模块
打包生成的一个文件就叫一个chunk
打包分析,preloading,prefetching
分析: link
prefetching优化异步加载,当主要资源加载完毕,当网络空闲,再加载异步,提升访问速度,提高代码利用率
CSS文件的代码分割
打包生成的index.html只引入了main.js
entry:{
main:'./index.js'
}
output:{
filename:'[name].js', //entry
chunkFilename:'[name].chunk.js' //非入口文件,被main.js引入的间接js文件
path:path.resolve(_dirname,'../dist')
}
使用插件MiniCssExtractPlugin进行对css文件分割 链接 用在生产环境中(因为不支持HMR)
注意tree shaking影响,并且删除style.loader
optimize-css-assets-webpack-plugin可以压缩分割的代码
webpack与浏览器缓存
在生产环境中,文件名用contenthash占位符
output:{
filename:'[name].[contenthash].js',
chunkFilename:'[name].[contenthash].js'
}
内容改变,contenthash才改变,文件名才改变,浏览器由于文件名改变重新请求访问。文件名没有改变的用本地缓存。
老版本webpack还需配置optimization:
optimization:{
runtimeChunk:{
name:'runtime'
}
}
Shimming的作用
rules:[{
test:/\.js$/,
use:[{
loader:'imports-loader?this=>window' //让每个js文件的this替换成window
}]
}]
plugins:[
new webpack.ProvidePlugin({
$:'jquery', //见到$,自动引入jQuery
_join:['lodash','join'] //见到_join,代表lodash中join方法,自动引入
})
]
环境变量的使用方法
1.首先去掉在webpack.dev.js,webpack.prod.js的融合导出,即去掉融合
2.在webpack.common.js
将导出写成函数形式
const merge = require('webpack-merge');
const devConfig = require ('./webpack.dev.js')
const prodConfig = require ('./webpack.prod.js')
const commonConfig ={
entry:{
main:'./src/index.js'
},
........
}
module.export = (env) => {
if(env && env.production){ //若是开发环境
return merge(commonConfig,prodConfig);
}else{
return merge(commonConfig,devConfig);
}
}
package.json
"scripts":{
"dev-build":"webpack --config ./build/webpack.common,js" //不传参数,走dev
"dev":"webpack-dev-server --config ./build/webpack.common,js" //不传参数,走dev
"build":webpack --env.production --config ./build/webpack.common,js //传递参数env.production为true,走prod
}
Library的打包
index.js
import * as math from './math';
import * as string from './string'
export default {math,string}
module.exports = {
mode:'production',
entry: ' ./src/index.js '
output: {
path:path.resolve(_dirname,'dist'),
filename:'library.js'
libraryTarget:'umd' //支持各种形式引入库。ES Module,AMD,COMMON JS,不支持script标签引入
}
}
通过< script src=‘library.js’>< /script>引入库,以便可以使用library.math,需要再加一个配置
output:{
path:path.resolve(_dirname,'dist'),
filename:'library.js'
library:'library' //打包生成的文件挂载到全局页面变量上
// libraryTarget:'umd'
libraryTarget:this/window/global //与library:'library' 配合使用,访问this.library等,不过一般填umd,以保证可以以模块化及标签都可以引入
}
为了解决在开发library时引入了lodash,而用户不知道可能以
import _ from 'lodash';
import library from 'library'
方式重复引入lodash问题,需要再做以下配置
mode:'production';
externals:["lodash"]; //打包的时候忽略这些库,因此在用户使用时library时,需要先引入lodash,再引入library
externals还可以配置为一个对象
externals:{
lodash:{
commonjs:'lodash' //const lodash = require('lodash') lodash以commonjs方式加载时名字必须被叫做lodash
root:'_' //通过全局script标签引入时,lodash为被起名叫_的全局变量
}
}
上传至npm
1.在package.json中更该main为打包好的js文件
2.登录npm官网
3.npm adduser
4.npm publish
PWA的打包配置
将dist打包文件放在一台服务器上
npm install http-server --save-dev
package.json中
"scripts":{
"start" : "http-server dist" //线上的代码在一台服务器上启动
}
传统方式访问:当服务器挂掉页面访问不到
PWA:即使服务器挂掉,也可以利用缓存访问到页面
npm install workbox-webpack-plugin --save-dev //利用该插件实现PWA
只有上线的代码需要PWA,只改webpack.prod.js文件
new WorkboxPlugin.GenerateSW({
clientsClaim:true,
skipWaiting:true
})
打包生成precache-manifest,service-worker.js(缓存)文件,还要写业务代码
if('serviceWorker' in navigator){ //若浏览器支持serviceWorker
window.addEventListener('load',() => {
navigator.serviceWorker.register('/service-worker.js').then(
registration => { console.log('serviceWorker registed') } ).catch(
error => {console.log('serviceWorker register error') } )
})
}
使用WebpackDevServer实现请求转发
在开发的时候进行转发,线上没有devServer
devServer:{
proxy: {
‘/react/api’:'http://www.dell-lee.com' // 当访问本地/react/api路径下接口时,被转发到后面域名相对应的接口http://www.dell-lee.com/react/api/.....
‘/react/api’:{
target:'http://www.dell-lee.com',
secure:false, //对https转发
pathRewrite:{
'header.json' : 'demo.json' //访问/react/api/header.json被转发为http://www.dell-lee.com/react/api/demo.json
}
changeOrigin : true // 突破目的网站爬虫限制,一般配置上
headers: {
host:'www.dell-lee.com'
}
}
}
}
WebpackDevServer 解决单页面应用路由问题
devServer : {
historyApiFallback: true
}
将所有页面转到index.html下,利用打包生成的main.js实现路由跳转。
生产环境需要后端配置。
ESLint在Webpack中的配置
npm install eslint --save-dev
npx eslint --init
npx eslint src //校验src目录符不符合规范
ESLint.js
module.exports = {
"extend" : "airbnb" ,
"parser" : "babel-eslint" ,
"rules" : {
"react/prefer-stateless-function" : 0 //不遵循react/prefer-stateless-function规则
},
globals:{
document:fasle //不允许覆盖全局变量document
}
}
与webpack结合
modules:{
rules: [
test:/\.js$/,
exclude:/node_modules/,
use:['babel-loader',{
loader:‘'eslint-loader'’,
options : {
fix : true
}]
//先执行eslint-loader,再翻译,否则颠倒顺序要加force
(force:'pre')
]
devServer:{
//弹层形式报错
overlay:true
}
}
使用eslint-loader会降低打包速度,因此一般不建议使用。而是在提交之前利用git钩子eslint src
webpack的性能优化
1.跟上技术的迭代(Node,Npm,Yarn)
2. 在尽可能少的模块上应用Loader
test:/\.js$/
//只对src使用babel-loader
include : path.resolve(_dirname,'../src')
3.Plugin尽可能精简并确保可靠
4.resolve参数合理配置
业务代码中 import a from './a' //省略文件后缀
业务代码中 import a from './a/' //省略引入文件路径
业务代码中 import a from 'delllee' //路径别名
需要分别配置
resolve:{
//省略后缀,先找a.js,没有a.js找a.jsx
extensions:['.js',.'jsx']
//先找./a/index文件,没有找./a/child文件
mainFiles:['index','child']
//路径别名
alias:{
delllee : path.resolve(_dirname,'../src/a/b/c')
}
}
5.使用DllPlugin提高打包速度
不使用该插件时,import React from 'react’每次都要从node_modules取出模块,再分析打包。但库代码基本不会变,可以只打包一次存起来。这样再次import用的时候直接会去取打包好的文件,提高打包性能。
- 目标:第三方模块只打包一次
新建webpack.dll.js
const path = require('path');
const webpack= require('webpack');
module.exports = {
mode:'production',
entry : {
vendors:['react','react-dom','lodash'],
}
output:{
filename:'[name].dll.js',
path:path.resolve(_dirname,'../dll'),
//通过配置全局变量library,名称叫vendors暴露出来
library:'[name]'
}
}
package.json
//新建命令
"build:dll":"webpack --config ./build/webpack.dll.js"
运行生成vendors.dll.js文件
webpack.common.js
//安装额外插件,将生成的文件以script标签形式引入到html里(全局变量)。
npm install add-asset-html-webpack-plugin
plugins:[
new AddAssetHtmlWebpackPlugin({
filepath:path.resolve(_dirname,'../dll/vendors.dll.js')
})
]
- 我们引入第三方模块的时候,要去使用dll文件引入-----DllPlugin
在webpack.dll.js继续配置DllPlugin
const path = require('path');
module.exports = {
mode:'production',
entry : {
vendors:['react','react-dom','lodash'],
},
output:{
filename:'[name].dll.js',
path:path.resolve(_dirname,'../dll'),
library:'[name]'
},
plugins: [
//对暴露的文件进行分析,生成一个映射文件
new webpack.DllPlugin({
name:'[name]',
path:path.resolve(_dirname,'../dll/[name].manifest.json')
})
]
}
webpack.common.js
new webpack.DllReferencePlugin({
/*把刚才生成的映射文件引入进来,当import第三方模块时,会去找映射关系,
能找到就不用打包了,通过全局变量直接从vendors.dll.js拿过来用,找不到再从node_module*/
manifest:path.resolve(_dirname,'../dll/vendors.manifest.json')
})
利用node在webpack.common.js中动态化写DllReferencePlugin,AddAssetHtmlWebpackPlugin
//引入node核心模块
const fs = require('fs');
const plugins = [
new HtmlWebpackPlugin({
template:'src/index.html'
}),
new CleanWebpackPlugin(['dist'],{
root:path.resolve(_dirname,'../')
})
];
//读取该路径下而对文件
const files = fs.readdirSync(path.resolve(_dirname,'../dll'));
//对不同文件生成不同插件
files.forEach(file = > {
if(/.*\.dll.js/.test(file)){
plugins.push(new AddAssetHtmlWebpackPlugin({
filepath:path.resolve(_dirname,'../dll/',file)
}))
}
if(/.*\.manifest.json/.test(file)){
plugins.push(new webpack.DllReferencePlugin({
manifest:path.resolve(_dirname,'../dll/',file)
}))
}
})
module.exports={
//键值相同
plugins
}
6.控制包文件大小
7.thread-loader,paraller-webpack,happypack多进程打包
8.合理使用sourceMap
9.结合stats分析打包结果
10.开发环境内存编译
多应用打包配置
利用htmlwebpackplugin
webpack.common.js
entry:{
main:'./src/index.js',
list:'./src/list.js'
}
plugins: [
new HtmlWebpackPlugin({
template:'src/index.html',
filename:'index.html',
chunks:['runtime','vendors','main'] //只引入这些打包好的js
}),
new HtmlWebpackPlugin({
template:'src/index.html',
filename:'list.html',
chunks:['runtime','vendors','list']
})
]
自动化
configs.plugins = makePlugins(configs);
const makePlugins = (configs) => {
const plugins = [];
Object.keys(configs.entry).forEach(item => {
plugins.push(
new HtmlWebpackPlugin({
template:'src/index.html',
filename:`${item}.html`,
chunks:['runtime','vendors',item]
})
)
})
return plugins;
}