webpack 详解
- 1、webpack是什么
- 2、webpack初始化配置
- 3、webpack 开发环境的基本配置
- 3.1、webpack配置打包
- 3.2、webpack css 样式打包
- 3.3、webpack Html资源打包
- 3.4、webpack 图片资源打包
- 3.5、webpack 其他资源打包
- 4、devServer 热更新
- 5、webpack 生产环境的基本配置
- 5.1、将css提取为单独文件
- 5.2、css兼容性问题处理
- 5.3、css压缩
- 5.4、Eslint语法检查
- 5.5、JS兼容性处理
- 5.6、JS压缩
- 5.7、html压缩
- 6、性能优化
- 6.1、HMR代码热更新
- 6.2、Source-map
- 6.3、oneOf
- 6.4、缓存
- 6.4.1、babel缓存
- 6.4.2、文件资源缓存
- 6.5、tree shaking
- 6.6、代码分割 code split
- 6.6.1、多入口配置:
- 6.6.2、公共代码单独打包
- 6.7、懒加载和预加载
- 6.7.1、懒加载
- 6.7.2、预加载
- 6.8、PWA
- 6.9、多进程打包
- 6.10、externals
- 6.11、DLL
1、webpack是什么
webpack 是一个前端资源加载/打包工具。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。
从图中我们可以看出,Webpack 可以将多种静态资源 js、css、less 转换成一个静态文件,减少了页面的请求。
webpack中文文档:https://webpack.docschina.org/guides/getting-started/
2、webpack初始化配置
首先通过 npm init 命令对项目进行初始化。随后我们在项目当中下载webpack
使用命令:
npm install webpack webpack-cli -g
npm install webpack webpack-cli -D
在进行安装的时候出现了一些问题:
- 安装依赖失败:EPERM: operation not permitted,
这是因为在进行设置全局变量的时候可能使用的是管理员下的cmd,这里我们使用管理员打开cmd进行安装即可。 - Refusing to install package with name “webpack” under a package
这是因为在项目初始化的时候也是使用webpack作为项目名,导致了重名,我们只需要将pack.json当中的name进行修改掉即可。
在进行打包的时候,抛出了一个错误:webpack : 无法加载文件,是因为在此系统上禁止运行脚本。我们使用管理员权限打开我们的工具(Idea、webstrom、vscode、hbuilder)等等。
- 执行:get-ExecutionPolicy,显示Restricted,表示状态是禁止的
- 执行:set-ExecutionPolicy RemoteSigned
- 再执行get-ExecutionPolicy,就显示RemoteSigned
之后我们直接使用webpack进行打包测试:这里是使用webpack命令:我们的index.js文件就是入口文件,而后面指定的就是打包之后的路径地址。所以我们在src下面新建一个js文件,在js文件下面写入一些内容,之后进行打包:
webpack ./src/js/index.js ./build/ --node=development
进行打包之后我们可以在build下的main.js文件看到我们打包之后的内容:并且我们的webpack进行打包的时候我们可以对js、json文件进行打包处理,而对css/img无法编译通过。在这里我们给index.js文件进行使用js和json,之后进行打包,
/**
* webpack 起点文件
* */
/**
* 运行指令
* 开发环境
* webpack ./src/index.js -o ./build --mode=development
* 将 index.js 做为入口文件进行打包,打包到./build/main.js
* */
import data from './data.json'
console.log(data)
function add(a, b) {
return a + b
}
console.log(add(1, 5))
打包之后会得到main.js文件,得到js文件之后,我们添加一个html文件引入这个js文件,我们运行html文件,查看控制台输出结果。而前面我们都是使用的开发环境进行打包,这里还可以使用生产环境进行打包:
webpack ./src/js/index.js -o build/js/built.js --mode=production
而是用生产环境和开发环境进行打包有什么区别呢?使用生产环境进行打包就是在开发配置功能上多一个功能,压缩代码。
3、webpack 开发环境的基本配置
3.1、webpack配置打包
webpack.config.js 是 webpack 的配置文件。
作用: 指示 webpack 干哪些活(当你运行 webpack 指令时,会加载里面的配置)
我们添加一个webpack.config.js文件,在文件当中我们需要添加webpack的五个要素:也就是entry、output、loader、plugins、mode
/**
* 使用path的resolve进行拼接绝对路径
* */
const {resolve} = require('path')
module.exports={
// 入口
entry:'./src/js/index.js',
// 输出
output:{
// 输出文件名
filename:'main.js',
// 路径
path:resolve(__dirname,'build')
},
// loader
module:{
rules:[]
},
plugins:[],
// 模式 (开发、生产)
mode:'development'
}
打包出错:Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.
这个的话很简单,原本是rules,却写成了roles,头皮发麻(遇到这个报错仔细检查一下自己是否有写错的地方)。之后我们进行打包,这个时候我们已经可以进行打包成功了,之后我们同样的使用一个html文件,引入打包后的js文件,在浏览器当中查看效果。
3.2、webpack css 样式打包
我们首先添加一个css文件,文件内容先随便添加一点css样式进去,之后我们在入口文件当中进行引入样式文件。样式文件引入之后,直接执行webpack打包命令会报错,这是因为css文件打包我们还需要添加其他的配置才行。
我们进行css样式打包,我们需要安装css-loader和style-loader。直接执行命令进行安装即可。css-loader是允许在js中import一个css文件,会将css文件当成一个模块引入到js文件中。而style-loader能够在需要载入的html中创建一个标签,标签里的内容就是CSS内容。
npm install style-loader --save-dev
npm install css-loader --save-dev
之后我们在webpack.config.js文件当中添加loader和rules打包规则:
rules:[{
// 匹配哪些文件
test:/\.css$/,
// 使用哪些loader进行处理
use:[
// 从下到上进行执行
'style-loader',
'css-loader'
]
}]
添加好之后我们就可以对css样式文件进行打包啦。同样的我们这里不单单是存在css文件,有些时候我们还需要对less或者sass文件进行打包,这有如何处理呢?,我们只需要在rules当中添加less或者sass的打包规则即可。
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader'
]
}
之后我们再进行打包即可,当然了,我们这里还需要下载less-loader和less的依赖,直接执行命令进行安装就好。
npm install less --save-dev
npm install less-loader --save-dev
3.3、webpack Html资源打包
首先下载所需依赖:
npm i -D html-webpack-plugin
之后我们在配置文件当中引入这个组件,并且进行配置使用。这个插件默认会创建一个html文件,引入打包生成的所有资源。
const HtmlWebpackPlugin = require('html-webpack-plugin')
plugins: [
// 1、默认的html文件
// new HtmlWebpackPlugin(),
// 2、自定义内容
// new HtmlWebpackPlugin({
// title:"this is title"
// })
// 3、使用模板
new HtmlWebpackPlugin({
template:'./src/index.html'
})
],
我们可以看一下打包生成的html文件,如下,可以看到我们打包生成对应的js文件main.js会在html文件当中进行引入。
3.4、webpack 图片资源打包
首先下载所需依赖:
npm install url-loader --save-dev
npm install file-loader --save-dev
在这里我们可以不用配置任何相关图片资源的打包方式进行打包,在webpack5之后默认会对图片文件进行打包,但是我们在使用图片的时候,还是需要对图片进行处理的,比方说哪些图片就不进行打包了之间转成base64,而哪些需要进行打包,转成base64格式,可以减少请求的数量,降低服务器压力,但是他的缺点就是文件体积会变大,请求速度会变慢。
// 处理图片
{
test: /\.(jpg|png|gif)$/,
loader: 'url-loader',
options: {
// 文件大小限制,超过100kb的文件将会被打包,反之会被转化为base64格式
limit: 100 * 1024,
// 打包后文件的命名规则 原文件名+hash值+文件后缀名
// name: '[name][hash:16].[ext]',
esModule:false,
// 输出路径,相对于build
// outputPath: '/img'
},
type: 'javascript/auto',
},
这里对小于100kb的图片文件进行转码处理,可以看到这张图片就不会被打包出来,进行访问的时候也会通过base64格式进行访问获取.
而当我们直接在html文件当中通过image标签进行使用图片,进行打包之后会发现图片的路径地址不会指向打包之后的地址,这个如何处理呢?首先我们引入html-loader.
npm install html-loader --save-dev
添加配置:再次进行打包,可以发现image标签的指向地址页替换成打包之后的图片地址了。
// 处理html文件当中的图片
{
test: /\.html$/,
loader: 'html-loader'
}
3.5、webpack 其他资源打包
这里说到的其他资源指的就是除了前端常用的css、js、html这种,我们这里已图标为例进行打包,首先在iconfont上面下载一些图标的css和对应的字体等文件下来,我们进行导入css文件,
import icon from '../other/iconfont.css'
导入后在html文件当中通过class类名进行指定即可使用:
<span class="iconfont icon-zhangdan"></span>
<span class="iconfont icon-youxi"></span>
<span class="iconfont icon-yuanbao"></span>
<span class="iconfont icon-shoujichongzhi"></span>
而对应的webpack打包配置可以使用:
// 处理其他资源
{
exclude: /\.(css|js|html|less)$/,
loader: 'file-loader',
options:{
name:'[name].[ext]',
esModule:false,
},
type: 'javascript/auto',
}
4、devServer 热更新
在这里webpack提供了一个实时更新代码进行打包的工具,这里我们首先安装依赖:
npm i webpack-dev-server -D
依赖安装之后我们在配置文件当中加入配置:
devServer: {
contentBase: resolve(__dirname, 'build'),
compress: true,
port: 3000
}
而后我们通过npx webpack-dev-server
指令进行启动这个项目,
启动报错:[webpack-cli] Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
webpack版本原因,不支持这个contentBase属性,配置调整为:
devServer: {
// contentBase: resolve(__dirname, 'build'),
static: resolve(__dirname, 'build'),
compress: true,
port: 3000
}
5、webpack 生产环境的基本配置
5.1、将css提取为单独文件
首先我们安装开发环境的webpack配置进行构建一个配置文件,在前面我们使用开发环境对css文件进行打包,可以看到并没有css文件输出,这是因为使用了style-loader会将css样式转成link标签的格式进行引入,对应的css就被打包到了js文件当中,而我们想将css文件单独进行打包输出该如何做呢?
首先我们导入依赖:
npm install --save-dev mini-css-extract-plugin
这是一个插件,对于前面使用到的HtmlWebpackPlugin的使用是一样的,首先在配置文件当中导入,之后进行实例化。这里我们可以直接new创建,也可以传递参数,下面代码表示的是css文件单独打包提取之后的路径。
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
plugins: [
// new MiniCssExtractPlugin()
new MiniCssExtractPlugin({
filename:'css/built.css'
})
],
并且,在前面对css打包使用的style-loader也不能使用了,改成这个插件的loader进行打包即可。
rules: [{
// 匹配哪些文件
test: /\.css$/,
// 使用哪些loader进行处理
use: [
// 从下到上进行执行
// "style-loader",
MiniCssExtractPlugin.loader,
"css-loader",
],
}]
5.2、css兼容性问题处理
对于css样式在不同的浏览器不同的版本下会存在一些兼容性的问题,
npm install --save-dev postcss-loader postcss-preset-env
修改配置:
rules: [{
// 匹配哪些文件
test: /\.css$/,
// 使用哪些loader进行处理
use: [
// 从下到上进行执行
// "style-loader",
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [['postcss-preset-env',{}]]
}
}
}
],
}]
往下我们在package.json文件当中可以对开发环境、生产环境下的浏览器兼容进行配置。
"browserslist": {
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
"production": [
">0.2%",
"not dead",
"not op_mini all"
]
}
在这里我们进行打包,默认会使用生产环境下的对应兼容性处理,而要使用开发环境下的兼容处理,我们只需要指定node的环境变量,如下代码:
process.env.NODE_ENV = 'development'
我们使用生产环境进行兼容性处理,在css当中对应flex定位等样式会存在兼容性问题,我们在css当中加入:
display: flex;
backface-visibility: hidden;
而后进行打包,可以看到对该样式做了兼容性处理
display: flex;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
5.3、css压缩
在对css样式代码进行压缩的时候我们需要使用到一个插件,先对插件进行安装:
npm install --save-dev optimize-css-assets-webpack-plugin
而对于插件的使用基本上都是大同小异,首先将插件引入,引入之后在plugins里面直接new创建对象即可。
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin' )
plugins: [
new OptimizeCssAssetsWebpackPlugin()
]
5.4、Eslint语法检查
首先我们安装eslint相关依赖:
npm install --save-dev eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import
5.5、JS兼容性处理
在使用babel可以对js的代码进行降级也就是对后续的高级的js代码进行降级处理,方便对低版本的浏览器做兼容,首先我们引入babel相关包。
npm install --save-dev babel-loader @babel/core @babel/preset-env @babel/polyfill core-js
这个时候我们添加js代码,可以添加一个const或者箭头函数,对应的我们在配置当中加入配置:这个时候进行编译可以看到在编译后的js代码当中都进行了降级处理。
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
options: {
presets: ['@babel/preset-env']
}
}
但是对于一些高阶的函数对象等是无法进行兼容的,我们在js代码当中加入一个promise对象,拿到这个对象我们使用上面的配置进行编译打包。看到promise对象是不会被转义的,这个时候我们添加一个依赖。
npm install --save-dev @babel/polyfill
而后直接在js代码当中导入这个polyfill的js库。
import '@babel/polyfill'
这样的解决方式是全部的浏览器都进行了兼容处理,所以通过该方式打包之后的js代码也会格外的大,那么我们还可以进行部分适配兼容,添加core-js依赖。
npm install --save-dev core-js
之后我们修改配置如下:这样就做到了对部分浏览器兼容,也大大的减小了打包后的js文件的大小
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
options: {
// 预设:指示 babel 做怎么样的兼容性处理
presets: [
[
"@babel/preset-env",
{
// 按需加载
useBuiltIns: "usage",
// 指定 core-js 版本
corejs: {
version: 3,
},
// 指定兼容性做到哪个版本浏览器
targets: {
chrome: "60",
firefox: "60",
ie: "9",
safari: "10",
edge: "17",
},
},
],
],
},
5.6、JS压缩
在生产环境下会默认对js代码进行压缩,所以我们只需要切换mode选项为生产环境即可。
mode:'production'
5.7、html压缩
这个我们只需要在前面设置html模板的插件来进行压缩即可,修改对应配置:
plugins: [
new HtmlWebpackPlugin({
template: "./src/html/index-pro.html",
minify: {
// 去掉空格、换行
collapseWhitespace: true,
// 去掉注释
removeComments: true
}
}),
],
6、性能优化
6.1、HMR代码热更新
在进行热更新启动项目的时候,当修改一个文件的代码,会对整个项目下的全部代码进行打包,这大大的降低了开发调试的效率,所以就有了HMR单独更新修改的文件,热更新的配置,在原有的基础上加上hot属性:
devServer: {
// contentBase: resolve(__dirname, 'build'),
static: resolve(__dirname, 'build'),
compress: true,
port: 3000,
hot: true
}
这个时候由于是使用style-loader来进行处理css样式的,该loader已经实现了HMR功能,所以这个时候当我们修改样式文件之后,对应的js代码并不会进行重新加载,
log.js:16 [HMR] - ./src/css/image.css
log.js:24 [HMR] - ./node_modules/css-loader/dist/cjs.js!./src/css/image.css
其次对于html文件来说,我们并不需要对其进行热更新,在开发当中我们往往会打包一个主页面也就是对应的html文件,而当html文件修改后该页面必然要进行更新,其对应的js等代码也需要进行更新,在这里我们只需要在打包的入口上加上这个html文件即可。
entry: ["./src/js/index.js", "./src/html/index.html"],
6.2、Source-map
当我们在终端中运行npm run dev时,如果代码出现问题报错时, 我们通过控制台看到的错误是在代码压缩后的,而不是源代码的错误。当在源代码中故意写错console,然后运行后报错,但是这个报错行数显示的是编译后的代码,所以就会出现错误行数不匹配的结果,所以我们引出Source Map概念。
Source Map就是一个信息文件,里面存储着位置信息,也就是说Source Map文件中存储着压缩、混淆后的代码,所对应的转换前的位置,有了它,代码出错的时候,除错工具将直接显示原始代码的错误行数,而不是转换后的代码,能够极大的方便后期的调试。
Source-map的使用只需要在配置文件当中加入:
devtool: 'source-map'
6.3、oneOf
正常来讲,所有文件在执行的时候,都要将loader中的rules过一遍,如果符合,就被对应loader处理,不符合则直接过。这样对性能不好,为了解决这个问题,使用ondeof。
作用:提升构建速度,避免每个文件都被所有loader过一遍,因为任何一个文件,构建过程中,在遇到第一个与之对应的loader后,不会再往下进行。oneOf里面的loader只匹配一个。不能有两个配置处理同一种类型的文件,比方说两个Loader,一个eslint,一个babel,他们都处理Js文件,那只会第一个生效,第二个不起作用。
oneof的格式是一个数组,数组当中放loader的配置。
6.4、缓存
6.4.1、babel缓存
代码里面最多的就是js文件,标签结构或者样式文件较少(即使多也没办法处理)
babel可以对我们写的代码进行编译处理,处理成浏览器可以识别的语法,即JS的兼容性处理。
比如有100个js模块,其中有一个JS模块有变化修改,其他99个模块没有,那么不可能因为这一个JS 模块变化了,就把全部100个JS模块重新打包。
这个时候开启babel缓存,先把100个JS模块缓存,第二次构建时,没有变化的JS模块就直接启用缓存。
并且在这个时候我们使用nodejs构建一个服务器向外暴露端口来进行访问我们打包之后的文件,并且将文件进行缓存。
const express = require('express')
const app = express()
app.use(express.static('build', {
maxAge: 1000 * 3600
}))
app.listen(3000)
之后直接通过node进行启动这个服务,访问3000端口,可以看到在刷新第二次的时候会从缓存当中获取css和js文件。这样就大幅度的减少了对服务器的请求,加快了页面的响应速度
6.4.2、文件资源缓存
但是这样也会存在一个问题,当我们的js和css代码发生改变之后并不会访问服务器获取最新的代码进行渲染,这又该如何处理呢?
这个时候我们只需要对修改后的文件的文件名进行处理即可,每次打包之后的文件名使用hash来进行命名, 这样请求的文件不一样就不会从缓存当中获取了。
/**
* 以下为js输出地址、css同理
*/
output: {
filename: "main.[hash:10].js",
},
但是这样的话,每当重新打包后生成的文件名都不一样,都走不了缓存,而当只改了一个文件,重新打包后所有文件都会被进行重新获取,就大大的浪费了时间跟资源。所以就引入了contenthash:根据文件的内容生成hash值,不同文件hash值一定不一样
6.5、tree shaking
基于 ES6 的静态引用,tree shaking 通过扫描所有 ES6 的 export,找出被 import 的内容并添加到最终代码中。 webpack 的实现是把所有 import 标记为有使用/无使用两种,在后续压缩时进行区别处理。简单来说就是去除没有使用的代码,如下我们新加一个js文件,采用es6进行向外暴露
export function add(x, y) {
return x + y
}
export function reduce(x, y) {
return x - y
}
而后当我们在入口js当中只引用了一个方法,这个时候再进行打包,就会去除掉未使用的方法,如下
// 入口文件代码
import {
add
} from "./tree-shaking";
console.log(add(1, 2));
// 打包后代码
!function(){"use strict";console.log(3)}();
6.6、代码分割 code split
webpack会将所有依赖的文件打包到一个文件中,即bundle.js文件,当一个项目慢慢变得复杂的时候会导致这个bundle.js文件越来越大,浏览器加载的速度也会越来越慢,可以使用代码分割来将不同代码单独打包成不同文件。
- 改为多文件入口
- 通过optimization将公共代码单独打包
6.6.1、多入口配置:
添加配置:这样就会对多个js文件就会进行分别打包,
entry: {
indexPro: "./src/js/index-pro.js",
indexProTest: "./src/js/index-pro-test.js"
},
6.6.2、公共代码单独打包
首先对js代码引入一个第三方库axios;这样进行打包
import {
reduce
} from "./tree-shaking";
import axios from 'axios'
console.log(reduce(1, 2));
console.log(axios)
这里进行打包之后axios的源码也会被打包到这个js文件当中,这就需要对这种进行抽离出来,我们只需加上配置
optimization: {
splitChunks: {
chunks: 'all'
}
},
6.7、懒加载和预加载
6.7.1、懒加载
懒加载:当代码进行使用的时候才开始加载对应资源:
如下:首先在html当中定义一个按钮,之后在入口文件当中给按钮绑定一个单击事件,这种情况下,当页面初始化加载的时候并不会加载dom.js这个文件资源,只有当按钮点击之后才会加载dom.js文件。
console.log("index-pro loading...")
document.getElementById('btn').onclick = function () {
import( /*webpackChunkName:'dom'*/ './dom').then((data) => {
console.log(data)
})
}
6.7.2、预加载
预加载:会在使用之前加载js等文件资源,正常加载是同时并发的加载对应的资源,而预加载会在使用的资源加载完毕之后,在浏览器空闲的时候再加载后续资源。但是也有缺陷:浏览器兼容性
document.getElementById('btn').onclick = function () {
import( /*webpackChunkName:'dom',webpackPrefetch:true*/ './dom').then((data) => {
console.log(data)
})
}
6.8、PWA
PWA::渐进式网络开发应用程序(离线可访问)
在进行使用的时候需要下载依赖:
npm install --save-dev workbox-webpack-plugin
而后在配置文件当中的插件下加入配置:
new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true,
skipWaiting: true
})
最后只需要在入口文件当中进行判断要不要使用这个PWA技术即可:
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('./service-worker.js').then(() => {
console.log("success")
}).catch(() => {
console.log("error")
})
})
}
同样的,打包之后的代码需要运行在服务器之内,使用前面提到的server.js那个文件,通过express库构建一个服务器。最后我们访问暴露的端口,并且切换到offinline模式下或者切断网络,进行测试:
6.9、多进程打包
首先下载多进程打包依赖
npm install --save-dev thread-loader
对于多进程打包,只需要将对应的loader加在要打包的loader上即可。之后进行webpack打包就会变为多进程打包
6.10、externals
externals:防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies)。
这里在js代码当中直接导入axios库,这样进行直接打包,第三方库就会被打包到对应的那个js文件当中,这样显然是不友好的,所以我们可以在这里排除对axios的打包
externals: {
// 拒绝 axios 被打包进来
axios: 'axios'
}
而在入口html文件当中加上axios的cdn进行外连接过来即可
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
6.11、DLL
- 什么是DLL
- DLL全称是动态链接库(Dynamic Link Library),是为软件在Windows中实现共享函数库的一种实现方式;
- 那么webpack中也有内置DLL的功能,它指的是可以将可以共享,并且不经常改变的代码,抽取成一个共享的库;
- 这个库在之后编译的过程中,会被引入到其他项目的代码中,减少的打包的时间;
首先对于ddl对第三方库进行打包,指定哪些第三方库进行额外打包
// 第三方库打包
entry: {
indexPro: "./src/js/index-pro.js",
axios: ['axios']
},
// 输出
output: {
// dll 打包
filename: '[name].js',
path: resolve(__dirname, 'dll'),
library: '[name]_[hash]'
},
并且指定打包后的关系
// 打包生成一个映射关系
new webpack.DllPlugin({
name: '[name]_[hash]',
path: resolve(__dirname, 'dll/mainifest.json'),
}),
这样之后就可以看到会单独给axios打一个包。但是这样打包之后的文件如何使用呢?这个时候就需要新增依赖。
npm i add-asset-html-webpack-plugin -D
用于指定第三方库打包后的存放位置
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');
new AddAssetHtmlWebpackPlugin({
filepath: resolve(__dirname, 'dll/axios.js')
})