从零搭一个现代化前端项目,我踩过的坑比你走的路还多
去年双11大促前夜,我们团队临时接到产品需求:要为一个新业务线从零搭建一个高性能、可维护、支持快速迭代的前端项目。当时我正戴着耳机听着Lo-fi beats写代码,突然收到产品经理发来的“紧急”钉钉消息——“这个功能下周一上线,拜托了!”。我心里一万个MMP,但表面上还得回个“OK~ 😊”。
作为阿里P7前端工程师,经历过不止一次大促洗礼,我深知“从零开始”四个字背后藏着多少技术债和深夜加班的泪水。更别提我现在一边准备跳槽,一边刷LeetCode,还要应付这种突发需求,属实是地狱难度。
不过话说回来,这也是个机会。既然要重头来过,不如彻底现代化一把——告别老旧脚手架、混乱的目录结构、手动部署的原始操作。今天就借这篇文章,聊聊我是如何从零构建一个真正“现代化”的前端项目的,尤其聚焦在React生态下的技术选型与实战思考。
为什么这次不能再用 create-react-app?
很多同学第一反应肯定是 npx create-react-app my-app,简单粗暴,开箱即用。但如果你真的在大厂待过,就知道CRA(Create React App)在真实业务场景中有多“天真”。
- 不支持微前端(我们内部系统全是微前端架构)
- 构建速度慢得像蜗牛(双11期间改一行代码等5分钟?达咩)
- 无法自定义Webpack配置(除非eject,但eject等于自杀)
- 没有TypeScript深度集成(现在谁还敢不用TS?)
所以,我直接pass了CRA。取而代之的是 Vite + React + TypeScript 的组合。Vite的HMR(热更新)快到离谱,本地开发秒级启动,改完代码几乎无感知刷新。上周五晚上我改了个组件样式,保存后浏览器还没反应过来我已经切到另一个tab了——这就是生产力!
当然,也有人推荐 Next.js。确实,Next.js在SSR、SEO、路由管理上很香,但我们这个项目是纯后台管理系统,不需要服务端渲染,反而会引入不必要的Node.js依赖和部署复杂度。而且我们团队对K8s和云原生比较熟,静态资源直接扔OSS + CDN就行,根本不需要Node中间层。
| 方案 | 启动速度 | 构建速度 | 微前端友好 | 自定义能力 | 适用场景 |
|---|---|---|---|---|---|
| CRA | 慢 | 慢 | 差 | 弱(需eject) | 快速原型、学习 |
| Vite + React | ⚡️极快 | ⚡️快 | 好(配合Module Federation) | 强 | 现代化SPA、后台系统 |
| 0 | |||||
| Next.js | 中 | 中 | 一般 | 中 | 内容型网站、需要SSR |
最终,我们选择了 Vite 作为构建工具,理由很朴素:快、轻、灵活。
目录结构:别再把所有东西塞进 src 了!
很多项目 src 下面堆着 components、utils、pages、hooks、assets……看起来整齐,实则混乱。一旦项目超过100个文件,找东西全靠全局搜索。
我参考了阿里内部的前端工程规范,采用 分层 + 领域驱动 的结构:
src/
├── app/ # 应用入口 & 全局状态
├── features/ # 业务功能模块(按产品功能划分)
│ ├── order/ # 订单模块
│ │ ├── components/
│ │ ├── hooks/
│ │ ├── services/
│ │ └── index.tsx
│ └── user/
├── shared/ # 跨模块共享代码
│ ├── ui/ # 通用UI组件(Button, Modal等)
│ ├── lib/ # 工具函数、第三方封装
│ └── types/ # 全局TS类型
├── config/ # 环境配置、API地址
└── main.tsx
这样做的好处是:高内聚、低耦合。每个 feature 模块自包含,产品经理说“砍掉订单模块”,我直接删整个 order 文件夹,连Git记录都干净。
而且,这种结构天然支持 微前端拆分。未来如果要把订单模块独立成子应用,只需加个 expose 配置就行。
状态管理:别再无脑上 Redux 了!
坦白讲,Redux 在2024年已经不是默认选项了。我们这个项目交互不算复杂,主要是表单、表格、弹窗,完全没必要引入 Redux + Toolkit + Thunk + Saga 这套重型装备。
我试了三种方案:
- useState + useContext:简单场景够用,但跨层级传递还是麻烦。
- Zustand:轻量、API简洁、支持持久化,写起来像Vue的Pinia。
- Jotai:基于原子模型,适合细粒度状态,但学习曲线略陡。
最终选了 Zustand。为什么?因为它真的省心。看这段代码:
// store/orderStore.ts
import { create } from 'zustand';
interface OrderState {
orders: Order[];
loading: boolean;
fetchOrders: () => Promise<void>;
}
export const useOrderStore = create<OrderState>((set, get) => ({
orders: [],
loading: false,
fetchOrders: async () => {
set({ loading: true });
const data = await api.getOrders();
set({ orders: data, loading: false });
}
}));
没有 Provider,没有 action type,没有 reducer switch,直接在组件里 const { orders, fetchOrders } = useOrderStore() 就能用。测试也简单,因为 store 是纯函数。
而且 Zustand 支持 middleware,比如加个 logger 或 persist(本地缓存),几行代码搞定。双11期间我们遇到一个诡异的Bug:用户刷新后购物车清空。后来发现是没做持久化,加了个 persist middleware,问题秒解。
UI 组件库:Ant Design 还是自己造轮子?
作为阿里人,第一反应肯定是 Ant Design。但说实话,A ntd 的体积太大了,光一个 Button 就带了一堆你用不到的逻辑。而且样式定制困难,想改个 primary color 都得翻文档半小时。
这次我决定 自建轻量UI库,只封装真正需要的组件:
Button:支持 loading、size、typeTable:虚拟滚动 + 分页 + 排序Modal:支持拖拽、ESC关闭Form:配合 Zod 做校验
核心原则:够用就好,不求大而全。每个组件都用 Storybook 写了 demo 和测试用例,确保不会半夜被测试小姐姐@。
顺便吐槽一句:产品经理总想加“动画效果”,上次非要给表格加 fade-in,我说“亲,性能压测过吗?”,他立马闭嘴了。
构建与部署:拥抱云原生
既然我对 K8s 比较熟,那部署肯定不能还是 npm run build && scp dist root@server 这种原始操作。
我们的 CI/CD 流程:
- Git Push 到
main分支 - GitLab CI 触发 Pipeline
- 构建 Docker 镜像(多阶段构建,base 镜像只有 20MB)
- 推送到私有 Harbor 仓库
- ArgoCD 自动同步到 K8s 集群
- Ingress 暴露服务,绑定 CDN
关键配置片段:
# Dockerfile
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
线上环境跑在阿里云 ACK(K8s 托管版),配合 SLB + OSS 静态资源加速,首屏加载压到了 800ms 以内。双11当天峰值 QPS 5w+,稳如老狗。
性能优化:别让用户体验掉链子
现代化项目不能只跑起来就行,性能就是产品力。
我们做了几件事:
- 代码分割:路由级 + 组件级动态 import
- 图片懒加载:用
loading="lazy"+ Intersection Observer - 字体优化:本地托管 + font-display: swap
- 缓存策略:immutable + contenthash,长期缓存
- 监控上报:接入阿里内部前端监控平台(类似 Sentry)
最骚的操作是:把非关键 CSS 内联到 HTML,关键路径 JS 提前 prefetch。结果 Lighthouse 分数从 60 飙到 92。
最后:技术选型的本质是权衡
写到这里,耳机里的音乐刚好切到《Weightless》——据说是全球最放松的歌。而我也终于松了口气。
从零构建一个现代化前端项目,没有银弹,只有权衡。React 是我们的选择,但更重要的是围绕它搭建一套适合团队、产品、业务节奏的工程体系。
现在这个项目已经稳定运行半年,支撑了三个产品线的需求迭代。上周我拿它当跳槽面试的谈资,还拿到了不错的 offer。果然,能落地的技术方案,才是最好的简历。
如果你也在从零开始,别急着抄作业。先问自己三个问题:
- 产品目标是什么?(To B 还是 To C?需要 SEO 吗?)
- 团队技术栈如何?(新人能不能快速上手?)
- 未来半年会怎么变?(会不会拆微前端?要不要国际化?)
想清楚这些,你的“现代化”才不会变成“过度设计”。
好了,不说了,LeetCode 第328题还在等着我。下次双11,希望我能在家躺着,而不是在工位debug。

评论 0