为什么需要打包工具?
- 代码编译:React/Vue框架、ES6模块化语法、Less/Sass等css预处理器
- 代码压缩:减小包大小
- 兼容性处理:ES5兼容,浏览器兼容等
- 提升代码性能:分包加载
- ...
有哪些打包工具?
- Gulp
- Grunt
- Webpack
- Rollup
- Vite
- Esbuild
- ...
Demo使用
- 安装webpack webpack-cli
- 可以npx直接在命令行启动,或者在package.json中配置命令(调用node_modules中.bin目录)
- 直接在index.html中引用es6代码是不行的,需要通过webpack转换(或者script使用type=module)
- js文件后缀是webpack处理的,script引用时需要完整路径
npx webpack ./src/main.js -mode=development
注意development模式下,只编译了es6模块化语法,但是箭头函数、展开操作符...并未编译,且代码未压缩; 默认打包到dist目录
npx webpack ./src/main.js -mode=production
production模式下,es6模块化语法、箭头函数、展开操作符...并未编译,且代码已压缩;
且打包后的文件使用的匿名函数进行包裹,避免命名冲突
(()=>{"use strict";console.log(3),console.log([1,2,3,4].reduce(((o,e)=>o+e),0))})();
5大概念
- 入口:webpack构建模块依赖图的起点
- 输出:打包后资源的输出位置
- loader: webpack默认只能识别js和json文件,对于其他类型的文件,需要通过loader进行转换webpack可处理的模块,进行后续处理。loader执行顺序为从右向左依次执行
- plugins: 用于执行范围更广的任务,如打包优化,资源管理,注入环境变量
- 模式:开发模式和生产模式
使用配置文件
npx webpack --config webpack.config.js- 配置文件是在nodejs环境运行的,使用module.exports导出
开发环境自动化:监听文件的更改并重新打包。需要注意的是devServer的打包资源是运行在内存中的,并没有打包到当前目录。
devServer: {
host: 'localhost',
port: 3000,
open: true
},
处理css
- css-loader可以将css提取到commonjs模块
- style-loader 可以将模块中的css通过style标签注入到html
- less-loader 将less转为css
- sass-loader 将sass, scss转为css
- mini-css-extract-plugin插件 将style中css单独提取成css文件中(用于替代style-loader)
- postcss css样式兼容处理(package.json中的browserslist字段用于指明浏览器兼容范围)
- css-minimizer-webpack-plugin css压缩
rules: [
{
test: /\.css$/i,
// use: ['style-loader', 'css-loader']
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
{
test: /\.less$/i,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: ['postcss-preset-env'], // 兼容性问题处理
},
},
},
'less-loader',
],
},
{
test: /\.s[ac]ss$/i,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: ['postcss-preset-env'], // 兼容性问题处理
},
},
},
'sass-loader',
],
},
]
plugins: [
// 提取css成单独文件
new MiniCssExtractPlugin({
// 定义输出文件名和目录
filename: "static/css/main.css",
}),
],
optimization: {
// css压缩
minimizer: [new CssMinimizerPlugin()]
},
处理图片
webpack内置可处理,
-
Rule.parser.dataUrlCondition.maxSize可以配置资源大小,当资源小于该值时,使用base64编码,减少服务器请求(注意当图片较大时,转化成base64的成本也会更高,如200kb -> 400kb,得不偿失) -
generator可以修改文件输出的目录,避免打包后的资源文件夹混乱
-
hash:10 去哈希值的前10位即可,避免文件名称太长
{
test: /.(png|jpe?g|webp|gif|svg)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10 * 1024 // 10kb
}
},
generator: {
filename: 'static/[hash:10][ext][query]'
}
}
处理字体资源
asset/resource类型资源不会转化为base64,保持文件原样输出
@font-face {
font-family: "iconfont"; /* Project id 3375413 */
src: url('../assets/fonts/iconfont.woff2') format('woff2'),
url('../assets/fonts/iconfont.woff') format('woff'),
url('../assets/fonts/iconfont.ttf') format('truetype');
}
{
test: /.(ttf|woff2?)$/i,
type: 'asset/resource',
generator: {
filename: 'static/fonts/[hash:10][ext][query]' // 指定字体资源输出目录
}
}
js资源处理
-
生产模式默认已压缩
-
Eslint
- 可以单独在.eslintrc.js文件中配置,也可以在package.json的eslintConfig中配置(eslintrc中的优先级高于package.json)
- eslintrc可以跨层级配置,子目录的eslint是根目录eslintrc和子目录的eslintrc的组合,发生冲突时,以子目录为准
- package.json的eslint配置也是全目录生效的
- 配置webpack的eslint插件,在打包时可以监控eslint错误,打包失败
const ESLintWebpackPlugin = require('eslint-webpack-plugin')
plugins: [
new ESLintWebpackPlugin({
// eslint检查目录
contenxt: path.resolve(__dirname, 'src')
})
],
- babel
- 将ES6语法转化为向后兼容的js语法,以便在旧版本浏览器中运行
- 可以单独写在babel配置文件中,或者写在webpack.config.js、package.json中
module.exports = {
presets: ['@babel/preset-env'],
// 支持 ?. 和 ??
plugins: ['@babel/plugin-proposal-optional-chaining', '@babel/plugin-proposal-nullish-coalescing-operator']
}
{
test: /.m?js$/i,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader'
// use: {
// loader: 'babel-loader',
// options: {
// presets: ['@babel/preset-env']
// }
// }
}
html资源处理
自动生成html文件,并将打包后的文件自动注入;生产模式默认已压缩
const HtmlWebpackPlugin = require('html-webpack-plugin')
plugins: [
new HtmlWebpackPlugin({
// 指定html模板,否则使用默认模板
template: path.resolve(__dirname, 'public/index.html')
})
],