从零搭建一个现代化前端项目的实战经验分享

星河程序员
2025-06-16 15:08
阅读 478

开篇:为什么想写这篇文章?

开篇:为什么想写这篇文章?

作为一名在互联网公司摸爬滚打了几年的前端开发者,我经历过多个从零开始构建项目的情况。有的是公司新业务线需要启动,有的是老项目维护成本太高必须重构,也有的是我自己业余时间折腾的一些小项目。

无论哪种情况,“从零开始”从来都不是一件容易的事。你不仅要选技术栈、搭框架、定规范,还要考虑后续的可维护性、性能、协作效率等等。特别是在团队逐渐变大后,很多细节问题就开始浮现出来了。

今天,我想结合最近参与的一个中型管理系统项目,来分享一下我是如何从零构建一个现代化前端项目的,包括遇到的问题、技术选型的心路历程、踩过的坑以及一些个人建议。希望对刚准备开新项目的你有所帮助。


背景介绍:一次典型的中后台系统重构

背景介绍:一次典型的中后台系统重构

事情要从半年前说起,我们部门负责的一套企业内部的资产管理平台已经运行了好几年,前后端都是基于 AngularJS(没错,不是 Angular)和 Java JSP 的架构。

由于历史原因,代码结构混乱、依赖杂乱无章、页面加载慢、调试困难、难以维护等问题越来越突出。最终领导拍板决定:全面重构这套系统

而我的任务是:作为主负责人之一,从零构建新的前端项目,并尽可能保留原有功能模块的迁移路径。

我们的目标:

  1. 使用主流现代技术栈,方便招人、维护、迭代;
  2. 构建速度快、打包体积小
  3. 支持多人协作开发,有统一规范
  4. 良好的性能表现,尤其关注首次加载速度;
  5. 未来具备扩展能力,比如 PWA、国际化等。

搭建过程中的挑战

搭建过程中的挑战

刚开始接到这个任务时,说实话还挺兴奋的。终于可以不受旧项目限制,自由选择自己喜欢的技术栈了。

但现实很快打脸。虽然有很多技术可以选择,但如何做最优组合如何保证长期可维护性,才是真正考验人的地方。

具体挑战包括:

  • 选型太多,反而难以下决定。Vue vs React?Vite vs Webpack?
  • 如何设计合适的目录结构? 既要清晰又要灵活。
  • 怎么管理多人协作中的冲突?
  • 性能优化要从一开始就考虑
  • 跨浏览器兼容性不能忽视,尤其是一些 IE 环境还在用。
  • 自动化流程怎么做?ESLint、TypeScript、Prettier、Husky、Commitlint …… 全都要配好。
  • 如何快速接入已有的接口和服务?

这些问题都直接关系到项目的成败,而且没有标准答案。每一步都需要结合实际需求做出权衡。


技术选型与架构设计

主流技术栈的选择

前端框架:Vue 3 + TypeScript

我们最初讨论过是否使用 React,但在团队调研后发现,大部分成员对 Vue 更熟悉,加上 Vue 3 对于中后台系统的友好度更高(特别是 Composition API 和响应式语法糖),最终选择了 Vue 3 + TypeScript 的方案。

构建工具:Vite

一开始我其实有点保守,打算用 Webpack,毕竟它成熟稳定,插件生态丰富。但我们尝试了 Vite 后就彻底被打动了。

  • 开发服务器冷启动速度飞快,几乎秒开
  • HMR 反应灵敏
  • 内置对 TypeScript、CSS 预处理器、JSX、Vue 单文件组件的支持
  • 支持按需编译,非常适合现代前端工程

所以最后毫不犹豫地选了 Vite。

状态管理:Pinia 替代 Vuex

Vuex 已经有些过时了,官方推荐 Pinia。我们也第一时间用了上来,结果非常顺利。

  • 类型友好(尤其是配合 TypeScript)
  • 模块化结构清晰
  • 写法更简洁直观

UI 库:Element Plus(搭配暗黑主题)

因为我们做的是一个企业级管理系统,UI 层面需要大量组件支撑。Ant Design Vue 当然也很不错,但我们团队之前有使用 Element 的经验,加上 Element Plus 对 Vue 3 支持很好,最终选定了它。

另外,用户反馈说他们希望界面不要太刺眼,所以我们还加了个暗黑模式切换功能。

项目结构设计

src/
├── assets/            # 静态资源
├── components/        # 通用组件
├── layouts/           # 布局组件
├── router/            # vue-router 配置
├── store/             # pinia 模块
├── services/          # 接口请求封装
├── views/             # 页面组件
├── utils/             # 工具函数
├── App.vue
└── main.ts

这样的结构兼顾了清晰度和可扩展性。每个模块职责明确,适合团队协作。


实施过程中的一些关键点

1. 模块划分与路由懒加载

项目初期我就意识到,随着功能增加,包体积会成为瓶颈。于是我们在路由层面做了懒加载配置:

const routes: Array<RouteRecordRaw> = [
  {
    path: '/dashboard',
    name: 'Dashboard',
    component: () => import('../views/Dashboard.vue'),
    meta: { title: '仪表盘' }
  },
  {
    path: '/assets',
    name: 'Assets',
    component: () => import('../views/Assets.vue'),
    children: [
      {
        path: 'list',
        name: 'AssetList',
        component: () => import('../views/Asset/List.vue')
      },
      ...
    ]
  }
]

这样可以在不同层级实现异步加载,提升首屏性能。

2. 请求服务封装:Axios + 中间件机制

为了统一处理错误码、拦截器、token 刷新等逻辑,我们对接口层做了统一封装。

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

const request = axios.create({
  baseURL: '/api',
  timeout: 10000
})

request.interceptors.request.use(config => {
  const token = localStorage.getItem('token')
  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }
  return config
}, err => Promise.reject(err))

request.interceptors.response.use(response => {
  return response.data
}, async error => {
  // 错误处理逻辑
  return Promise.reject(error)
})

export default request

之后我们在各个 service 文件中复用它:

// services/assets.ts
import request from './request'

export function fetchAssets(params) {
  return request.get('/assets', { params })
}

export function createAsset(data) {
  return request.post('/assets', data)
}

这样做之后,不仅统一了调用方式,也便于统一添加日志、埋点等功能。

3. 国际化支持(i18n)

虽然目前只有中文,但我们还是提前引入了 vue-i18n:

import { createI18n } from 'vue-i18n'
import zh from '@/locales/zh.json'
import en from '@/locales/en.json'

const i18n = createI18n({
  legacy: false,
  locale: 'zh',
  fallbackLocale: 'en',
  messages: {
    zh, en
  }
})

app.use(i18n)

然后在组件里就可以通过 $t 来调用翻译内容:

<h1>{{ $t('welcomeMessage') }}</h1>

这种做法让我们为后期多语言支持埋下伏笔。

4. 性能优化实践

  • 使用 v-oncememoization 减少重复渲染
  • 图片懒加载(<img v-lazy="url">
  • 引入 Lighthouse 进行性能评分指导优化
  • 合理拆分 chunk,避免单个包过大
  • Gzip 压缩部署 CDN 加速访问
  • 首屏优先加载策略
  • 使用骨架屏预占位(element-plus-skeleton)

我们最终实现了首屏加载小于 1s,Lighthouse 分数稳定在 90+。


踩坑记录和解决方法

坑一:Vite + 微前端环境兼容问题

我们的项目需要集成进一个微前端架构中(基于 qiankun)。Vite 默认的打包策略是以现代 ES Module 的方式输出,但在某些不支持动态导入的子应用环境中就会报错。

解决方案

改用 build.lib 模式,并指定输出格式为 umd:

build: {
  lib: {
    entry: resolve(__dirname, 'src/entry.ts'),
    name: 'MyApp',
    fileName: (format) => `my-app.${format}.js`
  }
}

同时,在 qiankun 的生命周期钩子中挂载:

// 子应用入口
export async function mount(props) {
  const app = createApp(App)
  app.mount('#sub-root')
}

坑二:IE11 不兼容 Proxy & Reflect

Vue 3 默认使用 Proxy 进行响应式追踪,但在 IE11 上无法正常运行。

解决思路

  • 降级到 Vue 2?代价太大。
  • 使用 polyfill 是唯一出路。

我们在项目中引入了 proxy-polyfill,并在入口文件顶部注入:

import 'proxy-polyfill'

虽然性能略有下降,但在兼容性和功能完整性上达到了平衡。

坑三:TypeScript + Vue 3 的组件类型定义问题

Vue 3 中虽然支持 <script setup> 语法,但与 TypeScript 结合使用时,某些泛型或函数参数推导会出现问题。

例如:

const props = defineProps<{
  items: Item[]
}>()

有时候 IDE 会提示找不到变量,或者类型未被正确推断。

解决方法

升级 Vue 相关的 TypeScript 插件版本,并确保 VSCode 安装了 Vue Language Features (Volar) 插件。

此外,尽量使用显式的 definePropsdefineEmits,而不是隐式提取。


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

经过两个多月的开发和测试,项目如期上线。整体效果超出预期:

指标 上线前 上线后
首屏加载时间 6~7s <1s
打包体积 ~5MB ~1.5MB
新人上手难度 高(文档少) 中等(有文档+脚手架)
Lighthouse Score ~55 ~92
Bug 数量 多且分散 少且集中

更重要的是,这次重构之后,我们建立了一套完整的开发流程和规范,使得后续开发效率大大提升。


经验分享:给正在起步项目的你几个建议

1. 技术选型不要盲目追求热门,适合团队最重要

我见过太多项目为了追热点选了个完全陌生的技术栈,结果半途而废。建议根据团队现有能力 + 明确的业务场景来做决策。

2. 自动化流程要尽早完善

别等到最后才配 ESLint、TypeScript、Git Hooks。越早配上越好,否则后面改起来就像修一栋没地基的大楼,处处受限。

3. 性能优化要前置

很多人觉得“先完成功能再优化”,其实不然。像懒加载、目录结构设计这些,一开始就决定了项目能不能跑得快。等出问题再改,代价极大。

4. 文档和模板也要重视

我们最后整理了一个自己的 CLI 初始化模板(基于 plop.js),每次新建模块或页面都能一键生成基础代码。新人入职两天就能独立提 PR。

5. 调试技巧和工具真的很重要

推荐几个我常用的工具:

  • Vue Devtools:Vue 生态标配调试神器
  • Source Map 查看:帮助定位压缩后的错误来源
  • Chrome Performance 面板:用来分析加载瓶颈
  • Mock.js + Mockoon:本地模拟接口数据很方便
  • Lighthouse:性能打分工具,强烈推荐加入常规检测流程

写在最后:关于成长和技术选择的思考

这几年下来,我一直坚信一句话:技术没有高下之分,只有合适与否

每一个项目、每一个团队、每一个业务阶段都会面临不同的挑战。作为前端开发者,我们要学会的不只是写出漂亮的代码,更是要在复杂需求中找到最适合的解决方案。

这次从零搭建新项目的经历,让我对整个前端工程体系有了更深的理解。也让我更加坚定了一个信念:优秀的前端项目,应该是易读、易维护、易扩展、易协作的

如果你现在正准备开启一个新的项目,希望这篇文章能给你带来一些启发和帮助。

愿你在未来的开发路上,每一次 “从零开始”,都是一次成长的机会。

(本文部分内容涉及公司项目细节,已脱敏处理。欢迎留言交流!)

评论 0

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