从零搭建浏览器端 AI 原型:React、WebGPU 与 Tailwind CSS 的一次实践
一、为什么关注浏览器端模型
常见的 AI 应用会调用 OpenAI、DeepSeek 等云端 API:
text
浏览器 → 发送 prompt / 上下文 → 云端大模型 → 返回结果
这种方案接入快、模型能力强,但也有明显代价:
- 调用会产生持续成本;
- 网络会带来延迟;
- prompt 和上下文需要传到服务端;
- 离线时无法使用。
浏览器端模型则将推理放到用户设备:
text
浏览器 → 本机 GPU → 本地模型推理 → 页面展示结果
它适合隐私敏感、离线可用、模型较小或任务明确的场景。代价是更受设备性能、浏览器兼容性和模型文件大小限制。
二、项目的技术组合
当前原型采用:
- React:组件化构建页面;
- TypeScript:增加类型约束;
- Vite:提供开发服务器与构建能力;
- Tailwind CSS:用工具类快速完成页面样式;
- WebGPU:尝试调用用户设备 GPU,为浏览器端 AI 推理提供计算能力。
三、先做能力检测:navigator.gpu
在浏览器端使用 WebGPU 前,首先要确认浏览器是否支持:
tsx
const isWebGpuAvailable = !!navigator.gpu
navigator.gpu 是 WebGPU API 的浏览器入口:
- 支持 WebGPU 时,它是对象;
- 不支持时,通常为
undefined; !!可以将结果转换为明确的true或false。
随后可以按能力渲染不同页面:
tsx
return isWebGpuAvailable
? <ModelLoadingPage />
: <p>您的浏览器不支持 WebGPU,请升级浏览器或使用其他浏览器</p>
这就是 React 的条件渲染:根据数据状态决定显示哪一段 UI。
四、React:用状态驱动页面,而不是手动操作 DOM
模型加载过程本身是一个状态变化过程,例如:
text
未开始 → 加载中 → 已就绪
↓
加载失败
React 使用 useState 保存这些状态:
tsx
const [status, setStatus] = useState(null)
const [error, setError] = useState('')
const [loadingMessage, setLoadingMessage] = useState('')
const [progressItems, setProgressItems] = useState([])
调用 setStatus、setError 等 setter 后,React 会重新执行组件函数,再根据新 JSX 更新页面。
例如只在有错误时显示错误区域:
tsx
{error && (
<div className="text-red-500 text-center mb-2">
<p>unable to load model due to error:</p>
<p>{error}</p>
</div>
)}
这里的 && 是 JavaScript 的短路逻辑:error 有值时才渲染右侧 JSX。
注意:若初始值直接写成"出错了",错误 UI 会在页面一开始就显示。更合理的是初始化为空字符串,在捕获到真实异常后再调用
setError。
五、useEffect:处理加载模型这类副作用
组件渲染 JSX 是 React 的主要职责,但下载模型、请求资源、创建定时器等事情属于"副作用"。
tsx
useEffect(() => {
console.log('组件挂载完成')
}, [])
空依赖数组 [] 表示:组件首次显示后执行一次。
后续模型加载逻辑通常会放在这里:
tsx
useEffect(() => {
// 1. 检查 WebGPU
// 2. 下载模型文件
// 3. 更新进度
// 4. 加载完成后设置 ready 状态
}, [])
六、Tailwind CSS 快速完成加载页布局
当前页面使用如下布局类:
tsx
<div className="flex flex-col h-screen items-center justify-end text-gray-800 bg-white">
对应含义:
| Tailwind 类 | 作用 |
|---|---|
flex |
开启弹性布局 |
flex-col |
子元素纵向排列 |
h-screen |
高度占满屏幕 |
items-center |
横向居中 |
justify-end |
纵向靠底部 |
text-gray-800 |
默认深灰色文字 |
bg-white |
白色背景 |
关键点是:items-* 控制交叉轴,justify-* 控制主轴。由于 flex-col 让主轴变成上下方向,所以这里 items-center 是左右居中,justify-end 是靠底部。
Tailwind v4 和 Vite 集成时,使用 @tailwindcss/vite 插件扫描 JSX 的类名,并生成最终 CSS。开发时不需要为每个样式单独写 CSS 选择器。
七、当前原型的完成度与下一步
目前已经完成:
- 搭建 React + TypeScript + Vite 工程;
- 接入 Tailwind CSS;
- 完成 WebGPU 基础能力检测;
- 完成模型加载前说明 UI;
- 预留模型状态、错误信息和下载进度 state。
下一步需要实现:
- 明确状态机:
idle、loading、ready、error; - 接入 Transformers.js 与 ONNX Runtime Web;
- 下载并加载 ONNX 模型;
- 根据真实下载事件更新进度;
- 实现 prompt 输入、模型推理和结果展示;
- 修正
mx-w-[510px]为max-w-[510px]。
八、总结
浏览器端 AI 并不是简单地"把模型放到网页里",而是一个前端工程问题:需要处理浏览器能力检测、资源加载、状态切换、错误提示、进度展示与 GPU 计算。
这个原型的价值在于先搭好了基础框架:用 React 管理页面状态,用 WebGPU 做能力检测,用 Tailwind 快速构建 UI。下一阶段再补齐模型加载与推理链路,就能形成一个完整的端侧 AI Demo。