从零搭建一个现代化前端项目,我踩过的坑和学到的经验

~曹思宇
2026-05-19 16:00
阅读 1518

早上8点,咖啡刚泡好,工位还没完全热乎——这大概是我过去三年在这家医疗软件公司最熟悉的日常。作为团队里为数不多坚持早起写代码的“异类”,我经常在同事们陆续打卡时,已经把当天最复杂的逻辑理得差不多了。

不过最近有点心不在焉。干满三年了,手里维护的几个老项目用的还是 Vue 2 + Webpack 4 的组合,每次打开控制台看到那堆 deprecation warnings 就头疼。上周五晚上加班修复一个因 moment.js 引起的打包体积爆炸问题时,终于下定决心:是时候从头搞一个现代化前端项目了

正好公司新立项了一个面向医生端的智能问诊辅助系统(内部代号“白大褂助手”),产品经理拍着胸脯说“这次咱们用最新技术栈”,虽然这话我听过八百遍,但这次居然真的批了技术选型自由权——当然,前提是别拖上线 deadline。

于是,我拉着两个实习生,开始了这场“现代化前端基建之旅”。


为什么不能直接 copy-paste 老项目?

很多人以为前端项目无非就是 vue createcreate-react-app 一把梭。但在医疗行业,事情没那么简单。

我们之前有个项目因为用了过时的 ESLint 配置,导致某次 CI 构建时自动格式化把关键医学单位“mg/kg”改成了“mg / kg”(多了空格),测试没覆盖到,结果线上医生差点开错药量——还好运维大哥眼尖,在灰度阶段就发现了。从此我们对“自动化”三个字又爱又怕。

所以这次,从零开始不是炫技,而是为了可控


技术选型:在“新潮”和“靠谱”之间走钢丝

首先明确几个硬性约束:

  • 必须支持 TypeScript(医疗数据结构复杂,类型安全是底线)
  • 构建速度要快(实习生等不起5分钟的 dev server 启动)
  • 要能无缝集成我们现有的 OAuth 2.0 和 FHIR(Fast Healthcare Interoperability Resources)API
  • 国际化支持(产品说未来要出海)

基于这些,最终敲定:

  • 框架:React 18 + Vite(告别 Webpack 的冷启动噩梦)
  • 状态管理:Zustand(轻量、无样板代码,比 Redux 好维护多了)
  • UI 库:Ant Design(虽然有点重,但表单、表格、日期选择器对医疗场景太友好)
  • Lint/Format:ESLint + Prettier + Husky + lint-staged(强制提交前检查,避免再出“空格事故”)
  • 部署:GitHub Actions + AWS S3 + CloudFront(运维组只认这套)

有意思的是,这次选型过程中,我试了试最近火出圈的 Amazon Q。它确实能根据自然语言生成基础配置,比如我输入:“帮我配一个 React + TypeScript + Vite 项目,支持 ESLint 和 Prettier,并在 pre-commit 时运行 lint-staged”,它几秒就吐出了一套 .eslintrc.cjs.prettierrcpackage.json 脚本。

但问题也来了:Amazon Q 生成的配置过于“通用”,比如它默认开启 @typescript-eslint/no-explicit-any,可我们在对接某些老旧后端接口时,不得不临时用 any 过渡。结果第一天就让实习生卡了半天。

相比之下,GPT-4o 在解释“为什么某个规则会报错”上更胜一筹。比如当 lint-staged 报错 Cannot find module 'eslint' 时,GPT-4o 不仅指出可能是 pnpm 的 hoisting 问题,还建议我在 package.json 中显式添加 eslintdevDependencies —— 这种上下文理解能力,目前 Amazon Q 还差一口气。

📌 小贴士:别迷信 AI 自动生成代码,尤其是在有行业特殊约束的场景。AI 是好助手,但不是决策者。


初始化项目:Vite 真香,但坑也不少

执行:

npm create vite@latest white-coat-assist -- --template react-ts
cd white-coat-assist
npm install

5 秒内 dev server 跑起来,热更新丝滑如德芙——那一刻我真的想给 Vite 团队磕一个。

但很快遇到第一个坑:Ant Design 默认不支持 ES Module 按需加载。直接 import { Button } from 'antd' 会导致整个库被打包进去,首屏加载直接飙到 3MB。

解决方案是用 unplugin-antd + babel-plugin-import(虽然 Vite 不用 Babel,但这个插件社区适配得不错):

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import unpluginAntd from 'unplugin-antd'

export default defineConfig({
  plugins: [
    react(),
    unpluginAntd({ importStyle: true }), // 自动按需引入样式
  ],
})

同时安装:

npm install -D unplugin-antd babel-plugin-import

搞定后,Bundle 分析显示 antd 相关代码从 2.1MB 降到 300KB,舒服了。


代码质量防线:Husky + lint-staged 真不能省

还记得那个“空格事故”吗?这次我铁了心要把质量门禁做死。

配置如下:

// package.json
{
  "scripts": {
    "lint": "eslint . --ext .ts,.tsx",
    "format": "prettier --write ."
  },
  "lint-staged": {
    "*.{ts,tsx}": ["eslint --fix", "prettier --write"],
    "*.{json,md}": ["prettier --write"]
  }
}

然后初始化 Husky:

npx husky-init && npm install

编辑 .husky/pre-commit

#!/usr/bin/env sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged

现在,任何人 git commit 时,都会自动格式化并修复可修复的 lint 错误。如果存在不可修复的问题(比如用了 any 且没加注释),commit 直接失败。

实习生第一次遇到时差点哭出来:“哥,我就是改了个注释啊!” 我笑着告诉他:“欢迎来到专业前端的世界。”


GitHub:不止是代码托管,更是协作中枢

这次我们把整个流程都搬到了 GitHub:

  • Issues:拆分用户故事(比如“医生能查看患者过敏史”)
  • Projects:用看板管理进度(To Do / In Progress / Review / Done)
  • Actions:自动化测试 + 构建 + 部署预发环境
  • Code Review:强制至少一人 approve 才能 merge

特别值得一提的是 GitHub Copilot。虽然它不能替代思考,但在写重复性代码时效率提升明显。比如写一个 FHIR Patient 资源的解析函数:

// 输入注释:
// Parse FHIR Patient resource and extract name, birthDate, gender, and allergies

// Copilot 自动生成:
function parsePatient(patient: fhir.Patient) {
  return {
    name: patient.name?.[0]?.text || '',
    birthDate: patient.birthDate || '',
    gender: patient.gender || 'unknown',
    allergies: patient.extension?.filter(ext => 
      ext.url === 'http://hl7.org/fhir/StructureDefinition/allergyintolerance'
    ) || []
  };
}

准确率大概 80%,剩下 20% 需要手动调整(比如 allergy 的 extension URL 实际是另一个),但省去了查文档的时间。


性能与体验:医疗场景下的特殊考量

医生用系统时往往在高压环境下,页面卡顿一秒都可能影响判断。所以我们做了几件事:

  1. 字体加载优化:使用 font-display: swap 避免 FOIT(字体未加载时空白)
  2. 图片懒加载:患者影像资料用 loading="lazy"
  3. 关键 CSS 内联:首屏样式直接塞进 <style> 标签
  4. 错误边界兜底:任何组件崩溃不导致整个页面白屏

还专门写了性能监控埋点,记录:

  • 首屏渲染时间(FCP)
  • 可交互时间(TTI)
  • API 请求耗时

数据上报到公司自研的监控平台(别问,问就是“借鉴”了 Sentry)。


成果与反思

项目上线两周,医生反馈“比旧系统快多了”,产品经理难得没提新需求(奇迹!)。Lighthouse 评分从旧项目的 45 提升到 92,构建时间从 4 分钟降到 28 秒。

但我也意识到:现代化 ≠ 追新。Rust 最近让我很心动(连写个 CLI 工具都想用它),但在前端领域,稳定性和团队熟悉度永远排第一。这次没上 Next.js 或 Remix,就是因为团队对 SSR 经验不足——宁可少点 fancy feature,也不能让实习生天天 debug hydration mismatch。


最后:关于跳槽和成长

写这篇文章时,我其实已经更新了简历。三年医疗软件经验,加上这次完整的现代化项目实践,应该够我去看看外面的世界了。

但无论去哪,我都不会忘记那个因一个空格差点酿成医疗事故的夜晚。技术可以迭代,工具可以更换,唯独对细节的敬畏,是一个开发者最不该丢掉的东西

共勉。


附:核心依赖版本参考(2024年6月)

工具 版本 说明
React 18.2.0 启用并发模式
Vite 4.4.0 构建工具
TypeScript 5.0+ 类型系统
Ant Design 5.12.0 UI 组件库
ESLint 8.44.0 代码检查
Prettier 3.0.0 代码格式化
Husky 8.0.3 Git 钩子
lint-staged 13.2.3 提交前检查

注:所有依赖均通过 npm outdated 定期检查更新,避免“依赖地狱”。

评论 0

最热最新
暂无评论
~曹思宇Lv.1
0
影响力
0
文章
0
粉丝