抖音 - 哲玄《大前端全栈实践》
前言
通过最近学习,对工程化有了进一步的认识,前端工程化 不是一个具体的工具,而是一个思想和体系,可以通过:
- 模块化/组件化来解耦复杂应用。
- 规范化来约束开发过程。
- 自动化来提升效率和质量。
- 性能优化来保障用户体验。
掌握工程化思想,要比学习怎么使用构建工具来的更重要。
1.解析引擎工作流程

2. 项目Webpack架构设计
2.1 配置文件结构
bash
app/webpack/
├── config/
│ ├── webpack.base.js # 基础配置(公共配置)
│ ├── webpack.dev.js # 开发环境配置
│ └── webpack.prod.js # 生产环境配置
├── dev.js # 开发服务器启动脚本
└── prod.js # 生产环境构建脚本
2.2 配置继承关系
scss
webpack.base.js (基础配置)
├── webpack.dev.js (开发环境继承)
└── webpack.prod.js (生产环境继承)
3. 核心配置详解
3.1 基础配置 (webpack.base.js)
3.1.1 多页面入口配置
javascript
// 动态构造入口文件和HTML模板文件
const pageEntries = {};
const htmlWebpackPluginList = [];
const entryList = path.resolve(process.cwd(), "./app/pages/**/entry.*.js");
glob.sync(entryList).forEach((file) => {
const entryName = path.basename(file, ".js");
pageEntries[entryName] = file;
htmlWebpackPluginList.push(
new HtmlWebpackPlugin({
filename: path.resolve(process.cwd(), "./app/public/dist/", `${entryName}.tpl`),
template: path.resolve(process.cwd(), "./app/view/entry.tpl"),
chunks: [entryName],
})
);
});
3.1.2 模块解析规则
javascript
module: {
rules: [
{
test: /\.vue$/,
use: { loader: "vue-loader" }
},
{
test: /\.js$/,
include: [path.resolve(process.cwd(), "./app/pages")],
use: { loader: "babel-loader" }
},
{
test: /\.(png|jep?g|gif)(\?.+)?$/,
use: {
loader: "url-loader",
options: { limit: 300, esModule: false }
}
}
]
}
3.1.3 代码分割策略
javascript
optimization: {
splitChunks: {
chunks: "all",
cacheGroups: {
vendor: {
test: /[\/]node_modules[\/]/,
name: "vendor",
priority: 20,
enforce: true,
reuseExistingChunk: true,
},
common: {
name: "common",
minChunks: 2,
minSize: 1,
priority: 10,
reuseExistingChunk: true,
},
},
},
runtimeChunk: true,
}
分割策略:
- vendor:第三方库代码(node_modules)
- common:业务公共代码(被2个以上页面引用)
- runtime:webpack运行时代码
- entry.{page}:页面特定代码
3.2 开发环境配置 (webpack.dev.js)
3.2.1 热更新配置
javascript
// 为每个入口添加HMR客户端
Object.keys(baseConfig.entry).forEach((v) => {
if (v !== "vendor") {
baseConfig.entry[v] = [
baseConfig.entry[v],
`webpack-hot-middleware/client?path=http://${HOST}:${PORT}/${HMR_PATH}?timeout=${TIMEOUT}&reload=true`,
];
}
});
plugins: [
new webpack.HotModuleReplacementPlugin({ multiStep: false })
]
3.2.2 Source Map配置
javascript
devtool: "eval-cheap-module-source-map"
选择原因:
- eval:快速重新构建
- cheap:只包含行信息,构建更快
- module:包含loader的source map
3.3 生产环境配置 (webpack.prod.js)
3.3.1 CSS提取和压缩
javascript
plugins: [
new MiniCssExtractPlugin({
chunkFilename: "css/[name]_[contenthash:8].bundle.css",
}),
new CssMinimizerPlugin(),
]
3.3.2 JavaScript压缩优化
javascript
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
cache: true,
terserOptions: {
compress: {
drop_console: true, // 移除console.log
},
},
}),
],
}
3.3.3 多线程构建加速
javascript
new HappyPack({
id: "js",
threadPool: HappyPack.ThreadPool({ size: os.cpus().length }),
loaders: [
`babel-loader?${JSON.stringify({
presets: ["@babel/preset-env"],
plugins: ["@babel/plugin-transform-runtime"],
})}`,
],
})
4. 开发服务器配置
4.1 Express + Webpack中间件
javascript
const devMiddleware = webpackDevMiddleware(compiler, {
writeToDisk: (files) => files.endsWith(".tpl"),
publicPath: webpackConfig.output.publicPath,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
"Access-Control-Allow-Headers": "X-Requested-With, Content-Type, Authorization",
},
});
const hotMiddleware = webpackHotMiddleware(compiler, {
path: `/${HMR_PATH}`,
log: false,
});
关键特性:
- 内存编译:文件保存在内存中,提高访问速度
- 选择性写盘:只有.tpl文件写入磁盘(后端需要)
- CORS支持:解决跨域问题
- 热更新通信:实时推送代码变更
结语
学习前端工程化有助于提升开发效率与项目质量,但不应盲目套用现有方案,而应深入理解其本质。我们应掌握其整体思路与工作流程,思考性能优化方向,并能够结合具体业务需求进行工程化配置。