从零搭建一个现代前端项目的那些事儿
去年年底,我接手了一个新项目——公司要开发一款面向中小企业的数据可视化工具。作为一个“从零开始”的项目,它没有遗留代码包袱,理论上可以自由选择技术栈,听起来像是个挺爽的活儿。但实际情况远比我想象中复杂得多。
初衷与背景:为什么要做这件事?

在项目启动前,我们团队已经意识到,现有的几个产品项目因为技术栈老旧、构建方式混乱,导致后期维护成本越来越高。因此这次我们要彻底“重开一局”,从头设计一个现代化的前端项目结构,目标是:
- 高可维护性,方便多人协作
- 快速构建和部署流程
- 支持跨浏览器兼容(IE11必须兼容)
- 高性能,用户体验优先
说白了,我们想做一个“能跑五年都不怕过时”的项目结构。
面临的挑战:理想很丰满,现实很骨感

刚开始做的时候,我以为这只是一个技术选型+搭架子的过程,但实际上我们遇到了不少问题:
- 技术栈该如何选?React 还是 Vue?ESLint + Prettier 怎么配置才不打架?
- 工程化怎么搞?Webpack/Vite 谁更适合初期?要不要用 monorepo?
- 团队协作规范难统一。每个开发习惯不同,Git 提交信息乱七八糟。
- UI 框架怎么接入?引入 Ant Design,结果发现样式加载太多,首屏性能被拉垮。
- IE11 兼容性问题层出不穷,Babel、Polyfill、PostCSS 都得一一处理。
- 构建过程太慢,本地开发服务器启动要等三四分钟,严重影响效率。
这些问题一个个堆上来的时候,我才意识到:所谓“从零开始”,其实是从一堆未知开始。
我们的技术方案:稳中求进,务实为先

综合权衡之后,我们选择了以下技术栈:
- 框架:React + React Hooks
- 状态管理:Redux Toolkit(轻量且内置 immutable)
- UI 框架:Ant Design + 可按需加载的 babel-plugin-import
- 构建工具:Webpack + Babel + PostCSS
- 组件库开发:Storybook
- 代码规范:ESLint + Prettier + Husky + lint-staged
- CI/CD:GitHub Actions + Docker 构建部署
技术细节拆解
1. 模块化设计先行
我们在 src/ 下建立了清晰的目录结构:
src/
│
├── assets/ # 静态资源
├── components/ # 公共组件
├── layouts/ # 页面布局
├── pages/ # 页面级组件
├── services/ # 接口封装
├── store/ # Redux 状态管理
├── utils/ # 工具函数
├── App.jsx # 主入口
└── index.js # ReactDOM.render
这种结构保证了模块之间耦合度低,便于扩展和测试。
2. 引入 Ant Design 并按需加载
最开始直接导入整个 antd,打包体积瞬间暴增。后来改用 babel-plugin-import 实现按需加载:
// 安装插件
npm install --save-dev babel-plugin-import
// 在 .babelrc 中添加
{
"plugins": [
["import", { "libraryName": "antd", "style": "css" }]
]
}
这样引入组件时会自动加载对应样式,体积减少了近 60%。
3. Webpack 构建优化
为了让首次加载更快,我们做了以下几个优化点:
- 使用 SplitChunksPlugin 拆分 Vendor 和业务代码
- 通过 CSS Minimizer Plugin 压缩 CSS 文件
- 图片压缩:url-loader + imagemin-webpack-plugin
还有一点特别重要的是,对 IE11 的 Polyfill 处理。一开始没加,上线后发现有些方法根本不可用。后来加上:
// 在 webpack.config.js entry 添加
entry: {
app: ['@babel/polyfill', './src/index.js']
}
同时在 Babel config 加上预设:
{
"presets": [
["@babel/preset-env", {
"targets": {
"ie": "11"
},
"useBuiltIns": "usage",
"corejs": 3
}]
]
}
解决了兼容性问题。
4. 规范化提交与检查机制
为了避免一团乱麻的 Git 记录,我们引入了 Husky + lint-staged,在每次 commit 前跑 ESLint 和 Prettier:
npm install husky lint-staged eslint prettier --save-dev
然后在 package.json 里加了:
{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.js": [
"eslint . --ext .js",
"prettier --write src/**/*.js",
"git add"
],
"*.css": "prettier --write"
}
}
从此再也不担心有人写错格式或者提交未修复的警告了。
开发中的几个大坑
1. Webpack 配置错误导致 HMR 失效
有一次本地开发环境的热更新一直失效。查了好久才发现是我在 Webpack Dev Server 的配置里误删了 hot: true,结果页面每次修改都刷新而不是局部热更新,白白浪费了不少时间。
2. Ant Design 图标不显示
项目刚上线时有个页面图标全白,最后发现是在 IE11 上 SVG 无法正确渲染。我们临时换成 iconfont 方案,虽然不够优雅但也算是兜住了。
3. Storybook 不支持按需加载
我们在用 Storybook 写组件文档时,发现 antd 按需加载的插件没有生效。最后手动加了个 .storybook/webpack.config.js,在里面重新引入了 babel-plugin-import 才解决。
这些小插曲让我深刻体会到一点:前端工程从来都不是“搭好框架就万事大吉”,每一个细节都要反复验证。
效果和收益:不止是一个脚手架
经过两个月的打磨,我们的“现代化前端基础架构”基本成型。效果如何呢?
- 本地开发服务器冷启动速度控制在 15 秒以内
- 首次访问加载时间从 8s 缩短到 2.5s(移动端实测)
- 团队协作更加顺畅,代码风格统一
- CI 流程自动化完成构建和部署,出错率显著降低
- 有了清晰的模块划分,后续新增功能模块变得简单可控
更重要的是,我们现在回头看之前的项目,会发现很多“那时候要是知道就好了”的经验,都沉淀到了这个新架构中。
一些实战建议送给你
如果你也在打算从零搭建一个现代化的前端项目,这里是我踩过的坑总结出来的一些建议:
✅ 技术选型别贪多,以团队为主
很多人喜欢追“最流行”的技术,但其实最重要的是团队熟悉度。比如如果你团队里没人用 Vue 3 + Typescript,那不如选一个更稳妥的组合。毕竟项目是要交付的,不是拿来练手的。
✅ 结构清晰比命名规范更重要
再牛的命名规范也挡不住混乱的目录结构。建议一开始就规划好层级关系,哪怕是简单的文件夹分类,也能为将来的重构节省大量时间。
✅ 不要忽视性能优化和兼容性
尤其做企业级应用时,用户可能还在用 IE11。一定要尽早考虑兼容问题,不要等上线后再去补窟窿。
✅ 组件库+文档并行开发
如果你也在做一个组件库级别的项目,强烈建议一边开发一边写 Storybook 文档。不仅能快速看效果,还能形成可视化的组件库说明。
✅ 启动器不要太依赖脚手架
Create React App 很方便,但在真正复杂的项目里,迟早要“eject”。不如早点自己搭一个轻量版的 Webpack 配置,既能学到东西,又能灵活控制。
这篇文章写到这里,其实不只是分享一个技术方案,更像是记录一段真实的经历。我始终相信,一个好的前端架构,不是靠某个炫技的新特性堆出来的,而是靠日复一日的实践、一次次失败后的反思,慢慢打磨出来的。
希望这篇实战经验,能在你下一个项目启动时有所帮助。如果哪天你在开发过程中遇到类似的问题,欢迎留言交流,一起进步!
文末小彩蛋 🍭
“有时候我们会因为一个构建工具的报错花了一整天都没解决,第二天却发现只是少加了一个空格。但正是这些看似无聊的琐碎工作,才最终构成了一个稳定运行的系统。” —— 来自深夜调试现场的感悟

评论 0