从零开始构建一个现代化前端项目:我在实践中踩过的坑与经验总结
开篇:为什么要重新思考“从零搭建”这件事?
去年年底,我接手了一个新的项目——为公司内部搭建一个全新的数据看板平台。这个项目没有历史包袱,完全是从零开始的。团队决定采用最前沿的技术栈,打造一个稳定、高效、可维护的系统。听起来挺理想化,但现实远比预期要复杂得多。
作为一名前端工程师,这并不是我第一次从零搭建项目,但这次的经历却格外深刻。从前端框架选择,到打包工具配置;从开发体验优化,到性能调优,每一个环节都充满了挑战和学习机会。
在这篇文章中,我会以第一人称的角度,分享这个项目从无到有的全过程。不只是告诉你“应该怎么做”,更重要的是我想让你知道,在真实工作中我们会遇到哪些问题、怎么解决它们,以及背后的一些决策逻辑。
问题描述:为什么说“从零开始”不是一件简单的事?
当我们说“从零开始”,很多人会下意识地想到创建一个 index.html 文件,然后引入几个 CDN 链接就开始开发了。但在企业级项目中,这种方式远远不够:
- 代码结构混乱:随着功能变多,文件夹结构不清晰会导致协作困难
- 开发效率低:缺乏模块化、热更新、代码校验等辅助工具
- 构建流程缺失:无法压缩、拆包、按需加载等基本优化手段
- 维护成本高:代码风格不一致、测试缺失,后续迭代变得痛苦
我们当时就面临着这些挑战。更棘手的是,项目需要支持 IE11(对,你没听错),同时又要兼顾移动端的响应式设计和良好的交互体验。技术选型必须在现代技术和兼容性之间取得平衡。
解决方案:选型与架构设计
1. 技术选型:Vue 还是 React?
最终我们选择了 Vue3 + TypeScript。理由如下:
- Vue3 的 Composition API 让组件逻辑更加清晰,尤其适合中大型项目
- Vue 官方生态相对完整(Vite、Vuex、Vue Router 等)
- 团队成员已有一定的 Vue 使用经验,学习成本更低
- Vue3 的 treeshaking 更彻底,有利于性能优化
TypeScript 是标配,它帮助我们在早期发现潜在错误,提高代码质量。
2. 构建工具选择:Vite vs Webpack
一开始想用 Webpack,毕竟它是老牌构建工具,社区成熟。但试了一圈之后发现启动慢、配置繁琐。特别是对于本地开发来说,每次启动都要等好几秒,严重影响效率。
后来我们果断切换到了 Vite。得益于 ES Modules 的原生支持,Vite 的本地开发服务器几乎是瞬时启动的,热更新速度也快很多。
3. 架构设计:项目目录结构
我们最终采用了类似这样的目录结构:
src/
├── assets/ // 静态资源
├── components/ // 公共组件
├── layouts/ // 页面布局
├── pages/ // 页面组件
├── router/ // 路由配置
├── store/ // Vuex 状态管理
├── services/ // 接口服务封装
├── utils/ // 工具函数
├── styles/ // 样式文件
├── App.vue
└── main.ts
这样的结构虽然看起来普通,但在实际开发中非常实用。比如,当你接手别人的页面时,只需要打开对应的 pages 文件夹就能找到所需的所有内容,大大降低了上手门槛。

代码实践:关键代码片段与配置示例
1. Vite 配置示例(vite.config.ts)
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import tsconfigPaths from 'vite-tsconfig-paths'
export default defineConfig({
plugins: [vue(), tsconfigPaths()],
build: {
outDir: 'dist',
sourcemap: false,
minify: true,
},
server: {
port: 3000,
},
})
2. ESLint + Prettier 配置(.eslintrc.js)
module.exports = {
root: true,
env: {
browser: true,
es2021: true,
node: true,
},
extends: [
'eslint:recommended',
'plugin:vue/vue3-recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
],
parserOptions: {
ecmaVersion: 2020,
parser: '@typescript-eslint/parser',
sourceType: 'module',
},
rules: {
'vue/multi-word-component-names': 0,
'@typescript-eslint/no-explicit-any': 0,
'prefer-const': 1,
},
}
3. 接口请求封装(services/request.ts)
import axios from 'axios'
const service = axios.create({
baseURL: import.meta.env.VITE_API_URL as string,
timeout: 5000,
})
service.interceptors.request.use(config => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
}, error => {
Promise.reject(error)
})
service.interceptors.response.use(response => {
if (response.data.code !== 200) {
alert(response.data.message)
return Promise.reject(new Error(response.data.message))
}
return response.data
}, error => {
console.error('接口错误:', error)
return Promise.reject(error)
})

export default service
踩坑经验:那些年我们掉进去的坑
1. Vue3 + TypeScript 类型推断问题
在使用 Vue3 的 defineProps 时,如果我们不显式声明类型,TS 有时并不能正确推断出类型,导致 IDE 提示错误或者类型丢失。解决方案是在 .d.ts 文件中手动定义 interface 或者使用泛型方式明确指定类型。
// 错误写法
const props = defineProps({
title: String,
})
// 正确写法
interface Props {
title: string
}
const props = defineProps<Props>({
title: String,
})
2. Vite 配置路径别名失效
这个问题让我一度怀疑人生。最后发现是忘记添加 tsconfig.json 中的 baseUrl 和 paths 设置,并且还需要安装插件 vite-tsconfig-paths 来启用路径解析。
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ESNext", "DOM"],
"skipLibCheck": true,
"outDir": "./dist",
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}
3. IE11 支持问题
虽然我们都想放弃 IE11,但在某些行业客户还在使用它。为了兼容 IE11,我们不得不引入额外的 polyfill 并修改 Babel 配置。
npm install --save @babel/polyfill regenerator-runtime core-js
Babel 配置:
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"ie": "11"
},
"useBuiltIns": "usage",
"corejs": 3
}
]
]
}
同时,Vue3 默认使用 Proxy,而 IE 不支持,所以我们还得加个 Polyfill:
import 'proxy-polyfill/proxy.min.js'
4. 打包体积过大
最初打包后的 vendor.js 居然有 6MB+!这明显不合理。通过使用 rollup-plugin-visualizer 分析后,我们发现主要问题是第三方库未被 Tree Shaking,如 moment、lodash 等。
最终我们做了以下优化:
- 将
moment替换为轻量级的时间库dayjs - 对
lodash使用按需引入 - 开启
splitChunks拆分 chunk - 添加 Gzip 压缩
优化后整体打包体积下降了 60% 以上。
效果总结:项目上线后的收获
经过两个多月的努力,项目终于上线了。用户反馈良好,后台数据显示首屏加载时间控制在 1.5 秒以内。代码结构清晰,团队协作顺畅,新同学入职也能很快上手。
回顾整个过程,最大的收益不是完成了一个项目,而是建立了一套可以复用的前端脚手架模板,包括:
- 自动化的 CI/CD 流程
- 统一的编码规范与代码检查机制
- 完善的构建优化策略
- 覆盖主流浏览器的兼容方案
这让之后的新项目起步变得异常轻松。
经验分享:给前端小伙伴的建议
如果你正准备从零开始搭建项目,这里是我的几点建议:
1. 不要急着写业务代码
前期花点时间把基础架构搭好,未来节省的时间可能远超你的想象。好的结构能支撑起长期维护,坏的结构会让你后悔当初偷懒。
2. 关注用户体验,不仅仅是功能
前端的本质是提供优秀的交互体验。哪怕是一个简单的按钮点击效果,也要考虑反馈是否自然,是否卡顿。细节做不到位,再高级的技术也救不了产品。
3. 合理评估技术选型的利弊
不要盲目追新。例如,Vue3 很好,但如果你的团队对它的 Composition API 不熟悉,那不如先从 Vue2 稳扎稳打开始。技术是为人服务的,不是用来炫技的。
4. 尽早接入自动化工具
- Git Hooks 配合 lint-staged,确保每次提交的代码都有保障
- 使用 Husky + Lint-staged 实现 commit 时自动格式化和代码校验
- 配置 E2E 测试和单元测试,提升信心
5. 调试能力也是硬实力
掌握 Chrome DevTools 的各种技巧非常重要。比如:
- Performance 面板分析加载瓶颈
- Memory 面板排查内存泄漏
- Source Map 映射源码调试
- Network 面板查看接口请求状态
6. 保持开放心态,持续学习
前端技术变化太快,今天流行的明天可能就被淘汰。唯一不变的是我们解决问题的能力。建议每周至少抽出 1~2 小时,看看最新的技术文章或开源项目。
结语
这篇文章写了我不少深夜加班、抓耳挠腮的瞬间。但回头看,正是这些问题让我们变得更专业。希望我的经历对你有所帮助。
无论你是刚开始接触前端,还是已经工作多年的工程师,愿你在构建项目的道路上少走弯路,多些从容。
前端开发从来不只是写代码,更是理解需求、权衡取舍、持续迭代的艺术。共勉!
如果你觉得这篇文章对你有启发,欢迎点赞、转发或留言交流 👇

评论 0