构建生产就绪的作品集:第二阶段 — 前端引导与架构设置
Source: Dev.to
在基础设施已经就绪、需求明确的情况下,终于可以开始编写代码了。不过,这一阶段并没有直接跳入 UI 组件的实现,而是专注于搭建一个能够扩展、演进且易于维护的前端基础。
🔗 项目仓库
https://github.com/imsushant12/sushantgaurav-portfolio
为什么前端设置值得单独的阶段
完成后:
- Phase‑0 – 基础设施与工作流
- Phase‑1 – 需求收集与 PRD
我拥有大多数副项目没有的东西:
- 范围清晰
- 用户流程明确
- 责任划分明确
因此当 Phase‑2 开始时,目标不是 “构建 UI”。
目标
- 建立前端架构
- 提前确定工具选择
- 强制一致性
- 减少未来的重构
- 让代码库更友好于贡献者
该阶段代表项目的 Day‑3,但它被视为 正式的工程阶段,而非每日日志。
Phase‑2 目标
本阶段的目标有意被限定为:
- 使用现代工具链启动前端
- 在功能开发前搭建文件夹结构
- 配置样式、代码检查和格式化
- 规划路由但不实现完整页面
- 为应用的可扩展性做好准备,避免后期重写
尚未进行 UI 打磨。
功能尚未完成。
仅搭建基础。
第一步 – 使用 Vite 引导 React 应用
对于前端,我选择了 Vite + React,而不是旧的打包工具。
为什么选择 Vite?
- 极快的开发服务器
- 基于现代 ESM 的工具链
- 最少的配置
- 为 React 项目提供出色的开发者体验
快速启动,保持快速,避免不必要的复杂性。
此决定也与 CI/CD 以及未来的构建流水线高度契合。
第2步 – 设置前端工作区
与其让默认结构自行演化,我立即将前端组织到专用的 frontend/ 文件夹中。
好处
- 前端和后端可以独立演进
- CI 流水线保持简洁
- 部署目标明确
- 所有权边界得到尊重
从产品和工程的角度来看,这与真实团队组织代码库的方式相吻合。
第3步 – 安装核心依赖(有意而非随意)
在编写组件之前,我已安装了 最低必需的工具 以支持长期质量。
样式
Tailwind CSS – 选择它的原因:
- 一致性
- 快速迭代
- 实用优先的设计理念
- 以后更容易进行设计重构
路由
React Router DOM – 早期安装以:
- 规划导航
- 与第 1 阶段定义的用户旅程保持一致
- 避免后期路由重写
代码质量
提前配置以:
- 强制统一的代码风格
- 减少审查摩擦
- 防止格式争论
- 保持 PR 干净易读
第4步 – 在构建页面之前规划路由
与其先创建页面再随后配置路由,我选择先规划路由,再构建页面。
为什么?
- 路由决定用户的使用路径
- 页面应当遵循导航逻辑,而不是主导它
- 可避免不必要的重写工作
我基于以下内容映射路由:
- PRD(产品需求文档)
- 第一期的用户流程图
- 之前确定的作品集章节
在此阶段:
- 已完成路由规划
- 已准备好结构
- 实际内容故意保持最小化
第 5 步 – 设计前端文件夹结构(在编写功能之前)
在此阶段最重要的决策之一是 前端架构。
我们没有把所有东西都丢进 components/,而是有意采用了分层结构。
高层视图
src/
├── components
├── pages
├── hooks
├── data
├── services
├── styles
├── contexts
该结构提前回答了关键问题:
- UI 放在哪里?
- 逻辑放在哪里?
- 数据来自哪里?
- API 调用应该放在哪里?
它还使代码库更易于理解,受益对象包括:
- 未来的贡献者
- 代码审查者
- 未来的你
为什么这个阶段很重要(即使目前还没有“可见”的东西)
在此阶段,有:
- 没有精致的用户界面
- 没有动画
- 没有完成的页面
但前端已经:
- 可扩展
- 可预测
- 有结构
- 易于维护
许多项目因跳过结构而悄然失败,随后付出代价。
Source:
组件架构 – 超越“仅仅是组件”的思考
在前端项目中,最大的错误之一就是把每个文件都当作普通的组件。
相反,我依据 职责 对组件进行分类。
components/common
包含可复用、与布局无关的构建块,不含业务逻辑。
示例
Section.jsxSectionHeader.jsx
这些组件:
- 不关心它们被 在哪里 使用
- 不依赖路由
- 易于在页面之间复用
components/layout
布局组件定义 结构,而非内容。
示例
NavBarFooterLayouts
这些组件:
- 包裹页面
- 管理共享 UI
- 定义骨架和间距
components/sections
Section 代表 领域特定的 UI。
示例
HeroAboutProjectsOpenSource
这些组件:
- 对内容有感知
- 针对特定页面
- 可以独立演进
设计系统是结构化的
页面 vs 区块(有意的区分)
一种常见的反模式是混合路由和 UI 逻辑。
为避免这种情况,我做了明确的区分:
pages/
- 路由级组件
- 直接映射到 URL
- 组装区块
- 最少的逻辑
sections/
- 在页面之间可复用
- 表示逻辑内容块
- 不关心路由
这确保了:
- 路由保持轻量
- UI 保持可组合
- 重构更容易
它还允许:
- 在不重写 UI 的情况下重构页面
- 一致的布局复用
Hook:将逻辑与 UI 分离
我在早期引入了 hooks/ 层,而不是将逻辑直接嵌入组件中。
目的:
- 隔离数据获取逻辑
- 封装副作用
- 提高可测试性
- 降低组件复杂度
示例:
useProjectsuseAchievementsuseAbout
这使得组件:
- 声明式
- 更易阅读
- 更易调试
当 API 演进时,只需更改 Hook —— UI 不受影响。
数据层:将 UI 与内容解耦
在此阶段,大多数内容存放在 data/ 目录下的 JSON 文件中。
为什么?
- 内容变化频率高于 UI
- 支持快速迭代
- 模拟 API 驱动的开发
- 简化早期测试
类似文件:
projects.jsonexperiences.jsonhero.json
充当 临时后端。当真实 API 后期接入时,迁移会非常顺畅。
服务层:为后端集成做准备
即使后端尚未完全实现,我仍创建了 services/ 层。
该层:
- 集中管理 API 调用
- 隔离 HTTP 逻辑
- 防止 API 使用泄漏到组件中
示例: api.js
收益:
- 避免紧耦合
- 支持 Mock
- 以后 CI 测试更容易
样式与资源:提前保持组织有序
样式
所有全局样式放在:
styles/
├── globals.css
├── animations.css
这样可以避免:
- CSS 分散
- 行内混乱
- 动画不一致
资源
资源按业务域分组:
- hero
- about
- projects
- logos
这提升了:
- 可读性
- 资源复用
- 可维护性

ESLint 与 Prettier:提前强制规范
在编写功能之前就配置了 Lint 与 格式化。
这确保了:
- 风格一致
- 差异可预期
- PR 审核更轻松
- 主观争论更少
作为负责人或审阅者,这在后期能节省大量时间。
第 2 阶段的成果
- 前端使用现代工具启动
- 可扩展的文件夹结构已就位
- 路由已规划(未仓促)
- 代码质量工具已配置
- UI、逻辑和数据明确分离
- 后端集成已准备
仍然没有“炫酷 UI”——但这是一个 坚实、面向真实世界的前端基础。
为什么这个阶段很重要(尤其是对于作品集)
大多数作品集展示了构建了什么。
这个阶段展示:
- 决策是如何做出的
- 架构是如何规划的
- 可维护性是如何被优先考虑的
- 真实团队是如何思考的
这就是区别所在:
“我做了一个作品集”
与
“我设计并实现了一个产品。”
接下来是什么?
第 3 阶段将专注于后端设置和 API 基础。
既然前端已经能够干净地调用 API,是时候正式构建它们了。