前端工程化:我在实战中走过的那些路
我是李晨,目前在一家中型互联网公司担任前端开发工程师。从业六年多来,我参与过不少项目,从最开始的简单页面重构,到如今主导中后台系统的前端架构设计和工程化建设。说实话,刚入行的时候,我对“前端工程化”这个概念并没有太多感知,觉得不就是写代码、调试样式、用个 Webpack 构建一下嘛?直到后来接手了一个复杂度颇高的中台项目,才发现自己对工程化的理解简直皮毛。
那次项目是我职业生涯中一次重要的转折点。项目本身业务逻辑庞大,模块众多,团队协作频繁,性能问题频发……当时我们团队里五六个前端,开发节奏一度非常混乱,每个人都在自己的小天地里写代码,构建流程不稳定、环境配置差异大、部署出错也找不到原因,上线后更是各种兼容性和性能问题层出不穷。
痛定思痛之后,我和团队决定彻底重构整个项目的工程体系。这篇文章,就来聊聊我在那个过程中踩过的坑、学到的经验,以及现在我们正在使用的一套相对成熟的工程化解决方案。
项目背景与挑战:一个“看似简单”的中台项目

当时的项目是一个企业级 SaaS 平台,面向的是中小企业的 IT 管理人员。虽然不是特别复杂的 ToC 类产品,但涉及到权限控制、数据可视化、大量表单交互等典型中后台功能。技术栈上,我们选择了 Vue3 + TypeScript + Vite 的组合。
一开始我们搭建了个简单的项目骨架,大家就开始各自分工开发了。但没过多久,我们就发现了一些明显的问题:
- 构建效率低下:随着组件数量增加,Vite 的热更新变慢,甚至有时候会卡住。
- 版本控制混乱:不同人的依赖版本不一致,有人本地跑得好好的,一合并代码就报错。
- 打包体积臃肿:最终 build 出来的文件动辄几 MB,加载速度极慢。
- 缺乏统一规范:命名、目录结构、代码风格随意,新同事看别人的代码像读天书。
- 自动化程度低:每次上线都需要手动打包上传,容易出错。
- 测试覆盖率低:基本没有单元测试或 E2E 测试,上线前靠手动点击测试,漏测频频发生。
这些问题直接影响了我们的开发效率和线上稳定性。那段时间,我每天早上打开 Slack 都能收到 QA 提的各种 bug,有些甚至只是因为某个依赖版本不对导致的,真的很让人头疼。
解决方案:重新梳理前端工程链路

既然问题这么多,那我们就得从头梳理整条工程链路了。我把这次重构划分为以下几个核心部分:
1. 初始化脚手架与项目结构标准化
我们决定不再直接 vite create,而是基于 pnpm 创建了一个内部的 monorepo 结构,并封装了自己的 CLI 工具用于初始化新项目(模仿了 @ant-design/cli 和 create-react-app 的方式)。
pnpm create my-project
这个 CLI 脚手架工具包含了统一的目录结构模板、基础组件库引入、全局样式处理和默认的配置文件,确保每个新项目开箱即用。
目录结构示例:
src/
│
├── assets/ # 静态资源
├── components/ # 公共组件
├── layout/ # 页面布局组件
├── pages/ # 页面路由组件
├── services/ # API 封装层
├── store/ # Pinia 状态管理
├── router/ # 路由配置
├── utils/ # 工具函数
├── App.vue
└── main.ts
2. 开发阶段的协作优化
使用 pnpm + Turborepo 进行依赖管理和缓存加速
我们在 monorepo 中集成了 Turborepo,这让多个子项目的依赖管理和任务执行变得高效了很多。比如我们可以并行运行多个 package 的 lint 或 test,极大提升了 CI 效率。
// turbo.json
{
"pipeline": {
"lint": {
"cache": true
},
"test": {
"dependsOn": ["^lint"]
}
}
}
统一 ESLint + Prettier + Stylelint
为了让代码风格统一,我们在项目中集成了以下规则:
eslint-config-airbnb-typescript@typescript-eslint/eslint-pluginprettierstylelint-scss(针对 SCSS)
并在 VSCode 中启用保存自动格式化,强制提交前检查风格。这一步大大减少了 review 时的风格争议。
3. 性能优化与打包策略
自动分包 + 动态导入
我们利用 Vite 内置的自动分包机制,结合 import() 实现懒加载路由组件。同时对于大型三方库(如图表库 ECharts),我们也进行了动态导入,减少主包体积。
// 示例:懒加载组件
const MyLazyComponent = defineAsyncComponent(() => import('@/components/LazyComponent.vue'));
图片压缩 + SVG Sprite
静态资源方面,我们集成了 image-minimizer-webpack-plugin,在构建时自动压缩图片,并将所有图标转换为 SVG Sprites,减少请求数量。
4. 自动化流程集成
我们搭建了一套完整的自动化流程:
| 环节 | 工具 | 目的 |
|---|---|---|
| 开发规范 | Husky + lint-staged | 提交前代码检查 |
| CI | GitHub Actions / Jenkins | 自动化测试、打包 |
| CD | Docker + Nginx + Ansible | 容器化部署 |
| 发布通知 | Dingtalk Bot | 上线通知 & 日志反馈 |
通过这些工具,我们实现了从提交代码 → 触发 CI → 打包 → 部署 → 通知的完整闭环。
5. 监控与错误收集
我们在生产环境中集成了 Sentry,用来捕获 JS 异常和接口失败信息,并且结合 source map 上传功能,可以在报错时看到具体哪一行出了问题。
import * as Sentry from '@sentry/browser';
Sentry.init({
dsn: 'https://xxx@sentry.io/project',
integrations: [new Sentry.BrowserTracing()],
});
代码实践:几个关键配置片段

为了让大家更直观了解,我挑几个比较常用的配置贴出来。
🧰 Vite 配置示例
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import tsconfigPaths from 'vite-tsconfig-paths';
export default defineConfig({
plugins: [vue(), tsconfigPaths()],
optimizeDeps: {
include: ['lodash-es', 'axios'],
},
build: {
outDir: 'dist',
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
return id.toString().split('node_modules/')[1].split('/')[0];
}
},
},
},
},
});
🔍 ESLint 配置(简化版)

module.exports = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
};
💼 GitHub Action 部署流程(简化)
name: Build and Deploy
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '18'
- run: npm install
- run: npm run build
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- run: echo "Deploying to staging..."
踩坑经验分享:那些年我们一起掉进去的地方
❌ 热更新卡顿问题
最初我们用 Vue3 + Vite 开发时,热更新越来越慢。后来发现是某些组件引入了大量的第三方库,或者过度使用响应式变量造成的。我们做了两个优化:
- 把大型依赖移出 watch 列表;
- 对于不需要响应式的对象使用
markRaw标记。
⚠️ Git Hooks 不生效
刚开始集成 Husky 时,发现提交代码并不会触发 eslint 检查。后来才发现是因为没有执行 husky install,导致 hooks 没有正确挂载。
建议大家安装完 husky 后记得运行:
npx husky install
npx husky add .husky/pre-commit "npm run lint"
🧵 多人协作下的 cache 冲突
Turborepo 默认开启了本地缓存,但在多人协同开发下会导致某些 cache 被污染。后来我们改为远程 cache 存储在 AWS S3,避免本地冲突。
实施后的效果和收益
经过两个月的努力,我们将整个项目的工程化体系建立起来,取得了明显的效果:
- 构建速度快了 2~3 倍
- 上线事故减少了 70% 以上
- 新人上手时间缩短了 60%
- 代码 Review 时间节省了 40%
更重要的是,我们团队的协作变得更加高效了,每个人都可以专注于业务逻辑而不是基建工作。
我的经验总结和建议

作为一名经历过工程化阵痛的开发者,我真心建议大家:
✅ 越早重视工程化越好
不要等到项目做大了才开始考虑这些问题。工程化就像盖房子的地基,前期花些力气,后期才能稳稳当当。
✅ 投资工具链=投资团队效率
一套好的脚手架、清晰的目录结构、自动化的流程,能让每个成员的工作更加聚焦,也更容易形成团队标准。
✅ 让工具帮你做重复的事
包括格式化、校验、测试、部署,尽可能自动化,减少人为操作带来的失误。
✅ 保持开放心态,持续迭代
工程化不是一锤子买卖,而是一个不断演进的过程。随着项目增长,你也需要不断地去调整构建策略、监控机制、错误上报等等。
写在最后:工程化不仅是个技术问题
其实我觉得,工程化不仅仅是写好一份 webpack.config.js,它更像是一种思维方式——如何把零散的代码、松散的流程组织成一个稳定、可持续发展的系统。
在我参与的每一次项目重构中,我都会回头去看当初自己写的那些“草稿式代码”,然后感慨:要是早点学工程化就好了!
如果你也是前端开发的一员,不妨从现在开始,着手优化你的项目结构、搭建你的 lint 流程、试一试自动化的发布机制。哪怕只迈出一小步,未来回头看的时候,你会发现这条路值得每一分努力。
愿你在编码的路上越走越远,一起写出更有质量的代码 🚀
如果这篇文字对你有帮助,欢迎在评论区交流你的工程化实践经历,我很乐意和大家一起探讨~

评论 0