从一个“空目录”到上线:我的现代化前端项目构建实战
背景

去年我加入了一个新的创业公司,负责搭建一个全新的 B2B 后台管理系统。当时的情况是:团队刚起步,产品原型刚出,技术选型还没有定下来。老板说:“你是有经验的工程师,这些你说了算。”——好家伙,压力山大。
我面临的第一个问题就是:怎么从零开始搭建一个现代、可维护、性能良好、开发效率高的前端项目?
那时候市面上各种框架、脚手架工具层出不穷,Vue、React、Vite、Webpack、TypeScript、Pinia、Tailwind……每个都有优势,但如何组合起来既高效又稳定?再加上时间紧迫,产品希望尽快看到效果。于是,我决定走一条“稳中求快”的路子。
这篇文章不是教科书式的教程,而是我在实际工作中踩过的坑、解决的问题和总结的经验,希望能帮你在构建项目时少走弯路。
遇到的挑战

1. 技术选型:太多选择反而成了负担
一开始我陷入了“选择困难症”。要不要用 React 还是 Vue?是否要引入 TypeScript?用 Vite 还是 Webpack?要不要上状态管理库?UI 组件库选 Element Plus、Ant Design,还是 Tailwind?
每种组合都有优缺点,但作为一个刚起步的项目,最重要的是:快速开发 + 易于维护 + 性能优秀。
最终我选择了:
- Vue 3 + Vite + TypeScript + Pinia + Tailwind CSS
- 构建流程使用 GitHub Actions
- UI 使用 Naive UI(比 Element 更灵活轻量)
- 状态管理统一用 Pinia(Vuex 已被官方弃用)
这不是最优解,但对当时来说是最合适的。
2. 构建初期配置复杂
刚开始搭建项目骨架的时候,虽然有 Vite 的模板,但真正要做一些定制化配置的时候才发现,比如:
- 多环境变量配置(开发/测试/生产)
- 自动导入组件、API 接口、路由懒加载
- 兼容性处理(比如 Polyfill)
- 打包优化(Chunk 分割、压缩)
这些问题让我在项目初始化阶段就花了不少时间调整配置。
3. 开发体验需要打磨
我们是前后端分离项目,接口还没完全就绪。为了不让前端卡死在等待接口数据上,我们做了两件事:
- 使用 mock 数据模拟 API 响应
- 搭建本地 mock server(基于 vite-plugin-mock)
此外,还要考虑热更新、HMR 效率、ESLint、Prettier、Git 提交规范等工程化问题。
4. 浏览器兼容性和性能优化
虽然是后台系统,但我们的用户群体中有不少还在使用老版本 Chrome 或 IE 兼容模式。虽然 IE 官方已经停止支持,但在国内依然有很多遗留系统必须兼容。
这要求我们必须做:
- JavaScript polyfill
- CSS 特性回退
- 图片懒加载
- 打包体积控制
另外,首屏加载速度也是一个关键指标,特别是对于低网速用户。
解决方案
技术栈选择依据
| 技术 | 为什么选择它 |
|---|---|
| Vue 3 | 上手成本低,生态成熟,适合中小型项目 |
| Vite | 快如闪电的开发服务器,TS 和 JSX 支持好 |
| TypeScript | 强类型带来更强的代码稳定性,适合多人协作 |
| Pinia | 简洁的状态管理模式,替代 Vuex 成为官方推荐 |
| Tailwind | 样式按需生成,不冗余,灵活性强 |
| Naive UI | 中文文档齐全,组件丰富且风格简洁 |
项目结构设计
src/
├── assets/ # 静态资源
├── components/ # 公共组件
├── layouts/ # 页面布局组件
├── pages/ # 页面级组件
├── router/ # vue-router 配置
├── store/ # pinia 状态管理
├── services/ # 接口请求封装
├── utils/ # 工具函数
├── App.vue # 主入口
└── main.ts # 入口文件
这种结构清晰易维护,方便后期模块拆分和代码复用。
核心配置项
Vite 配置(简化版)
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers'
import { resolve } from 'path'
export default defineConfig({
plugins: [
vue(),
vueJsx(),
AutoImport({
imports: ['vue', 'vue-router', 'pinia'],
}),
Components({
resolvers: [NaiveUiResolver()],
}),
],
resolve: {
alias: {
'@': resolve(__dirname, './src'),
},
},
})
多环境变量配置
我们采用 .env 文件方式定义不同环境变量:
.env # 全局默认
.env.development # 开发环境
.env.staging # 预发布环境
.env.production # 生产环境
在代码中通过 import.meta.env.VITE_API_URL 获取环境变量。
Mock 数据服务
使用了 vite-plugin-mock 插件,在 src/mock 目录下写 mock 接口:
// src/mock/user.ts
export default [
{
url: '/api/users',
method: 'get',
response: () => {
return {
code: 0,
data: [
{ id: 1, name: '张三' },
{ id: 2, name: '李四' }
]
}
}
}
]
这样即使后端没准备好,前端也能继续开发和联调。
实战踩坑记录
1. HMR 慢得令人崩溃
早期使用 Vue + Vite 的时候,HMR 更新速度忽快忽慢,特别是在页面组件复杂或者引用大量依赖时。
解决方法:
- 减少不必要的自动导入插件(比如有些工具函数其实可以手动引入)
- 控制组件嵌套层级,不要过深
- 合理使用 computed 属性减少重复计算
2. Tree-shaking 不生效
我们在某个第三方库里发现打包后的体积异常大,明明只用了几个函数,却引入了整个库。
排查发现是这个库并没有提供 ESM 版本,导致无法进行 tree-shaking。
解决方法:
- 换用更标准的库
- 手动 import 子路径来避免整库引入
3. 打包之后的白屏问题
有一天 CI 发布后首页打开全是空白,没有任何错误提示。
后来发现是因为动态导入的组件没有正确打包成 chunk,而异步加载失败也没做 fallback。
解决方法:
- 加上 loading 和 error 处理逻辑
- 使用
@vitejs/plugin-legacy增加对旧浏览器的支持
4. 用户权限控制太粗糙
我们最开始只是用简单的布尔值判断是否有权限,结果后面随着角色越来越多,条件判断变得非常复杂。
解决方法: 引入 RBAC 权限模型,将权限抽象成字符串集合,用指令实现按钮级别的权限控制。
示例:
// 自定义权限指令
app.directive('permission', (el, binding) => {
const permissions = useStore().user.permissions
if (!permissions.includes(binding.value)) {
el.remove()
}
})
使用方式:
<button v-permission="'create_user'">新建用户</button>
最终效果与收益
项目上线后,用户体验反馈不错:
- 首屏加载时间平均 < 1s(CDN + Gzip)
- 开发效率提升明显(Vite 热更新快,Mock 系统完善)
- 项目结构清晰,新人上手容易
- 权限控制系统灵活,适配新业务很快
更重要的是,这套体系在后续多个项目中都得到了复用和迭代,形成了我们内部的一套“启动模板”。
我的建议
如果你也正在准备从头搭建一个项目,以下几点是我的真实体会:
✅ 技术选型别贪多,先跑起来再说
我见过太多人纠结框架对比,最后项目迟迟不动工。先跑起来一个小功能,比写一篇分析报告更有价值。
✅ 工程化一定要尽早介入
很多人前期只写功能,到了后期才开始加 eslint、prettier、git hooks,结果满地报错。一开始就搭好基础工程化规则,开发体验会好很多。
✅ 重视组件复用和状态管理
不要把所有状态都放在页面里。提前规划哪些数据应该全局共享,用 Pinia 等状态库集中管理,可以大大减少耦合。
✅ 前端也是服务的一部分,要考虑用户的真实场景
比如:你的用户是不是经常在网速差的环境下访问?有没有老人机?有没有 IE 用户?这些都要考虑到,并做出取舍。
✅ 利用好开发者工具
Chrome DevTools、Vue Devtools、Vite Server 的调试能力都很强大。遇到性能瓶颈或渲染异常时,记得善用这些工具。
结语:一次成长之旅
回头来看,那次项目搭建其实不只是在写代码,更是一次工程思维的训练。
作为前端工程师,我们不仅要写漂亮的组件,更要思考架构是否合理、性能是否可控、维护是否方便。从一个空目录开始到最后上线,中间经历了很多细节的推敲和决策的反复,但正是这些真实的挑战,才让我们成长为更好的开发者。
如果你也在搭建自己的项目,不妨勇敢一点、试错一点、反思一点。记住,没有完美的起点,只有不断进化的过程。
欢迎留言交流,我们一起聊聊你们的项目是怎么搭起来的 😊

评论 0