Webpack
一、核心概念
1. Webpack 核心概念
问题:Webpack 核心概念
答案: 核心回答:Webpack 核心概念包括 Entry、Output、Loader、Plugin、Mode。
代码示例:
// webpack.config.js
module.exports = {
// 入口
entry: './src/index.js',
// 输出
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.[contenthash].js'
},
// Loader 处理非 JS 文件
module: {
rules: [
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
{ test: /\.js$/, use: 'babel-loader' }
]
},
// Plugin 执行更复杂任务
plugins: [
new HtmlWebpackPlugin({ template: './src/index.html' }),
new CleanWebpackPlugin()
],
// 模式
mode: 'production' // development | production | none
};
二、代码分割与懒加载
2. Code Splitting
问题:Code Splitting
答案: 核心回答:代码分割将 bundle 拆分成多个 chunk,实现按需加载。
代码示例:
// 1. 入口分割
module.exports = {
entry: {
main: './src/index.js',
vendor: './src/vendor.js'
},
output: {
filename: '[name].[contenthash].js'
}
};
// 2. 动态 import
const LazyComponent = React.lazy(() => import('./LazyComponent'));
// 3. splitChunks
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 10
}
}
}
}
};
3. Lazy Loading
问题:Lazy Loading
答案: 核心回答:懒加载延迟加载非首屏资源。
代码示例:
// ES6 动态导入
const getModule = () => import('./module');
// React 懒加载
const LazyComponent = React.lazy(() => import('./Component'));
function App() {
return (
<Suspense fallback={<Loading />}>
<LazyComponent />
</Suspense>
);
}
// Vue 路由懒加载
const routes = [
{ path: '/', component: () => import('./Home.vue') }
];
三、Loader 与 Plugin
4. 常用 Loader
问题:常用 Loader
答案: 核心回答:babel-loader、css-loader、style-loader、file-loader 等。
代码示例:
module.exports = {
module: {
rules: [
// Babel
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
}
},
// CSS
{
test: /\.css$/,
use: ['style-loader', 'css-loader', 'postcss-loader']
},
// 图片
{
test: /\.(png|jpg|gif)$/,
type: 'asset/resource'
},
// 字体
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
type: 'asset/resource'
}
]
}
};
5. 常用 Plugin
问题:常用 Plugin
答案: 核心回答:HtmlWebpackPlugin、CleanWebpackPlugin、MiniCssExtractPlugin 等。
代码示例:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
plugins: [
// 清理 dist
new CleanWebpackPlugin(),
// 生成 HTML
new HtmlWebpackPlugin({
template: './src/index.html',
minify: true,
chunks: ['main']
}),
// 提取 CSS
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css'
}),
// 代码压缩
new TerserPlugin({
terserOptions: {
compress: { drop_console: true }
}
})
]
};
四、性能优化
6. Webpack 性能优化
问题:Webpack 性能优化
答案: 核心回答:减少resolve、压缩代码、提取公共代码、使用缓存等。
代码示例:
module.exports = {
// 1. 优化 resolve
resolve: {
extensions: ['.js', '.jsx', '.json'],
alias: {
'@': path.resolve(__dirname, 'src')
}
},
// 2. externals 外部扩展
externals: {
react: 'React',
'react-dom': 'ReactDOM'
},
// 3. DllPlugin 预编译
// 4. HashedModuleIdsPlugin 稳定 ID
// 5. terser-webpack-plugin 压缩
optimization: {
minimize: true,
minimizer: [new TerserPlugin()],
splitChunks: {
chunks: 'all'
}
},
// 6. 缓存
cache: {
type: 'filesystem'
}
};
五、热模块替换
7. HMR 原理
问题:HMR 原理
答案: 核心回答:热模块替换在不刷新页面的情况下更新模块。
代码示例:
// webpack-dev-server 自动支持 HMR
// 配置
module.exports = {
devServer: {
hot: true,
hotOnly: true
}
};
// 手动启用 HMR
if (module.hot) {
module.hot.accept('./render', () => {
render();
});
}
// Vue HMR
import Vue from 'vue';
if (module.hot) {
module.hot.accept();
}
// React HMR
import React from 'react';
if (module.hot) {
module.hot.accept();
}