概念
本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler) 。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph) ,其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
本篇文章不会讲babel,loader,plugins这些是什么,建议对核心的几个概念不清晰的可以移步官网,因为官网讲的已经很清晰了,我们不做搬运工。
起步
首先我们创建一个目录,初始化 npm,然后 在本地安装 webpack,接着安装 webpack-cli(此工具用于在命令行中运行 webpack)
mkdir webpack-demo && cd webpack-demo
npm init -y
npm install webpack webpack-cli --save-dev
这里我们可以跟着官网快速搭建一个项目
基本配置
1. 拆分配置和merge
一般我们可以将webpack配置文件一分为三,common(通用配置),dev(本地配置),prod(生产环境配置),如下图。
通过安装 webpack-merge 插件merge通用配置,这样做就不会产生冗余的代码,利于维护,关键代码如下:
const { merge } = require("webpack-merge");
const conmmonConfig = require("./webpack.common");
module.exports = merge(conmmonConfig,{
mode: "development",
module: {}
});
创建完配置文件后,别忘了在package.json中引用该配置。
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --config webpack/webpack.dev.js",
"build": "webpack --config webpack/webpack.prod.js"
},
2. 启动本地服务
在webpack.dev.js中配置本地服务器,具体代码如下。
/**配置本地服务器 */
devServer: {
port: 8080,
compress: true, // 显示打包进度条
// contentBase: distPath, // 根目录
open: true, // 自动打开浏览器
compress: true, // 启动 gzip压缩
proxy: {
// 本地代理
"/api": "http: //localhost:3000",
},
},
以上配置在日常简单开发基本够用,更多配置参数可以移步
3. 处理ES6
- 在根目录下新建.babelrc.js
- 安装@babel/preset-env(yarn add @babel/preset-env --dev)
- 在babelrc.js 新增如下配置
module.exports = {
presets: [
["@babel/preset-env"],
],
};
4. 处理样式
样式文件只需要交给loader处理就好。
- css-loader: 解析.css文件 支持 import './xxx.css'
- style-loader: 将含有 CSS 字符串的 style 标签,将被插入到 html 文件的 head 中。
- postcss-loader: css兼容性 增加前缀
- sass-loader,less-loader: 解析sass/less -> css
module.exports = {
module: {
rules:[
{
test: /\.s[ac]ss$/i,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.css$/,
use: ["style-loader", "css-loader", "postcss-loader"],
},
]
}
}
注意:loader执行顺序 从后往前,更多webpack loader可以移步
5. 处理图片
使用file-loader和url-loader处理图片,在本地环境我们可以file-loader 处理图片(直接引入图片url) 可以轻松地将图片混合到 CSS 中
module.exports = {
module: {
rules:[
{
test: /\.(png|svg|jpg|gif)$/,
use: ["file-loader"],
},
]
}
}
生产环境当图片小于5kb的图片可以用base64格式产出,减小资源请求。
module.exports = {
module: {
rules:[
test: /\.(png|jpg|jpeg|gif)$/,
use: {
loader: "url-loader",
options: {
/**小于5kb的图片用base64格式 产出
* 否则依然用file-loader产出url格式
*/
limit: 5 * 1024,
/**打包到img目录 */
outputPath: "/img/",
},
},
]
}
}
高级配置
1.多入口
- 在common中将entry(入口)修改为如下
entry: {
index: path.join(srcPath, "index.js"),
print: path.join(srcPath, "print.js"),
},
plugins: [
/*多出口 */
new HtmlWebpackPlugin({
template: path.join(srcPath, "index.html"),
filename: "index.html",
// 表示该页面要引用哪些chunk vendor-第三方插件代码分割 common-公共模块
chunks: ["index", "vendor", "common"],
}),
new HtmlWebpackPlugin({
template: path.join(srcPath, "print.html"),
filename: "print.html",
chunks: ["print", "common"],
}),
],
- 将生产打包改为多出口
output: {
filename: "js/[name].[contenthash:8].js", // contentHash 内容改变hash值才会变
path: distPath,
},
2.抽离CSS文件
安装 mini-css-extract-plugin插件,具体的使用可以移步官网查看,这里不做赘述,后续会把源码地址贴在文末。
3. 压缩css/js
安装optimize-css-assets-webpack-plugin和terser-webpack-plugin插件,在生产配置上增加如下配置:
const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const TerserJsPlugin = require("terser-webpack-plugin");
module.exports = {
optimization: {
minimizer: [new TerserJsPlugin(), new OptimizeCssAssetsPlugin()],
}
}
4.抽离公共代码
注意从webpack v4 开始废弃CommonsChunkPlugin插件并且webpack内部集成了splitChunks代码分割,示例代码如下:
module.exports = {
optimization: {
splitChunks: {
chunks: "all",
/**缓存分组 */
cacheGroups: {
/**第三方插件 */
vendor: {
name: "vendor",
priority: 1, // 权限更高,优先抽离
test: /[\\/]node_modules[\\/]/,
minSize: 0,
minChunks: 1, // 模块至少被1个 入口chunk 共享)
},
/**公共模块 */
commons: {
name: "common",
priority: 0,
minSize: 0,
minChunks: 2,
},
},
},
}
}
5.懒加载
可以使用动态引入数据 - 实现懒加载
import('XXXX').then(() => {})
6.处理JSX
修改 .babelrc 配置为:
"presets": ["@babel/preset-react"],
7.处理Vue
rules: [{
test: /.vue$/,
loader: ['vue-loader'],
include: srcPath
}, ]