从零开始构建一个现代化前端项目:我的一次真实实践之旅

陈静♪
2025-06-30 11:48
阅读 431

作为一名工作五年的前端开发工程师,我经历过无数项目的搭建与迭代。但有一次让我印象尤其深刻——那是一次为一家创业公司从零开始搭建新平台前端系统的任务。这个项目不复杂,却极具代表性,涵盖了我们日常工作中最常遇到的技术选型、协作模式、性能优化等问题。

今天我就想以第一人称的角度,分享这段实战经历,希望能对正在或将要面对类似问题的你有所帮助。


背景介绍:一次从头开始的机会

背景介绍:一次从头开始的机会

那是一个典型的创业场景:团队只有5个人,产品经理刚画完原型,后端同学还在和架构师扯微服务拆分的事,整个前端团队就我一个人。老板希望我们能在三个月内上线MVP版本,同时预留后续扩展的可能性。

摆在面前的问题很明确:用什么框架、如何组织代码结构、怎么处理多人协作、怎么保证质量与可维护性?

我知道这不是简单的“搭个React项目”就能搞定的事情,而是要在技术和流程层面都考虑清楚。于是,我决定先静下心来梳理目标:

  • 快速上手,方便新人加入
  • 可持续维护,易于扩展
  • 用户体验好,加载快、交互流畅
  • 支持未来可能的多端部署(比如SSR或者PWA)

这四个目标构成了我这次从0到1搭建项目的指南针。


挑战来了:从技术选型到工程化落地

前端性能优化图表-1

挑战来了:从技术选型到工程化落地

第一个问题是技术栈选择。当时的主流方案有React + TypeScript、Vue 3 + Composition API、Angular等。考虑到我对React更熟悉,且TypeScript已经成为标配,我最终选择了 React + TypeScript + Vite 的组合

但真正困难的不是选了什么,而是如何让这些技术在项目中发挥最大价值

技术栈只是起点,工程化才是关键

  • 组件库选用Ant Design,因为业务偏后台系统,它提供的组件足够全面。
  • 构建工具选择Vite而非Webpack,是出于开发体验上的考量(热更新秒级响应)。
  • 状态管理一开始使用的是Redux Toolkit,后来发现有些重,最终换成了Zustand。
  • 样式方面,采用了Tailwind CSS作为主样式框架,配合SCSS变量统一主题色。
  • 测试用了Jest + React Testing Library。
  • CI/CD集成GitHub Actions实现自动构建与部署。
  • 部署选择了Netlify,可以一键发布、回滚、预览PR分支。

这些都是比较成熟的选择,但真正落地的时候才发现,每一步都不容易。


我的解决方案:模块化 + 规范先行 + 工程保障

为了应对项目快速推进和长期维护的需求,我做了以下几件事:

1. 前期设计清晰的目录结构

src/
├── assets/              # 静态资源
├── components/          # 公共组件
│   ├── shared/          # 共享组件
│   └── modules/         # 模块组件
├── hooks/               # 自定义hooks
├── routes/              # 页面路由配置
├── layouts/             # 布局组件
├── services/            # 接口封装
├── stores/              # 状态管理
├── styles/              # 公共样式文件
├── types/               # 类型定义
├── utils/               # 工具函数
├── App.tsx
├── main.tsx

这样的结构不仅有助于代码组织,也便于后期维护和重构。

2. 搭建基础模板+标准化脚手架

我基于Vite脚手架做了一些定制:

  • 添加.prettierrc.eslintrc.js确保代码风格一致
  • 加入husky + lint-staged,在提交前格式化代码
  • 使用commitlint规范 Git 提交信息
  • 设置别名(@指向src目录)
  • 引入PostCSS + Tailwind CSS插件
  • 初始化ESLint规则支持TypeScript
  • 搭建基础Layout组件、404页面、路由守卫等

这些看似简单的初始化配置,其实大大提升了团队后续的工作效率。

3. 状态管理轻量化尝试

最初我用了Redux Toolkit,但在一个不到20页的小项目里,每次都要写slice文件、action、reducer,感觉特别麻烦。加上接口返回数据结构不统一,很多公共状态很难抽象。

于是我改用了Zustand,写起来就像这样:

import { create } from 'zustand'

interface UserState {
  name: string
  updateName: (name: string) => void
}

const useUserStore = create<UserState>((set) => ({
  name: '',
  updateName: (name) => set({ name }),
}))

export default useUserStore

简单、直观、易测试,而且可以直接和React DevTools集成调试。对于中小型项目来说,非常够用。


实战中的关键代码片段分享

这里分享几个项目初期的关键配置或代码片段,供你参考。

Vite + TS + ESLint + Prettier 初始化配置节选

vite.config.ts

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tsconfigPaths from 'vite-tsconfig-paths'

export default defineConfig({
  plugins: [
    react(),
    tsconfigPaths(), // 支持ts路径别名
  ],
})

.eslintrc.cjs

module.exports = {
  root: true,
  env: {
    browser: true,
    es2021: true,
    node: true,
  },
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:react/recommended',
    'plugin:prettier/recommended',
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 2020,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
    },
  },
  plugins: ['react', '@typescript-eslint'],
  rules: {
    // 自定义规则
  },
}

tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
  theme: {
    extend: {},
  },
  plugins: [],
}

开发过程中的坑与填坑经验

任何从0到1的过程都会遇到坑,下面是我在实际开发中踩过的几个比较典型的坑以及解决思路:

1. Tailwind 和 SCSS 变量冲突

我原本打算通过SCSS变量来控制Tailwind的主题色,比如 $primary-color: #4f46e5;,然后在Tailwind中引用。结果发现Tailwind是在构建时生成样式的,并不会识别SCSS变量。

解决办法: 将颜色定义抽离出来放在tailwind.config.js中,直接作为theme参数传进去:

theme: {
  extend: {
    colors: {
      primary: '#4f46e5',
    }
  }
}

2. Zustand状态持久化问题

Zustand默认是内存状态,刷新页面会丢失。在项目里某些用户偏好设置需要持久化存储。

解决办法: 引入zustand/middlewarepersist中间件:

import { create } from 'zustand'
import { persist, createJSONStorage } from 'zustand/middleware'

interface SettingsState {
  theme: 'dark' | 'light'
  toggleTheme: () => void
}

const useSettingsStore = create(
  persist<SettingsState>(
    (set) => ({
      theme: 'light',
      toggleTheme: () => set((state) => ({ theme: state.theme === 'light' ? 'dark' : 'light' })),
    }),
    {
      name: 'settings-storage',
      storage: createJSONStorage(() => localStorage),
    }
  )
)

export default useSettingsStore

3. 开发环境跨域请求失败

前后端分离开发时遇到了CORS问题,虽然Vite提供了代理配置,但一开始没配置好。

解决办法: 在vite.config.ts中添加如下代理配置:

server: {
  proxy: {
    '/api': {
      target: 'http://backend.example.com',
      changeOrigin: true,
      rewrite: (path) => path.replace(/^\/api/, ''),
    },
  },
},

这样 /api/users 就会被代理到 http://backend.example.com/users


效果总结:项目上线后的真实反馈

大约两个半月之后,我们完成了MVP版本并正式上线。整体来看,效果还是不错的:

  • 开发效率高:得益于清晰的结构和工具链支持,新同学一天内就能理解项目并着手开发
  • 性能表现良好:Lighthouse评分85+,首屏加载时间控制在2s以内
  • 后续迭代顺畅:代码解耦充分,模块之间依赖低,新增功能改动少
  • 团队协作顺利:Git规范化提交和Code Review流程降低了沟通成本

更重要的是,项目上线后客户反馈不错,尤其是操作流程顺畅、页面响应速度快,这让产品同学也非常满意。


写给正在构建项目的你的一些经验

在这趟从0到1的旅程中,我学到了一些经验,也积累了不少教训。以下是我觉得值得分享的几点建议:

✅ 明确目标比技术选型更重要

不要盲目追求新技术,而要优先考虑当前项目的规模、团队构成和未来发展方向。有时候“够用就好”。

✅ 工具链虽小,影响深远

一个良好的开发环境和工程体系不仅能提升效率,更能降低出错率。前期多花点时间打磨工具链,后面会省下无数Debug时间。

✅ 保持开放心态,随时调整方向

技术方案不是一成不变的。例如我们中途从Redux切到Zustand,就是根据项目体量做出的灵活决策。

✅ 多关注用户体验,哪怕只是一个按钮

前端工程师的价值不仅是写代码,更是思考如何让用户操作更顺滑。例如防抖、加载动画、错误提示、表单验证提示等细节都值得深入打磨。

✅ 学会利用浏览器开发者工具

Chrome DevTools、Lighthouse、Performance面板是我日常排查性能瓶颈的重要工具。特别是Lighthouse,能够帮助你看到页面加载的真实表现,并提出优化建议。


最后的感悟:前端不止是写代码

这篇文章写到这里,我已经回想了很多当时熬夜搭项目的夜晚,也在脑海中一次次回顾自己为什么坚持要做这件事。

我始终相信,一个好的前端工程师不仅仅是代码写得快,更重要的是能够站在产品和用户的视角去思考问题。在项目早期的每一个选择背后,不只是技术考量,更有对未来可能性的判断。

如果你也正面临“从0开始”的挑战,请记住:

优秀的前端项目,不是一开始就完美的,而是在一次次实践中逐步打磨出来的。

希望这篇文章能成为你前行路上的一个小小灯塔,照亮你下一个新项目的起航之路。

如果你有任何问题,欢迎在评论区留言交流。我们一起成长 💪


End.

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝