从一次真实项目重构说起:如何从零开始构建一个现代化前端项目

产品经理别看我
2025-06-19 03:08
阅读 481

开篇:为什么我要写这篇文章?

开篇:为什么我要写这篇文章?

大家好,我是一名在一线干了五年的前端工程师。这五年里,我经历过初创团队的“敏捷狂奔”,也体验过大型企业的规范体系。但印象最深的一次,是前年我接手一个全新的项目——说是新项目,其实更像是个半成品改造工程。

客户给了我们一段老旧的 Vue2 代码库,功能基本跑通了,但结构混乱、性能差、维护困难。我们的任务是从头开始重建这个系统,目标不仅是提升用户体验,还要为未来的持续迭代打下基础。

这篇文章就围绕那次重构经历展开。希望通过我的个人视角和真实工作场景,带你了解一个现代前端项目究竟是怎么一步步搭起来的。


问题描述:项目初期面临的挑战

响应式布局概念图-1

问题描述:项目初期面临的挑战

我们接收到的原始项目,存在几个明显的问题:

  • 技术栈落后:基于 Vue2 + Webpack3,部分依赖版本陈旧,升级难度大。
  • 代码结构混乱:所有组件都放在一起,没有清晰的分层设计。
  • 缺乏工程化支持:没有统一的 lint 规范、测试覆盖、构建流程。
  • 用户体验差:首屏加载慢、交互响应延迟,页面抖动严重。
  • 协作困难:多人开发时容易产生冲突,代码风格不一致。

这些痛点让整个团队举步维艰。项目上线时间紧迫,我们只能边开发边重构,压力山大。


解决方案:选择合适的技术栈与架构设计

现代网页界面设计示例-2

解决方案:选择合适的技术栈与架构设计

首先,我们明确了技术选型的方向:

技术栈升级

  • 主框架切换为 Vue3(Composition API)
    • 比起 Options API 更易维护,适合中大型项目
    • 配合 TypeScript 使用更爽(后文详细说)
  • 构建工具换为 Vite
    • 开发服务器启动快,热更新秒级响应
    • 支持开箱即用的 TS、JSX、CSS预处理器等
  • 状态管理采用 Pinia 替代 Vuex
    • API简洁,模块化自然,TS友好
  • UI库选用 Element Plus
    • 官方支持 Vue3,社区活跃
  • 样式方案使用 Sass + BEM + CSS Modules 混合策略
    • 组件内样式隔离,全局变量统一管理

架构设计思路

我们将项目划分为以下几个核心层级:

src/
├── assets/           # 图片、字体等资源
├── components/       # 可复用的基础 UI 组件
├── layouts/          # 页面布局组件,如 Header、Sidebar 等
├── pages/            # 路由页面组件
├── router/           # Vue Router 配置文件
├── services/         # 接口服务层,封装 axios 请求
├── stores/           # Pinia 存储定义
├── utils/            # 工具类方法
├── views/            # 页面模板目录(早期习惯叫法)
└── App.vue & main.ts # 入口文件

这种分层方式让职责划分清晰,每个角色都能快速定位到自己的工作区域。


代码实践:关键配置与代码片段分享

初始化项目结构

使用 Vite 快速创建项目:

npm create vite@latest my-project --template vue-ts
cd my-project
npm install

安装常用依赖:

npm install -D sass sass-loader autoprefixer postcss cssnano pinia element-plus unplugin-vue-components @vitejs/plugin-vue @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint prettier eslint-config-prettier husky lint-staged

配置 ESLint + Prettier + Husky

eslintprettier 的配合上,我们做了一些取舍,最终选择了这样的 .eslintrc.js

// .eslintrc.js
module.exports = {
  root: true,
  env: {
    browser: true,
    es2021: true,
    node: true
  },
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'prettier'
  ],
  parser: '@typescript-eslint/parser',
  plugins: ['@typescript-eslint', 'vue'],
  rules: {
    // 自定义一些规则,例如:
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
  }
};

结合 huskylint-staged,我们配置了 commit 前自动格式化并校验代码,极大提升了代码质量。

路由 + 布局设计

在 Vue Router 中,我们采用了懒加载的方式引入路由组件,并按模块组织路由:

// src/router/modules/user.ts
export default {
  path: '/user',
  name: 'User',
  component: () => import('@/layouts/AdminLayout.vue'),
  children: [
    {
      path: 'list',
      name: 'UserList',
      component: () => import('@/pages/user/ListPage.vue')
    }
  ]
}

这种方式可以让我们在后续扩展更多模块时,保持结构整洁。

异常处理机制

针对接口请求失败的情况,我们统一封装了一个拦截器:

// src/services/request.ts
import axios from 'axios'

const service = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL || '/api',
  timeout: 10000
})

service.interceptors.response.use(
  response => {
    const { data } = response
    if (data.code !== 200) {
      // 这里可以抛出错误或者调用全局提示
      console.error(data.message)
      return Promise.reject(new Error(data.message))
    }
    return data
  },
  error => {
    // 处理网络错误或超时
    console.error('API Error:', error.message)
    return Promise.reject(error)
  }
)

export default service

踩坑经验:那些让人崩溃又成长的瞬间

1. 升级带来的 Typescript 类型问题

当我们从 Vue2 切换到 Vue3 + TypeScript 后,第一关就是类型定义。

比如以前随便写的组件 props,现在都需要写明 interface。刚开始大家都抱怨:“又要加类型?好麻烦!”

但我们坚持下来,反而发现好处多多:

  • 编译阶段就能捕获潜在的 bug
  • IDE 自动补全更好用了
  • 接口文档可以直接从类型推导出来

所以我的建议是:拥抱 TypeScript,别怕前期的学习成本。

2. 生产环境打包体积爆炸问题

Vite 默认的打包策略对于复杂项目来说可能会生成非常大的 bundle 文件。

我们在部署时发现首次加载超过 5MB,加载时间感人。

后来我们做了几件事情:

  • 使用 rollup 的手动分包配置,在 vite.config.ts 中增加:
build: {
  rollupOptions: {
    output: {
      manualChunks(id) {
        if (id.includes('node_modules')) {
          return id.toString().split("node_modules/")[1].split("/")[0]
        }
      }
    }
  }
}
  • 对第三方库进行按需导入,借助 unplugin-auto-importunplugin-vue-components 实现按需自动导入组件和 API。

优化后首屏 JS 打包到 400KB 左右,速度快了不少。

3. 开发环境本地代理配置踩坑

Vite 提供了代理配置功能,但是刚接入的时候经常遇到代理失效的问题。

最后发现是因为 vite.config.js 里的 proxy 设置只对 /api 开头的路径生效,而某些接口请求路径是 /rest/login,没有走代理,导致跨域报错。

解决办法是在请求拦截器中判断当前环境动态拼接 URL。


效果总结:重构后的成果与收益

经过两个月的集中开发和重构,项目终于上线,效果远超预期:

  • 首屏加载时间从原来的 4s+ 缩短到 1.2s
  • 构建效率从 8min 缩短到 1.5min
  • 团队协作顺畅,代码 review 时间减少一半
  • 用户反馈卡顿情况大幅下降
  • 支持未来新增模块变得轻松

更重要的是,我们建立了一套完整的工程化流程,包括:

  • Git Commit Hooks 校验
  • GitHub Actions CI 流程
  • 包含 E2E 测试的自动化测试体系(未完全展开)
  • 微前端集成能力预留

经验分享:给读者的几点建议

如果你也在准备搭建一个现代化前端项目,这里是一些实用的小建议:

✅ 选好骨架很重要

  • Vue3 + Vite 是目前主流组合,值得投入
  • 技术选型要综合考虑团队熟悉度、生态成熟度和长期维护能力
  • 尽早加入 TypeScript,避免后期反向适配

🧱 重视项目结构设计

  • 不要一开始就盲目追求“高内聚低耦合”,但要有清晰的层次感
  • 可以模仿流行的开源项目(如 Ant Design Pro、Vite + Vue3 官方模板)

🔍 性能优化不是上线后的事

  • 从第一天就要关注加载速度、包大小、渲染效率
  • 使用 Lighthouse、Performance 工具定期评估
  • 能懒加载的尽量懒加载,非必要内容推迟加载

🛠️ 工具链决定效率上限

  • 熟悉 Vite 插件系统,掌握常见插件的用法(比如自动导入、图标库、mock)
  • 善于利用 DevTools 调试技巧,节省排查 bug 时间
  • 提前配置好自动化测试(推荐 Cypress / Playwright 做 E2E)

👩‍💻 团队协作才是长久之计

  • 制定统一的编码规范,接入 EditorConfig + Prettier + ESLint
  • 合理使用 Git hooks 避免垃圾代码进入仓库
  • 写文档不要怕烦,特别是组件说明、API 接口定义

结语:构建一个项目,就像搭建一座房子

这次重构项目的过程,对我而言不仅是一个技术上的挑战,更是一种认知的升级。前端开发早已不再只是“写 JS 和 CSS”,而是一个涉及工程化、性能、用户体验、安全等多维度的综合性工程。

希望这篇带着个人实战经验的文章,能够帮你少走一点弯路。毕竟我们每天面对的不是完美的理想世界,而是一个个充满现实问题的业务需求。而这,也正是前端开发的魅力所在吧。

如果你也在做类似的项目,欢迎留言交流,一起进步!


评论 0

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