构建生产就绪的作品集:第二阶段 — 前端引导与架构设置

发布: (2026年1月13日 GMT+8 13:41)
11 min read
原文: Dev.to

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.jsx
  • SectionHeader.jsx

这些组件:

  • 不关心它们被 在哪里 使用
  • 不依赖路由
  • 易于在页面之间复用

components/layout

布局组件定义 结构,而非内容。

示例

  • NavBar
  • Footer
  • Layouts

这些组件:

  • 包裹页面
  • 管理共享 UI
  • 定义骨架和间距

components/sections

Section 代表 领域特定的 UI

示例

  • Hero
  • About
  • Projects
  • OpenSource

这些组件:

  • 对内容有感知
  • 针对特定页面
  • 可以独立演进

设计系统是结构化的

页面 vs 区块(有意的区分)

一种常见的反模式是混合路由和 UI 逻辑。
为避免这种情况,我做了明确的区分:

pages/
  • 路由级组件
  • 直接映射到 URL
  • 组装区块
  • 最少的逻辑
sections/
  • 在页面之间可复用
  • 表示逻辑内容块
  • 不关心路由

这确保了:

  • 路由保持轻量
  • UI 保持可组合
  • 重构更容易

它还允许:

  • 在不重写 UI 的情况下重构页面
  • 一致的布局复用

Hook:将逻辑与 UI 分离

我在早期引入了 hooks/ 层,而不是将逻辑直接嵌入组件中。

目的:

  • 隔离数据获取逻辑
  • 封装副作用
  • 提高可测试性
  • 降低组件复杂度

示例:

  • useProjects
  • useAchievements
  • useAbout

这使得组件:

  • 声明式
  • 更易阅读
  • 更易调试

当 API 演进时,只需更改 Hook —— UI 不受影响。

数据层:将 UI 与内容解耦

在此阶段,大多数内容存放在 data/ 目录下的 JSON 文件中。

为什么?

  • 内容变化频率高于 UI
  • 支持快速迭代
  • 模拟 API 驱动的开发
  • 简化早期测试

类似文件:

  • projects.json
  • experiences.json
  • hero.json

充当 临时后端。当真实 API 后期接入时,迁移会非常顺畅。

服务层:为后端集成做准备

即使后端尚未完全实现,我仍创建了 services/ 层。

该层:

  • 集中管理 API 调用
  • 隔离 HTTP 逻辑
  • 防止 API 使用泄漏到组件中

示例: api.js

收益:

  • 避免紧耦合
  • 支持 Mock
  • 以后 CI 测试更容易

样式与资源:提前保持组织有序

样式

所有全局样式放在:

styles/
├── globals.css
├── animations.css

这样可以避免:

  • CSS 分散
  • 行内混乱
  • 动画不一致

资源

资源按业务域分组:

  • hero
  • about
  • projects
  • logos

这提升了:

  • 可读性
  • 资源复用
  • 可维护性

Asset Overview

ESLint 与 Prettier:提前强制规范

在编写功能之前就配置了 Lint格式化

这确保了:

  • 风格一致
  • 差异可预期
  • PR 审核更轻松
  • 主观争论更少

作为负责人或审阅者,这在后期能节省大量时间。

第 2 阶段的成果

  • 前端使用现代工具启动
  • 可扩展的文件夹结构已就位
  • 路由已规划(未仓促)
  • 代码质量工具已配置
  • UI、逻辑和数据明确分离
  • 后端集成已准备

仍然没有“炫酷 UI”——但这是一个 坚实、面向真实世界的前端基础

为什么这个阶段很重要(尤其是对于作品集)

大多数作品集展示了构建了什么
这个阶段展示:

  • 决策是如何做出的
  • 架构是如何规划的
  • 可维护性是如何被优先考虑的
  • 真实团队是如何思考的

这就是区别所在:

“我做了一个作品集”

“我设计并实现了一个产品。”

接下来是什么?

第 3 阶段将专注于后端设置和 API 基础。

既然前端已经能够干净地调用 API,是时候正式构建它们了。

Back to Blog

相关文章

阅读更多 »

裸机前端

Bare-metal frontend 介绍 现代前端应用已经变得非常丰富、复杂且精细。它们不再只是简单的 UI 轮询数据。它们……

从混乱到秩序的前端

它是如何工作的 - 后端为微服务更新 GraphQL schema。 - 前端拉取最新的 schema,创建查询/变更并重新生成 type。 - 任何…