← Blog

如何利用 AI 入门前端

后端视角的前端入门路径:三剑客心智模型、组件到 Block、Design Token 分层,以及 vibecoding 时代的工程化门禁。

FrontendTooling

背景

最近想给自己写个个人网站:既当名片,也给文章在网上安个家。灵感来自别人分享知识的方式。记录本身需要动力,所以干脆做个站——哪怕只有一两个人看到,我感觉自己也很有动力。

说实话,我是个很喜欢写代码的人。之前写代码的时候,那种沉浸的感觉很爽,很有动力,有成就感。但是现在vibecoding搞的我很虚无,所以我给自己简单定一些之前从未接触过的东西的目标。让自己重新充实起来。

折腾了大概三周,搓废两个版本之后,我才算搞明白前端工程化大概是怎么回事。

对后端来说,写前端最难的往往不是语法,是选不动技术栈。AI 给的建议看起来哪个都对,而且很多选择根本不是对错问题,是口味问题。就像后端里我不太喜欢 Gorm,觉得重,但 Gorm 也没什么「错」。

所以有一条挺反直觉的结论:

至少自己完整做完一版前端,你才知道某个栈的优劣,以及它合不合你的口味。 对比文、榜单、AI 列的利弊表,都代替不了你亲手走通一版。

下面这些,都是我自己踩完坑之后才有用的东西,不是开写前就能从推荐列表抄全的。

前端三剑客

html + css + js。刚上手别被代码量和语法吓到,那些不重要。

  • html:骨架,搭 DOM 结构。缺购买页、缺按钮,都是结构问题。
  • css:装修,颜色、字号、布局怎么画出来。
  • js:神经。点击、hover 这些事件发生时,你要跑什么逻辑。

这里面,我感觉最难理解的是布局。即html中容器标签的作用。

标签本身不难记:divsectionformlabelinput……难的是:当标签开始嵌套的时候。感觉就变复杂了。

读布局不是一次把整棵 DOM 树背出来,而是自上而下,一层一层展开——跟读后端模块分层一个道理:先看见三层,再点开中间那层。

所以有一句我自己用的入门标准:

当你打开一个网页,随便找到一个block区域, 然后能够通过视觉可以大致看明白这里的的容器标签构成,就代表你对这里入门了。

举个例子:直接看懂一个表单组件

第 1 眼:只切三大块

先别看字段细节。任意登录卡,一眼往往就是:

+------------------------------------------+
| 登录 | ← title
|------------------------------------------|
| |
| (中间一坨:表单项) | ← content
| |
|------------------------------------------|
| 还没有账号? 去注册 | ← foot
+------------------------------------------+

对应容器就三层平级(包在 form / 卡片里):

form / .card
├── div.title ← 标题区
├── div.content ← 主体:所有字段 + 主按钮
└── div.foot ← 次要引导、协议、去注册

这一步只回答一个问题:这张卡从上到下分几段? 标题、主体、页脚。别急着管输入框怎么画。

第 2 眼:展开 div.content

content 里通常是竖着一串字段组 + 最底下的主按钮

div.content
├── div.field ← 邮箱
├── div.field ← 密码
├── div.field ← 记住我
└── button.submit ← 登录(常和 field 平级,不塞进某一个 field)

线框上长这样:

| content |
| +------------------------------------+ |
| | 邮箱 | | ← field
| | [ you@example.com ] | |
| +------------------------------------+ |
| | 密码 [忘记?] | | ← field
| | [ •••••••• 👁 ] | |
| +------------------------------------+ |
| | [ ] 记住我 | | ← field
| +------------------------------------+ |
| | [ 登 录 ] | | ← submit
| +------------------------------------+ |

content 的职责就一件事:把几组 field 和主操作从上往下排好(常见 flex-direction: column + gap)。单行内部怎么横排,还没轮到它管。

第 3 眼:再展开某一个 div.field

只有某栏「看起来不简单」时,才往下拆。比如密码栏:

div.field
├── div.field-head ← 这一行左右分布
│ ├── label 「密码」
│ └── a 「忘记密码?」
└── div.input-wrap ← 输入外壳
├── input
└── button.icon 显示/隐藏

合在一起:从粗到细

form
└── .card
├── div.title
├── div.content ← 先只看到这一坨
│ ├── div.field ← 再展开成 field 列表
│ │ ├── label
│ │ └── input
│ ├── div.field ← 复杂 field 再往下拆
│ │ ├── div.field-head
│ │ └── div.input-wrap
│ ├── div.field.row
│ └── button.submit
└── div.foot

有什么用?

学会这套东西最大的作用,其实不是让你如何写html, 而是明白视图 -> html的转换。 这样在做设计的时候会非常顺畅。

如何练习?建议在写前端的时候,多review代码。哪怕你不懂,能看懂一点是一点。

vibecoding 前端

上面这点东西搞清楚之后,我就开始建站。踩了无数坑,总结了一套比较适合有编程基础的后端同学的玩法。

框架怎么选:先做出一版,别先站队

现在我会建议 React + Tailwind。

对于后端来说,这套东西可以无脑选择。

从组件到 Block

先认组件:干什么用的、长什么样

组件展示。这是我比较喜欢用的一个组件库。

https://retroui.dev/components

再认 Block:一截说得清的页面

AI时代,只认识「组件」不够。组件是零件;真正拼出一页的,是一截一截有业务含义的 Block(区块)

学习写block最好的方式是多看。 这里示例:https://retroui.dev/blocks。

Block最大的作用就是,他已经是无数人沉淀下来的设计美学, 就和后端的设计模式一样。 是可以复用的最大资源。

做 Block 前:先让 AI 用 ASCII 画出来

这是我觉得最值钱的一句 prompt,也最省 token:

先别写代码。用 ASCII 把这个 Block 的布局画出来。 标清:几块区域、文案放哪、主按钮/次按钮、图在哪、手机上怎么叠。 我点头之后,再写实现。

为什么:

  • 直接出代码:布局不对就整文件重写,token 烧得飞快
  • 先画线框:改两行字就行,对齐了再生成一次

大概长这样(丑点没关系):

+--------------------------------------------------+
| [Logo] About Posts [CTA] |
+--------------------------------------------------+
| 标题 | +------------+ |
| 副标题... | | 图 | |
| [主按钮] [次按钮] | +------------+ |
+--------------------------------------------------+
| 卖点1 卖点2 卖点3 |
+--------------------------------------------------+

如何精准改样式

我改样式时其实有两种相反需求:

  1. 只动这一个:这个按钮再大点,别带跑别的
  2. 动同一类:全站主色蓝改紫,卡片底统一亮一点

两种老打架,多半是颜色、间距到处写死。解决办法是 Design Token,以及常见三层:ref → sys → component

Token 是啥

别把 #3B82F616px 抄得到处都是,给它起名集中管:比如主色、中等间距。

DTCG 在推一套交换格式,方便设计和代码共用。你真正要懂的是分层——改哪一层、影响多大。

ref(原始色板、尺度)
→ sys(主色、背景、正文这些语义)
→ component(按钮/卡片具体用哪个语义)
  • ref:颜料。blue.500space.4。一般不让业务组件直接摸。
  • sys:意图。brand.primarybg.default想统一改一类东西,改这层。
  • component:某个零件怎么用。button.primary.bg只想动一个组件,改这层。

全站主色变紫:改 sys 里 brand 指向,别逐个文件找 hex。 只要主按钮更抢眼:改 button 的 component token,别动 brand(链接、徽章可能一起变)。

你想干嘛 改哪
只改某个组件 component
改同一类语义(主色、默认背景) sys
换整套色板 ref(少动)
组件里直接写 #ff0000 别当常态

落地时 token 会变成 CSS 变量(或 Tailwind theme)。业务样式写 var(--button-primary-bg) 这类,别手写魔法数。

跟 AI 改样式,先说影响范围

只调 primary button 的 component token,背景深一点,别动 brand。

把 sys 的 brand.primary 换成紫,引用主色的地方一起变。

别说「把这个 div 背景写成 #7c3aed」(临时原型除外)。

改之前问自己三句:有没有语义?该影响几个组件?挂在哪一层?

如何落地脚手架

搓废两版之后我才认清:难的不是页面画不画得出来,是工程化站不站得住。架子歪了,AI 写得越多越像一锅粥。

配置文件别靠自己手抄一整套。你把目标和验收命令说死,让 AI 生成,你负责跑红灯。

装完你只记这些命令

命令 干什么
pnpm lint eslint + css(Stylelint,含 token 约束)
pnpm lint:fix 能自动修的先修
pnpm format / format:check Prettier(有 Astro 就带 astro 插件)
pnpm tokens:build ref/sys/component → 生成 token CSS
pnpm build 生成 token + 类型检查 + 打包

依赖用 pnpm:更严、省盘、少幽灵依赖。提交 lockfile。别跟 npm/yarn 混用。

目录上有这些角色就行(文件名交给 AI):eslint / stylelint / prettier 配置、tokens/ 三层源、生成脚本 → tokens.css、上面那些 scripts。

分阶段丢 Prompt(一次一件事)

原则就三条:先定验收再实现;一次只干一件事;改完跑命令,红了先修别堆功能。

0. 写进 AGENTS.md 的硬规矩

只用 pnpm。 必须有:lint(= eslint && css)、lint:fixformatformat:checktokens:build。 ESLint 9 flat、Stylelint 16、Prettier(有 astro 就上插件)。 token 三层在 tokens/ref|sys|component.json,业务样式禁止硬编码颜色。 tokens.css 手别改,改源就 tokens:build。 commit前:tokens:build && lint && format:check && build 全过。 别大面积 disable 规则;别写长教程,直接改仓库。

1. 初始化

pnpm 初始化。SPA 用 Vite+React+TS,内容站用 Astro+TS。 lockfile 要留着,pnpm dev 能跑。先别塞业务页。

2. 门禁脚本

把上面那些 script 写进 package.json,工具按 ESLint9 / Stylelint16 / Prettier 配好。 验收:lint、lint:fix、format:check 能跑。

3. ESLint

flat config,TS 覆盖到,any 至少 warn,unused 允许 _ 前缀。React/Astro 按项目加插件。ignore dist、生成物。别跟 Prettier 抢格式规则。

4. Stylelint + 禁硬编码色

业务样式禁止 hex/rgb 硬写颜色,颜色走 var(--...)。ignore 生成出来的 tokens.css。有 astro 要能查 <style>。 验收:业务里写个 #ff0000 必须报错。

5. Prettier

format / format:check。有 Astro 上 prettier-plugin-astro。生成物和 lockfile ignore 掉。

6. DTCG → CSS

ref/sys/component 三份 JSON($value),tokens:build 解析引用输出 tokens.css,全局 import 一次。build 依赖它。Stylelint 继续禁硬编码。 验收:tokens:build + lint + format:check 过。

7. 日常改样式

只改主按钮 → 只动 component 里 button,禁改 sys/ref,禁在组件写 hex,然后 tokens:build && lint。 全站主色 → 只动 sys(必要时 ref),别逐个改组件文件。

如何做设计

前面是代码侧。还有一半容易漏:设计在哪改、改完放哪

写站写到后面,耗时间的经常不是从零发明一页,而是:

  • 换个图标
  • 两栏改三栏
  • 改两行标题
  • 间距松一点、换张图

事小、次数多。每次都丢给 AI 改代码:费 token、容易顺手改歪布局、两周后对话也对不上仓库。

结构、系统的事可以交给 AI;换图标、改字、拧间距,用设计软件直接改更合适。

推荐 Open Design

设计侧我推荐 Open Design:开源、本地优先,设计稿能进 git,也能和本地 coding agent 配合。不必神话工具——它解决的是设计在哪发生、文件怎么留下;token 和 lint 还是在代码仓收口。

小改别默认走 AI

类型 例子 怎么干
微调 图标、两行字、间距、换图 设计软件里改
结构/系统 新 Block、信息架构、整站色板 AI + 仓库门禁
对照落地 设计已定,对齐代码 AI 按 Block/token 改,范围说死

典型浪费:

你:Hero 标题改短,图标换成火箭
AI:读半个仓库 → 改文案 → 顺手改 class → lint 红 → 再修
你:我其实就想改两个字和一个 svg

设计工具里点一下就完了。

设计文件跟仓库放一起

别设计在云端链接、代码在 GitHub、中间靠截图对齐。个人站更稳的是设计和代码同仓(子目录就行):

repo/
├── src/
├── tokens/
├── design/ # 页面、和代码同名的 block、图标源
└── package.json

好处很实在:PR 能一起看;让 AI「对照 design/blocks/Hero」比对照聊天记录靠谱;小改的 diff 也在 git 里。

命名尽量和代码 Block 对齐。色板最终还是映射回 ref/sys/component,别设计和代码两套永久分叉。大文件可以用 LFS,但路径和版本关系要在仓库里说得清。

流程上:

  1. 新页面/新 Block → Open Design 出结构 → 丢进 design/ → 再按 Block 落代码
  2. 换图标改字 → 只开设计工具,别为两个字开长对话
  3. 换品牌色 → 改 tokens,设计侧同步
  4. 收工 → lint/build + 把 design/ 一并 commit

该用软件时跟 AI 说清楚:

这次只改 Hero 标题和图标,你别动仓库。我在 design 里改完再告诉你要不要同步。

设计定了再同步:

design/blocks/HeroWithCTA 为准,只动对应 Block,颜色间距走 token,pnpm lint && pnpm build

Skill:Impeccable

流程对了,还有一层:AI 默认审美很「网感」——紫渐变、圆角卡片、Inter、假精致。后端往往分得出接口好不好,不一定分得出界面俗不俗。

心路:skill 写很多,最后删到只剩一个

最开始我写了很多用来处理前端的skill。但是skill有个问题就是,其实这个东西会让AI过拟合,占用太多token,随着模型能力的提示,我现在基本上skill都删除了。 不用skill去做,而是用前面提到的一整套harness工程来做。

为什么是它

Impeccable仓库)是给 coding agent 用的前端设计 skill:排版、颜色对比、间距、动效、交互、响应式、文案,还带一批反模式,专门对付一看就是 AI 吐的模板脸。

收尾

整条链路其实就这些:

  1. 先做完一版,再谈栈合不合口味
  2. 组件 + Block,做块之前先 ASCII
  3. 样式分 ref/sys/component,说清改局部还是改一类
  4. 脚手架靠命令验收,配置让 AI 写
  5. 小改用设计软件,设计文件进仓库;Open Design 够用
  6. 前端 skill 别堆,审美侧留 Impeccable 就行