资讯详情

全栈项目Day2:搭建前后端骨架并实现数据联调

📅 2026/10/17 16:07:08 | 华诺云谱 👁 阅读
全栈项目Day2:搭建前后端骨架并实现数据联调
day2这个标签在连续打卡类开发计划里是最容易翻车的位置。第一天大家都热血沸腾需求清单写满两页纸技术选型讨论半天到了第二天打开编辑器面对一片空白很多人就卡住了——不知道今天该干嘛。我给自己定了一个30天全栈小项目的挑战day2的任务被我从源头收敛得非常具体把第一天选定的技术栈落成一个能跑的前后端骨架并且让前端页面能真实拿到后端返回的数据。这一天做的事情乍一看不酷也不产生什么“看得见的功能”但它是整个项目后续30天能不能稳定推进的地基。这篇文章会把我day2的操作记录、目录设计、联调过程、踩坑经历完整摊开。如果你也在做类似的连续学习或项目打卡这些内容可以直接照着落地不用重复踩我走过的坑。1. 项目整体设计与Day2目标拆解1.1 把“第2天”拆出明确边界第一天做规划时我给自己定的规矩是不写代码只做三件事确定项目要解决一个什么问题、画出核心模块清单、给技术栈列候选人。这三件事做完除了几张草稿纸和几个文档没有任何能运行的东西。这也是为什么很多连续打卡计划会死在第二天——目标太模糊规划再漂亮落到编辑器里就变成“打开一个新项目然后发呆”。为了避免这种情况day2开始之前我把当天的目标压成三个可以验收的点前后端项目都能在本地用一条命令启动并且访问地址固定不变。目录结构按照功能域来组织而不是按文件类型堆在一起为后续增量开发留出稳定上下文。打开前端页面时浏览器能通过代理把请求发到后端拿到接口数据并渲染到页面上。这三个点都有一个共同特征每一项都能明确判断“完成”或“没完成”不存在模糊地带。在这个基础上我在文档里给每一天都定义了一个验收模板格式很简单今天要完成什么、完成的标志是什么、如果没完成明天要怎么处理。这套模板在day1其实就写好了day2只是第一次正式使用。实践下来它最大的作用是帮我在中途想“要不要顺手多做一个功能”的时候踩下刹车——如果这个功能不在今天的验收清单里那就列入明天再做。连续打卡真正考验的从来不是一天能写多少代码而是能不能一直稳定地推进所以控制每天的任务颗粒度比堆工作量重要得多。如果某天真的因为意外没能完成当天的目标我的处理方式是不补进度把目标顺延到第二天但第二天只保留这一个目标不再叠加新任务。这样做的原因很朴素——连续打卡的意义在于连续性如果为了赶进度而连续几天熬夜那这种“打卡”大概率坚持不到一周就会崩。允许自己偶尔放慢节奏但绝不允许自己没有完成感地混过一天。1.2 技术选型的取舍理由技术选型这个环节最容易犯的错误是“跟风”。今天看到某框架很火就想换过去明天看到别人发了新工具又觉得不错。day2我不能再纠结这个应该在day1定下的基础上直接开工。当时我的决定是前端用 Vue 3 Vite TypeScript后端用 Node.js Express数据存储暂时用最简单的方案等业务逻辑出现后再定。选Vue 3而不是其他框架理由很实际对单人、小项目的开发节奏来说它的学习曲线最平缓单文件组件的写法很直观类型集成也不绕。Vite作为构建工具冷启动速度是肉眼可见的快——我实测过一个空白项目从敲命令到页面能访问基本是秒级完成。这种细节在一天只写一点代码的打卡节奏里很重要因为等待启动的时间其实是消耗耐心最厉害的地方。后端选Express核心原因是这个阶段根本不需要重型的应用框架。Express的中间件模型足够表达“接收请求、解析参数、返回响应”这一整套最基础的链路等项目的业务复杂度上来了路由、控制器、服务分层都可以在现有基础上循序渐进地加而不是一上来就背上一个沉重脚手架。我给自己定的选型原则就三条能简单就不复杂能用现成的就不造轮子不追求“显得很专业”只追求“能稳定跑完这个项目”。2. 骨架搭建目录、配置与初始化细节2.1 脚手架初始化一条命令背后的约定前端的初始化我直接用 Vite 官方脚手架npm create vitelatest frontend -- --template vue-ts执行完frontend 目录里已经有一个完整的 Vue 3 TypeScript 工程自带开发服务器、构建脚本和基础配置。我做的第一件事不是写代码而是清理模板自带的示例组件和样式。这一步很多人会忽略结果项目里残留着一个和自己需求毫无关系的页面每次打开都是那个图标容易让人搞混。清理完目录里只剩下干净的入口文件、App.vue 和必要的配置。后端的初始化更加朴素手动创建 backend 目录然后npm init -y npm install express这样得到一个最小化的 Node.js 项目。手动初始化的好处是每一行结构都知道是用来干嘛的不会出现脚手架生成了一堆不知道用途的配置。但手动初始化的代价是所有的工程规范都要自己立。day2我没有引入 ESLint 和 Prettier 这类工具不是它们不好而是这个阶段的代码量很小手写规范完全够用等代码量上来了再在一个空闲的日子里一次性配置好比在每一天里分心处理工具配置要高效得多。这里有一个在连续开发中经常被忽视的点脚手架自带的版本和配置在你的运行环境里不一定兼容。我在初步完成后验证了一下启动命令发现前端可以正常启动但构建时有几条告警。经过检查确认是模板默认的 Node.js 版本要求和我本机环境存在差异导致的。遇到这种情况正确做法是调整本机工具链版本而不是反过来去改动项目依赖。这个细节我在后面的排查章节还会展开。2.2 目录结构设计的意图目录结构这件事决定了未来30天每天写代码时“该把文件放哪”的直觉。如果一开始就乱放后面每加一个功能都要纠结一下文件位置这种纠结虽然小但每天都在消耗注意力。很多初学者习惯按文件类型分目录一个文件夹放所有页面一个文件夹放所有组件一个文件夹放所有工具函数。这套方案在项目很小时挺直观但模块一旦变多就难受了——要改一个用户相关的功能你需要在页面、组件、工具、接口四个文件夹里跳来跳去才能看清全貌。day2我选择按功能域来组织frontend/src/ ├── api/ # 接口请求封装一个文件对应一个领域 ├── views/ # 页面级组件 ├── components/ # 可复用的局部组件 ├── router/ # 路由配置 ├── stores/ # 全局状态 └── types/ # TypeScript 类型定义后端目录同样强调功能归属backend/ ├── src/ │ ├── routes/ # 路由定义层 │ ├── controllers/ # 请求参数处理 │ ├── services/ # 业务逻辑 │ └── index.js # 应用入口 ├── .env └── package.json这个结构不是最复杂的但它足够清晰。核心优势是“稳定性”一旦确定下来后续每天的新代码都有固定的去处你不需要反复思考文件该放哪里。比如第10天要加一个收藏功能流程就是api 加一个收藏请求文件、views 加一个收藏页面、router 挂一条路由、如果需要状态就在 stores 加一个模块完事。对连续打卡来说这种稳定的开发节奏比任何花哨的架构都更重要。另外目录结构一旦定下来就不要随便改。我知道有人会在项目中途突然觉得结构不好然后花一整天重构目录。这个收益在项目早期几乎为零成本和风险却很高。骨架期定的结构可能不完美但只要它能容纳接下来一周的增量迭代就足够了等真正遇到结构瓶颈时再来调整不迟。2.3 环境变量与配置管理配置管理看着基础实则坑很多。day2我给自己定了一条规矩不允许出现硬编码的端口、地址和密钥全部收进环境变量。后端的环境变量放在backend/.envPORT3000代码里通过 dotenv 插件读取。这里写的端口是经过考虑的3000 是开发场景非常常用的端口不容易和前端默认的 5173 冲突而且生态兼容性好。后端入口里这样读取import dotenv/config; const port process.env.PORT || 3000; app.listen(port, () { console.log([server] running at http://localhost:${port}); });前端这边Vite 开发服务器的代理目标同样不写死而是读取环境变量。这样设计最大的收益在项目后期——当你要把项目部署到服务器时只需要改 .env 文件不需要翻代码找那些写死的地址。这个习惯越早养成后期重构的成本就越低。需要注意的是.env文件默认是不应该提交到版本仓库的因为它将来会存放敏感配置和不同环境的差异配置。我在.gitignore里把.env直接排除掉同时准备了一份.env.example提交到仓库里面只写变量名和示例值别人 clone 下来后复制一份改成自己的配置就能跑。这个做法在协作时会显得特别重要单人项目也建议从一开始就养成这个习惯。3. 前后端联调让页面真正拿到后端数据3.1 先把后端跑起来很多教程喜欢把前端后端放在一起讲但实操里应该先把后端单独跑通。这一步虽然简单却能为后面的联调减少一半的排查时间。后端入口代码我写得很克制// backend/src/index.js import express from express; import dotenv/config; const app express(); app.use(express.json()); app.get(/api/health, (req, res) { res.json({ code: 0, message: ok, time: Date.now() }); }); const port process.env.PORT || 3000; app.listen(port, () { console.log([server] running at http://localhost:${port}); });这里我特意定义了/api/health作为健康检查接口后面所有联调都先从这个接口开始。如果这个接口不通那就说明基础设施有问题不应该继续往下开发功能。启动命令是node src/index.js看到终端输出 running 日志后我用浏览器打开地址http://localhost:3000/api/health。页面返回 JSON 数据的时候后端链路就确认正常了。单独验证这一步的价值是当后续联调失败时你不需要同时怀疑前端和后端而是可以非常有底气地判断问题出在哪一侧。在这个阶段我还顺手验证了一件事接口返回的time字段用的是服务端时间戳说明数据确实是从后端实时生成的而不是被某些缓存策略挡在了中间层。这一开始可能觉得多余但当你后面引入缓存、CDN 或者部署到服务器上时这种“确认数据来源”的敏感度会帮上大忙。3.2 前端代理转发与跨域处理前端开发服务器默认端口是 5173后端是 3000两个不同源之间直接 fetch 会被浏览器的同源策略拦下来。处理这个问题有两种常见做法一种是后端开启 CORS另一种是前端开发服务器做代理转发。我选了后者。为什么不选 CORS因为 CORS 需要后端额外配置一堆响应头而且它在部署阶段还有各种各样的边界情况代理转发则是开发服务器天然支持的能力配置一行就行上线后由反向代理统一处理逻辑更干净。在 Vite 配置文件里加代理// vite.config.ts import { defineConfig } from vite; import vue from vitejs/plugin-vue; export default defineConfig({ plugins: [vue()], server: { proxy: { /api: { target: http://localhost:3000, changeOrigin: true, }, }, }, });这段配置的意思是凡是请求路径以/api开头的开发服务器都把它转发到http://localhost:3000。注意 target 不能写错端口此外changeOrigin一定要设置成 true。这个参数的作用是改写请求头里的 Host 字段让后端感觉这个请求就像来自同一个域名很多代理配了但仍然报跨域错误八成是在这里漏掉了。配置完成后建议先重启一次前端开发服务器再验证联调。因为 vite.config.ts 这类配置文件不会在页面刷新时自动重载这也是我后面会反复提到的“改配置必须重启”的典型场景。3.3 接口联调验证与数据打印代理配好了接下来写前端页面。day2不需要什么华丽功能我的目标只是让页面真实地拿到后端数据并显示出来。为此我封装了一个最简单的请求工具// frontend/src/api/client.ts const request async (url: string) { const res await fetch(url); if (!res.ok) { throw new Error(HTTP ${res.status}); } return res.json(); }; export const getHealth () request(/api/health);然后在页面组件里调用script setup langts import { ref, onMounted } from vue; import { getHealth } from ../api/client; const status ref(加载中...); const time ref(); const init async () { try { const data await getHealth(); status.value data.message; time.value new Date(data.time).toLocaleString(); } catch (e) { status.value 请求失败 (e as Error).message; } }; onMounted(init); /script template div h1Day2 联调验证/h1 p后端状态{{ status }}/p p后端时间{{ time }}/p /div /template我特意在 catch 分支写了错误提示而不是让请求失败时静默。这是个好习惯页面出错时至少能知道是请求 URL 写错了、后端挂了还是网络层出了问题。验证时我打开浏览器 DevTools 的 Network 面板确认/api/health请求的 Status 是 200响应体里有预期的字段再切到页面看渲染结果。这一步做到位day2 的三个目标才算全部通关。这里我再补充一个细节联调时不要只看页面显示对了就收工。页面显示对只能证明这条链路是通的但你还应该确认控制台没有报错、Network 面板里没有 404 或 500、请求头里的 Origin 和 Host 符合预期。这些信息才是后续排查问题的底牌。4. 常见问题排查与避坑记录4.1 端口占用与重启策略实际操作中端口占用是最常见的问题。我在启动后端时有一次终端直接报EADDRINUSE说明 3000 端口已经被占用。排查思路很简单先查看哪一个进程占用了这个端口确认是上次没关干净的后端进程后结束掉再启动。这里要特别提醒的是在开发机上结束进程时要确认它确实是自己跑起来的不要误杀其他项目的进程。除此之外我还养成了一套固定的开发启动顺序先把后端启动起来确认日志正常再启动前端开发服务器。这个顺序能保证联调时不会出现“前端开了后端忘了”的尴尬。关于重启策略day2 我没有引入热重载工具所以后端每次改完代码都必须手动重启。这个流程看起来原始但好处是让人对“代码生效”这件事有明确的掌控感不会出现改了半天以为生效了实际跑的还是旧代码的情况。等后面项目变大再考虑引入热重载也不迟。前端那边的热更新相对完善改业务代码保存后页面会自动刷新但需要注意vite.config.ts等配置文件仍然需要整个重启开发服务器。4.2 依赖版本不一致导致的诡异报错安装完前端依赖后我一启动就报语法错误报错信息指向一个第三方库的源码。初看很吓人仿佛库有问题。但冷静下来梳理会发现一个关键细节报错原因是这个库使用了当前 Node.js 版本不支持的语法特性。问题不在库在我的运行环境版本太旧。排查这类问题我的顺序是先读报错信息里的模块名和行号确认指向的是第三方库还是自己的代码如果是第三方库先检查 Node.js 的版本最后确认本机环境是否符合项目要求。实测下来绝大多数“莫名其妙”的报错根源都是环境版本不匹配和业务代码没有半毛钱关系。一个延伸出来的习惯是每次开始一个新项目先记录当前运行环境的版本信息再决定要不要升级。保持稳定优先不要为了“用新版本”而用新版本这是连续打卡项目能否长期稳定推进的一个隐形前提。环境这种东西越接近稳定越容易写出可预期行为的应用反之则会时不时给你添乱。4.3 配置不生效的排查路径还有一次我改完 Vite 代理配置刷新页面却发现请求仍然打到原来的地址上第一反应是“配置写对了没有”反复检查也没发现语法错误。最后才意识到问题出在Vite 配置文件的修改需要重启开发服务器才能生效刷新页面不会重新读取配置文件。这里想分享一个通用的排查原则当程序行为没有按照预期变化时先别急着怀疑逻辑先确认“修改是否真正加载了”。对于配置文件来说最直接的验证方式就是重启进程后看行为是否改变。如果重启了还是不对再进入下一步检查是否有一个优先级更高的配置在覆盖它或者实际加载的配置文件根本不是你以为的那一个。这套排查路径看起来简单但能解决开发中大量的“我明明改了但没生效”问题。我把这类的常见情况整理成一个速查表方便以后查看现象第一反应第二反应改了配置文件但行为没变重启对应服务检查加载的是否是当前文件端口被占用查看占用进程并处理确认占用者是自己项目还是其他程序前端请求跨域检查代理是否生效检查 changeOrigin 是否设置安装依赖后启动报错查看报错模块核对 Node.js 版本要求5. 连续打卡类开发怎么稳住节奏5.1 每天早上先定今天能验收的事连续打卡计划最常见的死法是“第二天热情还在但目标太大”。day2 的成功经验让我意识到每天开工前一定要花 5 分钟想清楚今天做完什么就算这一天赢了这个验收标准不需要宏大甚至可以是“把环境搭起来并跑通一个接口”。关键是它必须足够小、足够清晰让你在晚上回顾时能明确地说出“做到了”或“没做到”。写到一半想顺手加功能时用这个标准作为刹车可以避免每天的任务无限膨胀。我个人的实际体会是连续开发中完成感比成就感重要。成就感需要做大事而完成感只需要每天兑现一个小承诺。小承诺不断兑现项目就会像滚雪球一样自然地往前推进。而且这种节奏有一个额外的好处——因为每天目标不大你有余力去观察和思考而不是一直埋头赶进度。很多好设计反而是在这种“不太忙”的状态下冒出来的。5.2 用轻量记录代替流水账打卡项目最容易犯的第二个毛病是把记录写成流水账——今天做了什么、改了哪些文件、跑了哪些命令。这种记录当下觉得很充实一周后回看基本没有任何信息量。我更推荐的记录格式是“决策型日志”今天做了什么决策、为什么这么决策、踩了什么坑、如果再来一次会怎么避免。我今天的记录是这样的选择代理转发而非 CORS因为开发环境代理只需一行配置且上线后由反向代理统一处理整体链路更简单踩坑修改 vite.config.ts 后必须重启开发服务器刷新页面不会重新加载配置。这几十个字三个月后回看依然能想起当时的全部背景。这些决策记录在项目后期会异常宝贵。当你想回看为什么某个模块要长这样、为什么当初没选某个方案时这些日志能直接告诉你答案不需要靠猜。这也是连续打卡和一次性开发最大的区别——节奏让过程可以被记录记录让经验可以被沉淀。day2 跑通骨架落地第一轮前后端数据已经在浏览器里渲染出来了。回看这一天真正让我觉得值得的不是那几行代码而是三个被验证的决策功能域目录结构、代理转发方案、拒绝硬编码的配置管理。这三条看起来不炫技但后续30天里每一个新增功能都在享受它们的红利。如果你也在做连续开发或学习打卡我给的建议是不用纠结每天要产出一个多牛的成果把今天真正做完、做一个能验收的事就够了。积累两三个星期你会发现一天一点真的比一次猛冲要强。明天继续更新 day3 的业务模块实现到时候见。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑