打包工具-webpack
简介
webpack 是前端一款高效打包工具,它能把一个庞大的工程打包压缩,甚至体积能达到仅仅几kb,webpack是前端或不可缺的一环
环境搭建
既然是前端项目,那么就npm就必不可少
运行 npm install webpack-cli -g
来全局安装脚手架
随后使用 npm install webpack-cli -D
安装到工程下
在工程目录下创建 webpack.config.js (文件名固定) 来作为webpack的配置文件,所有有关webpack的配置都写在此文件中,其中的内容通过es5语法暴露出去
五个核心配置
webpack 五个核心配置是
- entry 入口文件
- output 输出
- module loader配置
- plugins 插件
- mode 打包模式
其结构如下下面详细聊聊这五个配置1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17module.exports = {
//入口起点
entry:
//输出
output:{
},
module:{
},
plugins:[
],//插件配置
mode:'development',
//mode:'production'
}
entry
入口文件,指示webpack 从哪个文件开始打包,这个入口文件所引用导入的文件都会参与打包
output
输出文件,指示webpack将打包好的文件输出到哪里
其中需要在顶部导入js的内置模块path
webpack 默认只能打包js/json资源,所以当我们想要打包其他资源是,则需要借助loader
module
module主要作用是配置loader,而每一个loader都作为一个对象,存在rules数组中。 loader是webpack最重要的一环,只有配置了各种loader webpack才能打包各种各样的资源,其中各种loader通过npm 下载即可
打包资源
打包css资源(需要下载css-loader,style-loader)
1
2
3
4
5
6
7
8
9
10
11
12
13{
//正则表达式 表示匹配哪些文件
test:/\.css$/,
use:[//use为一个数组,将loader按从下至上顺序执行
//创建一个style标签 将js中的样式添加到页面中生效
'style-loader',
//将css文件 以字符串的形式变成一个commjs模块加载到js
'css-loader',
]
}打包less资源(需要下载style-loader,css-loader,less-loader)
1
2
3
4
5
6
7
8
9
10
11
12
13
14{
test:/\.less$/,//每一种匹配规则 只适用与一种文件
use:[
//创建style标签 将js中的样式添加到页面中
'style-loader',
//将css文件 编译成commjs模块加载到js
'css-loader',
//将less文件编译成css文件
'less-loader'
]
},将css单独打包成一个文件(单独下载mini-css-extract-plugin)
首先new一个对象
const MiniCssExtracetPlugin = requir('mini-css-extract-plugin')
调用插件对象
1
2
3new MiniCssExtracetPlugin({
filename:'css/built.css'//对输出文件进行重命名
})修改loader信息
1
2
3
4
5
6
7
8{
test:/\.css/,
use:[
//'style-loader',//创建style标签,将样式放上去
MiniCssExtracetPlugin.loader,//取代style-loader 提取js中的css为单独文件
'css-loader'//将css文件整合到js中
]
}
打包img资源(1)(需要下载url-loader,file-loader)
由于图片数量在实际开发中会很多,在打包过程中就会拖慢打包速度,所以我们需要使用 options来修改loader的一些参数1
2
3
4
5
6
7
8
9
10
11
12
13//当只使用了一个loader时,则可以不使用use数组
loader:'url-loader',
options:{
limit:8 * 1024,
//图片大小小于8kb(项目中较小的图片) 就会被base64编码方式处理
//优点:减少请求数量 (减轻服务器压力)
//缺点:图片体积会更大(请求速度更慢)
name: '[hash:10].[ext]'
//文件名取哈希值前十位加上文件原拓展名
}
},打包img资源(2)(需要下载html-loader)
上面那种处理方式只能处理 html引用的css文件中引入的图片,不能处理html页面中引入的图片。解决方法是使用html-loader
但是 url-loader是使用es6model去解析,而html-loader是使用commjs去解析, 为了避免冲突我们需要关闭url-loader的es6Module 改用commjs解析(在option中加入esModule:false)1
2
3
4
5{
//使用html-loader
test:/\.html$/,
loader:'html-loader'
}1
2
3
4
5
6
7options:{
limit:8 * 1024,
name: '[hash:10].[ext]'
//在url-loader中关闭es6Module
esModule:false
}打包html资源(需要下载适用于html的plugin插件,
html-webpack-plugin -D
)在顶部引入
const HtmlWbpackPlugin = requi('html-webpack-plugin');
随后在plugins列表中new一个对象,其中的template属性,将作为结构模板。
1
2
3
4
5
6plugins:[
new HtmlWbpackPlugin({
template:'./src/index.html'
})
],兼容性处理
兼容css(需要下载postcss-loader,postcss-preset-env)
随着css版本的更新迭代,相对于应的兼容性问题也层出不穷,webpack也提供了css兼容性的解决方案修改loader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19{
test:/\.css/,
use:[
MiniCssExtracetPlugin.loader,
'css-loader',
//第一种 使用loader的默认配置 修改loader配置
//帮postcss找到package.json中browserslist的配置,通过指定配置加载兼容性样式
{
loader:'postcss-loader',
options:{
ident:'postcss',
plugins:()=>{
require('postcss-preset-env')
}
}
}
]
}在package.json 中添加支持的browserlist
1
2
3
4
5
6
7
8
9
10
11
12
13"browserslist": {
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
//兼容最近一个版本的谷歌火狐索菲亚浏览器
],
"production": [
">0.2%",//兼容99.8%的浏览器
"not dead",//不兼容已经死掉的浏览器
"not op_mini all"//不兼容op_mini
]
},
postcss 默认使用生产环境 如需使用开发环境则需要手动配置nodejs 中的临时环境变量,在webpack.config.js 顶部添加process.env.NODE_ENV = 'development'
如抛错 ValidationError: Invalid options object. PostCSS Loader has been initialized using an options object that does not match the API schema. 则说明 此插件版本不支持在webpack.config.js中进行配合
需要在项目根目录下 创建 postcss.config.js 添加如下代码
module.exports = { plugins:[ require('postcss-preset-env')() ] }
然后在webpack.config.js 中删除post-loader的额外配置
1 | { |
2. 兼容js(1)(需要下载babel-loader,@babel/core,@babel/preset-env)
1 | { |
这种方法只能转换基本语法,promise等不能转换
如需要兼容所有js(需要下载@babel/polyfill),在入口文件中引入import '@babel/polyfill'
,这种方法会将所有js兼容性都包括,所以打包后会非常大
3. 压缩处理
压缩js html
在修改mode属性为 production生成模式删除html中无用的内容
1
2
3
4
5
6
7
8
9
10new HtmlWbpackPlugin({
template:'./index.html',
minify:{
//移除空格
collapseWhitespace:true,
//移除注释
removeComments:true
}
})压缩css(需要下载optimize-css-assets-webpack-plugin插件),并在插件列表中使用
1
2
3plugins:[
new OptimizeCssAssetsWebpackPlugin()
],性能调优
HMR
HMR:hot module replacement 热模块替换
当某一个模块发生变化时 只会重新加载变化的模块 其他模块不会被加载
在webpack.config.js 结尾处添加
1 | devServer:{ |
js默认不能使用hmr,如需要,在入口文件添加监听即可
1 | if(module.hot){ |
html默认不能使用hmr 而且会导致html文件不能热更新
在入口文件 加上html文件即可(通常不需要hmr功能)
source-map映射
在源代码和构建后代码之间形成映射,当构建后代码出错时,可以映射到源代码
在webpack.config.js 末端添加devtool属性即可属性值及功能如下
1 | 开发环境下使用:eval-source-map(调试好) || eval-cheap-module-source-map(速度快) |
oneOfLoader
当使用oneOf后 当文件命中loader就会停止 不会接着继续判断 提高效率
将所有loader对象放入oneOf数组即可
1
2
3
4
5
6
7
8
9
10
11
module: {
rules: [
{
oneOf: [
{},
{},
{}
]
}
]
},
treeShaking
去除无用代码 减少打包体积
前提:es6module productionEnv
问题:会把一些文件干掉 如css babel(直接引用,没有使用)
在packge.json 中 添加配置sideEffects 以排除相应文件
1 | "sideEffects": [ |
codeSplit
将打包后的文件拆分成多个文件 可以实现并行加载/按需加载
- 多个入口 多个出口 每一个出口文件都对应一个入口文件
1 | entry:{ |
- 添加 属性 将node_modules 中的文件 单独打包成一个chunk,如果是多入口 会将里面公用的modules 单独打包,在配置文件中添加配置
1 | optimization:{ |
lazyLoading
只有当需要模块的时候 才去加载,加载完成之后 再次调用会使用缓存
pwa
渐进式网络开发应用程序(离线访问) (需要下载 workbox-webpack-plugin 并导入其GenerateSW方法)
在配置文件plugins中使用插件
1 | new GenerateSW({ |
随后在入口文件中 注册service-worker
1 | //注册serciceworker |
externals
忽略打包
如果有包通过标签引入了 可以设置不被打包
在配置文件中添加
1 | //忽略包名 不被打包 |
完整通用版本
生产版
1 | const { resolve } = require('path'); |
开发版
1 | const { resolve } = require('path'); |