从零搭起一个现代化前端项目,我踩过的坑比你走的路还多
上周五晚上十点半,我戴着 AirPods 半躺在工位上,一边听着 Lo-fi Hip Hop 一边疯狂敲键盘。窗外是上海徐家汇熟悉的霓虹——没错,我又在公司附近的小单间里“驻扎”加班了。事情起因很简单:我们技术中台要孵化一个新工具链,前端部分完全从零开始。领导说:“你不是一直嚷嚷着想用最新技术栈吗?这次给你机会。”
我嘴上说“好啊”,心里却咯噔一下——上次这么自信地接活,还是去年双11前重构购物车组件,结果线上白屏三分钟,被产品追着问“是不是故意搞破坏”。
但话说回来,作为上市公司技术中台的一员,写可维护、可扩展、可读性高的代码,本就是基本修养。这次项目虽然小,但麻雀虽小五脏俱全:需要对接 Spring Boot 后端、支持 CI/CD、具备完善的测试和文档、还要能快速部署到 GitHub Pages 做 Demo。更关键的是——这玩意儿将来可能会放进我的求职作品集里。毕竟,谁不想跳槽时甩出一个干净利落、架构清晰的 GitHub 项目呢?
起手式:别一上来就 npm create-react-app
很多人一想到“现代化前端项目”,第一反应就是 create-react-app 或者 Vite + React。但说实话,在企业级场景下,这种脚手架生成的项目往往只是个起点。真正的挑战在于:如何组织目录、管理依赖、统一规范、集成工具链。
我们的目标很明确:
- 技术栈:TypeScript + Vite + React 18 + Tailwind CSS
- 工程化:ESLint + Prettier + Husky + lint-staged
- 测试:Vitest + React Testing Library
- 部署:GitHub Actions 自动构建并发布到 GitHub Pages
- 文档:集成 Storybook,组件即文档
听起来是不是有点重?但相信我,在中台团队,这种配置已经是“轻量级”了。我们甚至砍掉了微前端和模块联邦——毕竟不是每个项目都需要那么“高大上”。
目录结构:可读性才是第一生产力
我见过太多项目把所有 hooks 塞进 utils 文件夹,把 API 请求散落在各个 component 里。每次接手都像考古。所以这次我坚持一个原则:按功能划分,而非按技术类型划分。
src/
├── features/ # 业务功能模块(如 auth, dashboard)
├── shared/ # 跨模块复用逻辑
│ ├── components/ # 公共组件(带 Storybook)
│ ├── hooks/ # 自定义 hooks
│ ├── lib/ # 工具函数、第三方封装
│ └── types/ # 全局 TS 类型
├── app/ # 应用入口、路由、全局状态
├── assets/ # 静态资源
└── main.tsx # 启动文件
这样做的好处是:当你想改“用户登录”逻辑时,直接去 features/auth 里找,不用在十几个文件夹里来回跳转。产品经理说“登录页加个验证码”,我也能三分钟定位到对应组件,而不是翻半天 components/Auth/LoginForm.tsx。
和 Spring Boot 联调:跨域不是玄学
后端同事用的是 Spring Boot,跑在本地 localhost:8080。前端 Vite 默认 localhost:5173。第一次联调,控制台直接给我甩了个经典错误:
Access to fetch at 'http://localhost:8080/api/login' from origin 'http://localhost:5173' has been blocked by CORS policy.
我差点以为自己配错了 URL。结果一问后端,人家根本没开 CORS。Spring Boot 默认是禁止跨域的,得手动加配置:
@Configuration
public class CorsConfig {
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(Arrays.asList("http://localhost:5173"));
config.setAllowedMethods(Arrays.asList("*"));
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/api/**", config);
return source;
}
}
当然,上线后我们会用 Nginx 统一代理,避免跨域问题。但在开发阶段,前后端分离调试是常态。所以我在 vite.config.ts 里也加了代理:
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
});
现在前端直接请求 /api/login,Vite 会自动转发到后端。再也不用担心 CORS 报错让我怀疑人生了。
Git 提交规范:Husky + lint-staged 救我狗命
我们团队有个不成文规定:PR 里不能有 ESLint 错误或格式混乱的代码。以前靠 Code Review 人工检查,效率低还伤感情。后来我引入了 Husky + lint-staged,提交前自动 fix:
// package.json
{
"scripts": {
"lint": "eslint . --ext ts,tsx --fix",
"format": "prettier --write ."
},
"lint-staged": {
"*.{ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{js,json,md}": ["prettier --write"]
}
}
配合 Husky 的 pre-commit 钩子,每次 git commit 都会自动格式化代码。虽然偶尔会因为 Prettier 把单引号改成双引号被同事吐槽,但至少 PR 里的 diff 不再是满屏红色了。
部署到 GitHub Pages:一键发布不是梦
为了方便展示和求职,我把项目部署到了 GitHub Pages。配置其实超简单,只需要两步:
在
vite.config.ts中设置base:export default defineConfig({ base: '/my-awesome-project/', // 注意和仓库名一致 });写一个 GitHub Actions workflow:
# .github/workflows/deploy.yml
name: Deploy to GitHub Pages
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm run build
- uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist
每次推到 main 分支,Action 自动构建并发布。Demo 地址立刻生效。面试时直接甩链接:“这是我独立搭建的项目,源码在 GitHub,欢迎 Star~”
性能与兼容性:别让用户等得想卸载
虽然项目不大,但我还是做了些基础优化:
| 优化项 | 措施 | 效果 |
|---|---|---|
| Bundle Size | 使用 vite-bundle-visualizer 分析 |
移除 unused lodash,体积 ↓30% |
| 图片懒加载 | <img loading="lazy"> |
首屏加载快 0.8s |
| 浏览器兼容 | browserslist 配置支持到 Chrome 80+ |
避免用太新的 JS 特性 |
| 错误边界 | 自定义 ErrorBoundary 组件 |
防止白屏,提升用户体验 |
特别吐槽一点:有些同学为了炫技用 Proxy 或 Reflect 搞花里胡哨的状态管理,结果 IE11 用户(对,我们还有!)一打开就报 Uncaught ReferenceError: Proxy is not defined。老板问起来,你说“现在谁还用 IE”,但客户偏偏就是那 0.5% 的用户。
最后:写代码是为了让人看懂,不是让机器运行
回过头看,这个项目从零到上线只用了两周。过程中踩过 Vite 插件冲突的坑、被 TypeScript 泛型绕晕过、也因为 GitHub Actions 权限问题熬到凌晨。但最终,它成了我 GitHub 上 star 最多的项目(虽然只有 23 个……)。
更重要的是,代码结构清晰、文档齐全、测试覆盖,连实习生都能快速上手修改。这才是“现代化前端项目”的真正意义——不是堆砌最新框架,而是打造一个可持续演进的工程体系。
如果你也在准备求职,不妨从一个小而美的项目开始。别只写 TodoList 了,试试对接真实后端、写单元测试、做自动化部署。这些细节,才是面试官眼里“靠谱工程师”的分水岭。
对了,项目地址在这:github.com/yourname/my-awesome-project(名字当然是假的)。Star 不重要,但 issue 欢迎提——说不定下次团建,我就请你喝瑞幸了。
(耳机里的音乐刚好切到下一首,是 The Weeknd 的《Blinding Lights》。嗯,该回家了,明天还得和产品 battle “这个按钮能不能再大 2px”。)

评论 0