【前端爽文】重构前端,从被踢出组件库开始

247 阅读13分钟

小声 BB + 免责声明

最近开了一个短剧会员,纯娱乐,无脑短剧,真好看,真上头! 不参加任何活动,不代表任何技术立场!纯娱乐!

第一章:我,被踢出了 UI 团队

那天,空气湿热,蝉鸣聒噪,宋执坐在工位上,刚刚提交了一次 PR。他喝了口冰美式,盯着 GitHub Actions 成功的小绿勾,脸上浮现出一丝成就感。

这是他为公司主站重构的新组件——一个动态响应式的 Button 模块,使用 tailwind-variants 组合出了 12 种状态,集成了焦点环、loading 反馈、icon 支持,还做了无障碍键盘操作支持。

feat(button): add variants, dark mode, and full a11y support

commit message 格式依旧规范,是他当初要求团队统一的标准。每个组件都要有文档、预览图、Storybook 示例、ARIA 验证,甚至配套截图测试。

他沉浸在短暂的满足感中,直到 HR 拿着文件夹来到他面前:

“宋执,可以来会议室聊一下吗?”

会议室里冷气刺骨。墙上贴着 Agile 流程图,但现在什么都不敏捷。

HR 没有拐弯抹角:“公司决定解散 UI 技术中台,把你这个方向合并进 AI 视觉体验团队。”

宋执一愣:“合并是什么意思?我带的组件库团队怎么办?”

产品总监接过话,冷静地说:“新团队会用更智能的方案。AI 生成组件、设计图直接转代码、无需维护手写组件库,组件抽象这种事我们认为是冗余的。”

“你做的东西,太‘工程化’了。我们需要的是‘产品感’和‘设计感’。”

宋执看着那封调岗信,突然意识到自己像极了早期的 jQuery,曾经辉煌,但终究被当作“过时的遗产”。

整个 UI 团队被打包进“视觉体验小组”,技术栈从 React 切换到一个不知名的 DSL,组件通过 YAML 生成,每次改动都要重新跑 prompt。

他的 Button 组件,被评审为“写得太细、太重、不够灵活”。

连变量名 button--variant-danger 都被嫌弃不够美观,要求改成 btnRed.

这不是技术问题,这是政治。


离开会议室的时候,宋执默默看了一眼公司楼下的招牌灯箱,那个他参与设计的 logo 上还残留着他亲手调过的 box-shadow 值。他笑了笑,自嘲地想:

“连阴影都有人维护,程序员却说换就换。”

他回到工位,发现邮箱权限被撤销,Figma 项目中他的头像变成了“已离职成员”,而那套他花了整整一年构建的组件库,已经被新组踢出了项目依赖。

曾经的同事们避而不谈,唯有一个 UI 实习生私信他说:“哥,我一直在偷偷用你那套按钮,真的比他们那 AI 自动生成的好用多了。”

宋执没回。他关掉 VSCode,把自己维护的组件库代码从 GitHub clone 到本地,又静静打开 README.md,最后一行写着:

“为那些相信规范、抽象、可复用性和代码美学的开发者。”


他起身走出公司,阳光晃得他睁不开眼,地铁站旁边贴着巨大的广告牌:

“AI 将彻底改变前端开发,你准备好了吗?”

宋执站在那里,听着人群走过的脚步,突然意识到:

如果前端开发真的会被替代,那第一个下线的,不会是懂语义化和无障碍设计的人,而是那些放弃原则随波逐流的临时工。

他在心里默默说了一句话:

“你可以不要我,但我不会不要组件。”

第二章:重新开始,从 npm init 开始

夜色沉沉,宋执窝在出租屋的飘窗前,笔记本电脑的屏幕亮度开到最大,映在他脸上泛着一点冷白的光。

他刚刚离开公司,被“技术中台合并”的荒谬理由扫地出门。两年,他从零搭建的组件库被打包进“AI UI 模板引擎”,说是未来的趋势,但他知道,那根本不是趋势——那只是省事,是“用生成式代替思考”的懒惰。

桌上是一杯泡得过头的速溶咖啡,键盘旁边是他从工位上带走的便签纸,上面写着他最喜欢的一句代码哲学:

“组件不是样式的组合,是语义的抽象。”

他打开终端,敲下熟悉的命令:

npm init -y

那一刻,他感觉自己像是从荒原中徒步归来的术士,重新召唤出了第一个魔法圈。 他给项目起名叫:unicorn-ui。 他给项目起名叫:unicorn-ui。

为什么叫这个名字?

他也说不清。

可能是想要一点“稀有”“纯净”“不屈”的意味。

他用 Vite 搭建了项目骨架,集成了 TypeScript 和 Tailwind。选择 tailwind-variants 作为样式工具,因为相比传统 BEM 或 class 合并器,这套组合方式更灵活,也更符合现代前端的函数式审美。

项目结构清晰利落:

src/
├── components/
│   ├── Button.tsx
│   ├── Input.tsx
│   └── Tooltip.tsx
├── utils/
│   └── cn.ts
└── index.ts

第一步,他重写按钮组件。他没有复制以前的代码,而是从零写起。

// Button.tsx
import { cva } from 'tailwind-variants'
import { cn } from '../utils/cn'

const buttonVariants = cva(
  'inline-flex items-center justify-center font-medium transition-colors focus:outline-none disabled:opacity-50',
  {
    variants: {
      variant: {
        default: 'bg-zinc-900 text-white hover:bg-zinc-800',
        outline: 'border border-zinc-300 text-zinc-700 hover:bg-zinc-100',
        ghost: 'bg-transparent hover:bg-zinc-100',
      },
      size: {
        sm: 'h-8 px-3 text-sm',
        md: 'h-10 px-4 text-base',
        lg: 'h-12 px-6 text-lg',
      },
    },
    defaultVariants: {
      variant: 'default',
      size: 'md',
    },
  }
)

export function Button({ className, variant, size, ...props }) {
  return (
    <button className={cn(buttonVariants({ variant, size }), className)} {...props} />
  )
}

看着组件自动在 Storybook 里渲染出来的那一刻,他有种说不出的满足。

没有老板、没有会审、没有设计师拍脑袋决定 spacing 和圆角,只有自己和代码。****

他写了 README,添加了完整的 props 文档,甚至配置了 typedoc 生成静态 API 页面。

然后,他发布了第一个版本。

npm publish --access public

版本号是 0.0.1,他知道这个组件库还很弱小,但——

他给了它一个灵魂。

第二天醒来,他在 GitHub 收到一个陌生网友开了个 issue:

“Your Button component has very clean structure. Could I help translate the docs into Spanish?”

宋执愣住了。

这只是一个简简单单的按钮组件,一个还没人用的早期版本。居然已经有人主动来贡献翻译?

那一刻他意识到,他不是在战斗,而是在播种。****

他决定写一篇文章,发在 Dev.to 和国内的掘金上,标题是:

“我被AI组件库淘汰后,重写了自己的UI系统”

文章第一段写的是他离职的故事,后面是他对组件设计哲学的理解——包括:

  • 为什么不要滥用 auto layout

  • 为什么组件应先定义语义,再定义样式

  • 为什么 aria-* 和键盘交互应该成为默认支持

这篇文章在短短 12 小时内被转发了上百次,GitHub 项目 star 从 1 变成了 87。

有 React 社区的开发者说:“这个库虽然简单,但比那些自动生成的组件更可控。”

也有人私信他说:“我打算从 Chakra UI 迁移到你的按钮体系。”

宋执心中一震。

他意识到自己曾经努力维护的东西——那些“很工程化”的事情,那些“过度关注细节”的坚持,其实并没有错。

只是在体制里,它们不值钱。

而在开源世界里,这些,才是信仰。

但问题也来了。

没有设计师。

没有 UX。

宋执一个人,要承担组件样式、视觉一致性、交互体验,还得做动画细节,处理兼容性 bug。

他开始焦虑。

为了解决这个问题,他灵感一闪,干脆建立一套“无设计者的设计系统流程”,他称之为:

Developer-first UI System

原则如下:

  1. 所有颜色必须使用语义命名,如 primary, accent, destructive,内部统一映射 HSL。

  2. 组件交互基于 keyboard-first:先考虑键盘可用性,再考虑鼠标与触屏。

  3. 动画必须基于 framer-motion 的 spring 动效,禁止使用硬切。

  4. 所有 spacing 单位统一用 Tailwind rem 体系,不使用任意 px 值。

他甚至写了个生成器,叫 gen-token.ts,自动从 tokens.json 生成 CSS variables、Tailwind config、Figma tokens 三套标准。

这个设计系统,从代码出发,反向约束了设计。

有人笑他:“这能叫设计系统?”

他笑着回了一句:

“你可以不认同,但你会用。”

深夜,窗外蟋蟀聒噪。

宋执坐在屏幕前,Review 一个刚刚来自印度开发者的 PR——

对方为 Tooltip 组件补充了 delay 参数,还修复了在 iOS Safaripointer-events 的问题。

他点了 Approve,心中泛起暖流。

是的,他现在可能什么都没有。

但他有一件东西,越来越完整,越来越强大。

他自己写的组件库。

第三章:组件库爆火后,我成了“AI UI 的反对派”

距离宋执发布 unicorn-ui 的第一个版本已经过去了 23 天。

GitHub Star 数:1427

下载量:13,904

社区贡献者:27

Issue 数:38(其中 33 已关闭)

在没有任何流量支持、没有开源基金赞助、没有“设计指导”的前提下,这个小而美的组件库正逐渐走进更多开发者的视野。

也正因如此,主流的“AI UI”团队开始注意到他。

注意到他,并开始——讽刺他。

那天晚上,宋执刷着前端社区的直播频道,看到了熟悉的公司 LOGO。

是他前公司主办的一场“AI UI 智能组件设计”直播活动,主持人正是当初把他踢出团队的设计 VP 兼“AI UI 布道师”——许凡。

直播标题:

“传统组件库的尽头?AI 生成的 UI 编码新范式”

标题下方还有个讽刺意味极强的小副标题:

“评评那些还在手写 Button 的浪漫主义者”

宋执点进去,没过十分钟,就听到他的名字被点出来。

许凡笑着说:“比如最近有个很火的开源项目,叫 unicorn-ui,很努力地用 tailwind 和 TS 去写组件,还坚持什么 accessibility 和 variants。”

旁边的产品经理附和:“我看了他的 Tooltip 实现,光一个延迟动画就手搓了三百多行代码,现在谁还这么搞?”

许凡转向镜头:“我们 AI UI 系统只需要一句 prompt,就能生成同样的按钮,带 hover、dark mode、animation。人写的东西,终究会被模型替代。”

直播弹幕一边倒:

  • “写那么复杂干啥,直接 prompt 多快”
  • “哥们以为自己在写操作系统呢?”
  • “代码洁癖吧,活该脱离团队”

只有零星几个弹幕说:“但他那个 Button 的结构确实更清晰”、“至少他的组件能读懂逻辑”

宋执没说话,他退出了直播。

但他把那段直播录了下来,剪成了一段三分钟的视频,配上标题:

“我手写了一个组件库,被说是浪漫主义者。”

然后,他把它发到了 B 站、抖音和 YouTube Shorts。

视频发出的第二天,他的邮箱被关注提醒炸满。

那条视频短短两天在全网播放量超过 30 万,评论上千。

人们突然意识到,原来在“AI 统治一切”的当下,还有人在用代码坚持架构思维、组件哲学和用户体验本质。

甚至还有某知名前端技术号发文支持他:

“我们不反对 AI 参与 UI 生成,但前端开发不是按钮堆叠游戏,而是交互、抽象、维护成本与工程边界的艺术。”

网友给他贴了个标签:

“代码理想主义者”

有人嘲笑,有人崇拜,但更多人,是好奇:

他,到底写了什么样的组件?


【社区的反击:fork storm】

就在直播第四天,unicorn-ui 项目迎来了史上最大的一次 fork 爆发。

从韩国的独立开发者,到巴西的 SaaS 创业者,再到国内某高校前端课程项目,全都开始 fork 他项目改造成自己的 UI 库。

有开发者将它集成进 vite-plugin-preview

有团队用它重写自己的内网后台系统

甚至有一个 React Native 方向的开发者,提交了一个 PR,开始适配移动端

宋执看着通知中心不断跳动的 PR 提醒,心脏砰砰跳动。

他明白,自己被骂的那一刻,反而让更多人看见了坚持的价值。*


但冲突没有结束。

一个叫「UIGEN」的 AI UI 公司向他发起了挑战:组件 Battle。

规则很简单:

  • 双方各出一个组件主题(如 Modal、Dropdown、Tabs)

  • 一方由人类写代码,另一方用 AI prompt 自动生成

  • 评审标准为:性能、无障碍支持、设计一致性、二次封装能力、开发体验

这一次,社区来投票。

这个话题迅速登上 Twitter 热榜(国内 X 热榜),被称为“人类开发者与 AI 的第一次 UI 决斗”。

UIGEN 推出他们的 Modal Prompt:

“Create a responsive modal component with dark mode, keyboard navigation, and animation.”

不到 2 分钟,AI 生成了一段代码,样式炫酷,动画丝滑。

宋执没有立刻写代码。

他沉默了一夜。

然后打开 VSCode,开始写他的版本。


他用了:

  • Headless UI 的组合思想:行为与表现分离

  • React Context 控制状态:兼容嵌套与 Portal

  • Framer-motion 的 layout spring:自然闭合动画

  • 焦点陷阱(Focus Trap)键盘导航支持

他写了整整 280 行,写完后每一行都跑了测试,并加了完整文档,支持嵌套 Modal、异步加载内容与响应式布局。

他将这段代码 push 到 unicorn-ui 的 next 分支。

一小时后,GitHub 上出现了这样一条 Star 评论:

“这不是 Modal,这是手术级别的交互模块。”


最终的社区评审投票:

  • 视觉一致性:AI 版本胜(因为用了一套自动化设计语言)

  • 响应速度:平局

  • 无障碍支持:人类版本胜(AI 版本缺失 focus trap)

  • 二次封装能力:人类版本胜(AI 生成代码高度耦合)

  • 开发者好评:人类版本压倒性胜出

宋执用代码赢了。

但他没有嘲讽、也没有开香槟。

他只是更新了 unicorn-ui 的 README,新增了一句引用:

“AI 可以加速实现,但无法替你思考架构。”


回到原来那家公司的前端组,有人在偷偷在项目中重新安装 unicorn-ui,把默认按钮样式覆盖到生成式组件之上。

许凡当然知道,但他没有阻止。

因为他明白——这个按钮,虽然是宋执写的,但已经不属于宋执了。

它属于开发者。

属于那些不愿意被 prompt 定义流程、不愿意被工具异化为机器的工程师。

宋执坐在电脑前,打开 Notion,记录下下一阶段的 roadmap:

  • Tabs 组件支持多语言布局方向

  • Dropdown 支持命令面板模式

  • Form 套件与 yup/zod 的集成计划

  • create-unicorn-app 脚手架构想

他喝了一口凉掉的美式,敲下一行标题

第四章:AI 开始抄我组件了!

to be continue

收工,该去吃中午饭了~