从零开始构建一个现代化前端项目:我的实战经历与思考
引言:为什么我们要重新开始?

去年年底,我加入了一个新的创业团队,负责技术架构的搭建。当时摆在我们面前的是一个几乎空白的技术环境:没有框架选型、没有工程化流程、甚至也没有一个稳定的开发协作方式。我们的目标是快速上线一套面向企业用户的 SaaS 平台,界面要现代、响应式设计良好、交互流畅,还要能在各种浏览器上稳定运行。
作为一个有多年经验的前端负责人,我知道“从零开始”既是一次机会,也是一次挑战。它意味着我们可以按照最新的技术趋势来搭积木,但同时也意味着每一个选择都需要反复斟酌,每一次决策都可能影响后续的开发节奏和产品体验。
这篇文章,我想用第一人称的方式,分享我如何带领团队从零搭建一个现代化前端项目的过程——包括遇到的问题、做的技术选型、踩过的坑,以及最后带来的收益。如果你也曾面临类似的起点,或许能从中找到一些灵感。
项目背景:一个典型的中后台应用场景

我们开发的产品是一个面向中小企业的数据管理平台,用户通过 Web 端完成数据导入、分析、可视化展示和配置任务。项目初期目标明确:
- 快速迭代,支持持续交付
- 页面需兼容主流浏览器(Chrome、Edge、Firefox),在 IE11 上尽可能兜底
- 用户操作频繁,需保证交互流畅、加载速度快
- 未来具备一定的扩展性,为 PWA 或 Electron 客户端预留空间
这些需求决定了我们在技术选型时,不能简单照搬社区模板,必须结合实际场景做出权衡。
第一阶段:技术栈的选择与原型搭建

我们的初步选型清单
| 类别 | 技术选项 | 原因说明 |
|---|---|---|
| 主框架 | React | 团队熟悉,生态丰富,适合组件化开发 |
| 状态管理 | Redux Toolkit + RTK Query | 轻量、集成方便,减少样板代码 |
| 构建工具 | Vite + Rollup | 开发体验好,打包速度快 |
| UI 组件库 | Ant Design | 成熟、可定制性强、适合中后台系统 |
| 工程规范 | Prettier + ESLint + Husky | 团队协同必备 |
| 单元测试 | Vitest | 更轻量、更快于 Jest |
| 部署方案 | GitHub Actions + Netlify / Vercel | 支持自动部署,CI/CD 流畅 |
这并不是一开始就确定下来的,而是在不断尝试中逐步成型。比如最初我们尝试了 CRA(Create React App),但在项目逐渐变大后,热更新速度明显下降,最终决定切换到 Vite。
搭建过程中的小插曲
我记得第一次用 Vite 初始化项目的那天晚上,本地启动很快,但 CI 流水线一直报错:“找不到模块 react-refresh”。
后来查了一下发现是因为某些依赖项需要显式安装,而 Vite 的默认 preset 不包含这些开发依赖。这个问题虽然不大,但提醒我一点:越是追求“极速”的工具,越要注意依赖管理和版本控制。
于是我们统一整理了一份 package.json 模板,在新成员加入时直接套用,避免重蹈覆辙。
第二阶段:项目结构设计与基础能力实现

统一的项目结构
为了避免后期出现“混乱式增长”,我在项目初期就制定了一套标准目录结构,如下所示:
/src
├── app/ # 全局状态、路由、根组件
├── components/ # 可复用的基础组件
├── layouts/ # 布局容器(Header, Sidebar)
├── pages/ # 页面级组件
├── services/ # 数据请求服务
├── utils/ # 工具函数
├── hooks/ # 自定义 Hook
└── assets/ # 图片、字体等静态资源
这样的组织方式,不仅利于维护,也能帮助新人迅速上手。
路由设计与权限控制
我们采用的是 React Router v6,并结合角色权限系统来动态渲染菜单和路由。这里有个关键点:不要把权限逻辑耦合进路由配置中。
为了实现这一点,我们将权限系统封装成一个高阶组件:
const withRole = (allowedRoles: string[]) => (Component: FC) => {
return function RoleGuarded(props) {
const { role } = useAuth();
if (!allowedRoles.includes(role)) {
return <Navigate to="/403" />;
}
return <Component {...props} />;
};
};
然后在路由中这样使用:
<Routes>
<Route path="dashboard" element={<Dashboard />} />
<Route path="admin" element={withRole(['admin'])(AdminPage)} />
</Routes>
这样可以做到清晰分离业务逻辑与权限控制,也为后期接入 RBAC 系统打下基础。
踩坑记录:那些不该忽视的小细节
1. 本地开发和生产环境的差异
刚开始我们一切顺利,直到某天发布版本后,突然爆出一个问题:“页面上的图标不显示”。
查了很久才发现,Ant Design 的图标库中,某些图标在 dev 模式下可以正常加载,但在 build 后却没有被正确打包进去。
解决方法是引入完整的图标库:
import * as antIcons from '@ant-design/icons';
然后注册全局可用的图标组件:
const Icon = ({ name }) => {
const Component = antIcons[name];
return <Component />;
};
这件事让我意识到:看似“开箱即用”的功能,背后也可能有性能优化导致的副作用。一定要做好构建前后的测试验证。
2. 样式冲突问题
多个组件引用不同类名造成样式污染,也是一个常被忽视的问题。我们在 CSS Modules 和 Tailwind 之间犹豫很久,最终选择 CSS Modules + BEM 命名规范。
原因很简单:Tailwind 在大型项目中会导致 HTML 属性臃肿,也不便于主题覆盖。而 CSS Modules 加上命名规范,反而更易维护。
举个例子:
// _button.scss
.Button {
&--primary {}
}
对应的组件内:
import styles from './Button.module.scss';
function Button({ type = 'primary' }) {
return <button className={clsx(styles.Button, styles[`Button--${type}`])}></button>;
}
这样可以在不牺牲语义的同时,隔离组件样式。
3. IE11 支持问题
虽然现在大多数项目已经放弃对 IE11 的支持,但我们仍不得不考虑一部分企业客户的遗留系统。
这里踩的大坑是:Vite 默认不处理旧版语法,即使你用了 Babel 和 polyfill,有些特性如箭头函数、async/await 在 IE 中仍然报错。
解决方案有两个:
- 使用 @vitejs/plugin-react-swc 的替代方案,确保转译器能够输出兼容代码;
- 在
vite.config.ts中增加build.target: ['es2015', 'edge88', 'firefox78', 'chrome87', 'safari14']来扩大兼容范围;
不过还是建议大家根据真实用户统计数据评估是否真的有必要支持 IE。
性能优化与用户体验提升

初期表现不佳?我们做了这几件事
随着功能越来越多,项目首屏加载时间达到了 4 秒以上(未压缩)。这显然不行,尤其对企业客户来说,等待时间会直接影响使用意愿。
我们逐步优化了以下几个方面:
1. 图片懒加载 + WebP 支持
对于大量图表和数据封面图,我们统一使用 <img loading="lazy" />,并生成 WebP 格式的图片资源,节省了约 30% 的带宽。
2. 动态导入 + Code Splitting
使用 React.lazy + Suspense 实现按需加载:
const LazyComponent = React.lazy(() => import('./ExpensiveComponent'));
function Page() {
return (
<React.Suspense fallback="Loading...">
<LazyComponent />
</React.Suspense>
);
}
同时配合路由级别拆分,将各个主页面单独打包,进一步提升首屏速度。
3. 使用 Service Worker 缓存策略
虽然我们还没做离线功能,但提前引入 Workbox 设置缓存策略,可以让重复访问速度大幅提升。
4. 使用 Lighthouse 做性能审计
我们定期使用 Lighthouse 对比每次发布的得分变化,重点关注 Performance Score、CLS(累计布局偏移)、LCP(最大内容绘制)等指标。
效果总结:重构之后的变化
经过两个月的打磨,项目终于迎来了第一个可交付版本,我们也看到了实实在在的提升:
- 初次加载时间从平均 4s → 1.8s
- 打包体积减小约 40%
- 开发效率提升(HMR 稳定,错误提示精准)
- 团队协作更顺畅(结构清晰,文档完善)
更重要的是,我们建立了一整套标准化的开发流程和自动化机制,例如:
- Git 提交前自动 lint
- 发布前自动生成 changelog
- 构建失败自动通知 Slack 频道
这些看似琐碎的事情,其实正是项目健康度的关键保障。
经验总结:给你的几个建议
1. 选型不是越多越好,而是越合适越好
不要盲目跟风,每个新技术都要问一句:“它能不能解决我们当前的实际问题?”有时候最朴素的方案,反而是最稳定的。
2. 尽早规范化,哪怕一开始只有一个人
项目早期写代码很自由,但自由过了头就是灾难。建议从第一天起就统一命名规范、文件结构、组件设计思路。
3. 重视用户体验,不只是功能正确
现代前端不仅仅是实现功能,更要关注动画、交互反馈、无障碍等细节。哪怕是一个小小的 loading indicator,也要认真对待。
4. 善用开发者工具
Chrome DevTools、Lighthouse、React Developer Tools、Redux DevTools… 这些工具是帮你定位问题的最佳搭档,别总靠 console.log。
5. 多看、多试,也要多总结
技术更新太快,不要怕试错。但一定要及时总结经验,形成文档或内部知识库。这样团队的成长才会更高效。
结语:从零开始,不只是写代码

写到最后,我想说,从零构建一个前端项目,远不止是写代码那么简单。它是技术选型、是架构设计、是协作沟通、是性能调优,更是对未来的一种预判。
在这个过程中,我经历了焦虑、兴奋、痛苦,也有成就感。最重要的是,我学会了一件事:真正的现代化前端项目,不是堆砌新技术,而是用最合适的组合,把事情做得漂亮、稳定、可持续。
希望这篇文章能给你带来一点点启发。如果你也在做类似的事,欢迎留言交流!我们一起成长。
祝你在下一个项目中少踩坑、多产出!
本文首发于个人博客 https://zhuanlan.zhihu.com/p/xxxxxx,欢迎关注获取更多实战经验分享。

评论 0