从零开始构建一个现代化前端项目:一个大专生的血泪复盘
大家好,我是小李,一个刚毕业半年的大专计算机应届生。现在在北京一家中型互联网公司做前端开发,每天通勤一小时(早高峰10号线真的能挤到灵魂出窍)。别看我学历一般,但靠着自学前端,在校期间死磕 JavaScript + Vue,还顺手搞了个 GitHub 小作品集,居然真拿到了 offer——虽然工资不高,但够我在五环外合租活下去了。
说起来有点惭愧,入职前我以为“会写页面”就是前端的全部。结果第一个月就被安排重构一个老后台系统,产品那边天天催:“这个功能双11前必须上线!”、“用户反馈加载太慢了!”、“能不能加个暗色模式?”……而我,一个连 Webpack 都没配过的人,面对满屏的 Uncaught TypeError: Cannot read property 'xxx' of undefined,一度想回老家考编。
但人嘛,总得成长。这半年来,我硬着头皮从零搭起一个现代化前端项目,踩了无数坑,也攒了些经验。今天就来技术分享一下我的完整流程——不是教科书式的“最佳实践”,而是真实世界里一个普通前端仔怎么在 deadline 和产品经理的双重夹击下,把一个项目跑起来、跑稳、还能让测试小姐姐少提几个 bug 的故事。
起因:产品经理又改需求了
事情要从去年双11说起。我们团队负责一个 B 端 SaaS 产品,原本是 jQuery + Bootstrap 写的“祖传代码”,性能差、维护难、UI 还像十年前。老板拍板重做,让我牵头搭新架构(其实是因为 senior 哥们跳槽了,锅甩给我了)。
PM 周一晨会扔来一份 PRD:“我们要 PWA、支持离线、首屏秒开、还要 SSR 提升 SEO……对了,下周 demo 给客户看。”
我当时差点一口老血喷在 Vim 上——没错,我是个 Vim 党,JetBrains?那是什么?能吃吗?
但抱怨归抱怨,活还得干。我意识到:不能再用“能跑就行”的思维了,得整一套现代化的工程体系。
第一步:选型——别被 hype 带偏了
现在前端框架多得眼花缭乱,React/Vue/Svelte/... 我司之前用 Vue 2,团队熟悉度高,所以果断选 Vue 3 + TypeScript + Vite。理由很现实:
- 学习成本低(我只会 Vue)
- Vite 启动快(再也不用等 Webpack 编译等到泡面凉了)
- TS 能减少低级错误(上次我把
user.name写成user.nane,线上崩了半小时)
📌 安全意识 tip:别盲目追新!新工具可能有未知漏洞。比如某次我用了社区一个热门 UI 库,结果发现它依赖的某个包偷偷收集用户数据——赶紧删了,吓得我连夜扫了一遍
package-lock.json。
初始化项目很简单:
npm create vue@latest my-product
# 一路回车,记得勾上 TypeScript、Pinia、Router
cd my-product
npm install
Vite 默认配置已经很现代了:ESBuild 预构建、HMR 热更新快如闪电。我甚至能在 Vim 里改一行代码,浏览器自动刷新,爽到飞起。
第二步:目录结构——别让代码变成意大利面条
很多新手(包括曾经的我)喜欢把所有文件堆在 src/components 下。结果三个月后,找一个组件比找对象还难。
参考了公司老项目的惨痛教训,我定了这套结构:
src/
├── assets/ # 静态资源
├── components/ # 公共组件(Button, Modal)
├── views/ # 页面级组件(HomePage, UserList)
├── composables/ # Vue 3 Composition API 逻辑抽离
├── stores/ # Pinia 状态管理
├── services/ # API 请求封装
├── utils/ # 工具函数(debounce, formatDate)
├── router/ # 路由配置
├── types/ # TS 类型定义
└── main.ts
关键点:按功能分,不按文件类型分。比如用户模块相关的组件、API、store 都放在 features/user/ 下(后来才加的,初期偷懒没分,后悔死了)。
第三步:API 层——别再裸奔 fetch 了
以前我直接在组件里写 fetch('/api/user'),结果:
- 错误处理到处重复
- token 过期了不会自动刷新
- 测试时 mock 数据麻烦
现在我用 axios 封装了一层:
// services/api.ts
import axios from 'axios'
const api = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
timeout: 10000,
})
// 请求拦截器:自动加 token
api.interceptors.request.use(config => {
const token = localStorage.getItem('token')
if (token) config.headers.Authorization = `Bearer ${token}`
return config
})
// 响应拦截器:统一错误处理
api.interceptors.response.use(
response => response.data,
error => {
if (error.response?.status === 401) {
// token 过期,跳登录页
localStorage.removeItem('token')
window.location.href = '/login'
}
return Promise.reject(error)
}
)
export default api
这样,组件里调用超干净:
// composables/useUser.ts
import api from '@/services/api'
export function fetchUser() {
return api.get('/user')
}
💡 安全提醒:永远不要在前端存敏感信息!token 用
HttpOnlyCookie 更安全,但我们后端没配合,只能先这样。下次一定推动他们改!
第四步:状态管理——Pinia 真香
Vuex 太重了,配置一堆 mutations/actions。Pinia 直接用函数式 API,清爽:
// stores/user.ts
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', () => {
const user = ref<User | null>(null)
const login = async (credentials: Credentials) => {
const data = await api.post('/login', credentials)
user.value = data.user
localStorage.setItem('token', data.token)
}
const logout = () => {
user.value = null
localStorage.removeItem('token')
}
return { user, login, logout }
})
在组件里直接解构使用,TypeScript 还能自动推导类型,再也不用担心拼错 state 名字了。
第五步:性能优化——用户可不管你是谁
产品最常问:“为什么加载这么慢?” 其实大部分问题出在资源加载策略上。
1. 代码分割(Code Splitting)
Vite + Vue Router 天然支持路由级懒加载:
// router/index.ts
const routes = [
{
path: '/dashboard',
component: () => import('@/views/Dashboard.vue') // 自动分块
}
]
2. 图片优化
别再直接丢原图了!我们用 vite-plugin-imagemin 压缩:
// vite.config.ts
import viteImagemin from 'vite-plugin-imagemin'
export default defineConfig({
plugins: [
viteImagemin({
gifsicle: { optimizationLevel: 7 },
optipng: { optimizationLevel: 7 },
mozjpeg: { quality: 20 },
pngquant: { quality: [0.65, 0.8] }
})
]
})
3. 首屏加速:Critical CSS + 骨架屏
- 把首屏用到的 CSS 内联到 HTML(Vite 插件
critters自动搞定) - 列表页加骨架屏,用户不再盯着白屏发呆
性能对比(Lighthouse 评分)
| 指标 | 重构前 | 重构后 |
|---|---|---|
| 首屏时间 | 4.2s | 1.1s |
| Lighthouse 性能分 | 38 | 89 |
| Bundle 体积 | 2.1MB | 680KB |
看到这个数据,产品终于闭嘴了(暂时)。
第六步:安全与合规——别等出事才后悔
作为前端,很多人觉得安全是后端的事。但 XSS、CSRF、数据泄露,前端也是重灾区!
我做的几件事:
- XSS 防御:所有用户输入内容,用
DOMPurify清洗import DOMPurify from 'dompurify' const clean = DOMPurify.sanitize(dirtyHTML) - CSP 配置:在
index.html加 Content Security Policy<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' https://trusted.cdn.com"> - 敏感操作二次确认:删除按钮必须弹窗确认,防误触
- 日志脱敏:错误上报时自动过滤手机号、身份证等字段
⚠️ 血泪教训:上周五晚上加班,测试突然说“用户密码明文显示在控制台”——原来是我调试时忘了删
console.log(user)。赶紧全局搜console.log,加了个 ESLint 规则禁止提交。
第七步:自动化与协作——别当独行侠
一个人写代码爽,但团队协作必须规范。
我们团队落地的流程:
- Git 提交规范:用
commitlint+husky,强制格式[feat|fix|docs]: description - PR 模板:每次合并必须填“改动点”、“测试方案”、“影响范围”
- GitHub Actions:自动跑单元测试 + 构建预览
# .github/workflows/ci.yml name: CI on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: npm ci - run: npm run test:unit - run: npm run build
最爽的是:每次 push,GitHub 自动部署一个临时链接给 PM 预览,再也不用听他说“你本地跑给我看”。
最后:Rust?哦,那是下班后的事
写这篇文章时,我已经能比较从容地应对日常开发了。最近还在业余研究 Rust——不是为了转岗,纯粹觉得它的内存安全和并发模型太酷了。说不定哪天能用 Rust 写个 WASM 模块,给前端提速?
回头看看,从那个连 git rebase 都不会的大专生,到现在能独立搭建项目架构,靠的不是天赋,而是:
- 大量试错(删库跑路的心都有过)
- 善用开源(GitHub 是最好的老师)
- 保持警惕(安全不是选修课)
如果你也和我一样,学历普通、起点不高,别慌。前端世界足够大,容得下一个愿意死磕的普通人。
最后吐个槽:今天 PM 又说“加个 AI 功能吧,让用户上传图片自动生成文案”……我默默打开了 GitHub,搜索 “AI image to text”。兄弟们,救救孩子!
附:我的学习资源清单(真实用过)
- Vite 官方文档:简洁清晰,比 Webpack 友好多了
- Vue 3 深入响应式原理:理解底层,debug 不慌
- Web.dev 安全指南:Google 出品,权威可靠
- GitHub Trending:每天刷一刷,跟上社区节奏
共勉。

评论 0