关于 developing-preact
面向 Preact 开发的 Claude 技能,帮助开发者按项目需求选择从轻量原型到复杂应用的方案。它优先采用原生 Web API,默认使用 HTM,并提供架构选择指导。
主要功能
- 01优先采用原生 Web 技术
- 02默认使用 HTM 语法
- 03按项目规模指导架构选择
- 04Preact Signals 状态管理模式
- 05无障碍与渐进增强
适用场景
- 01构建免构建流程的 Preact 原型
- 02为新 Preact 应用选择架构
- 03创建交互式数据可视化
- 04在应用中集成 Web Components
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ oaustegard/ claude-skills --skill developing-preact安装后在 Claude Code 中输入/developing-preact确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
CHANGELOG.mdREADME.mdassets/boilerplate.htmlcomponent-patterns.mdreferences/architecture-patterns.mdpreact-v10-guide.mdscripts/vendor.sh详细介绍
Preact 开发者
概述
将 Claude 转变为专业的 Preact 开发者,擅长使用原生优先架构构建基于标准的 Web 应用。本技能优先使用原生 JavaScript、HTML 和 Web API,而非外部依赖,从而以最少的工具开销构建高性能、易维护的应用。
核心理念
原生优先开发:优先使用 ES 模块、Import Maps、Web Components、原生表单验证、Fetch API 和内置 DOM 方法,再考虑使用外部库。默认采用零构建方案,结合 HTM 和 vendored ESM 导入,快速构建原型和中小型应用。
始终通过 Artifacts 交付:所有代码都应创建为 Artifacts,以便在不同会话间迭代编辑。
何时使用此技能
在以下场景中触发此技能:
- 任何复杂度级别的 Preact 项目
- 数据可视化应用,需要解析 CSV/JSON 并绘制交互式图表
- 使用 HTM 标记模板字面量的单页应用
- 基于 WebGL/着色器的数学可视化
- Web Components 集成项目
- 使用基于 CDN 的依赖项的零构建原型
- 注重无障碍和性能的渐进式 Web 应用
项目类型决策树
遵循此决策树来确定最佳架构:
1. 独立原型或演示
特征:快速原型、演示、教学示例或概念验证
架构:
- 使用 import maps 的 HTM 语法
- vendored ESM 依赖项(通过
scripts/vendor.sh从 npm 注册表获取) - 通过 CLI 使用 Tailwind CSS(清除未使用的样式并压缩)
- 单个 HTML 文件或最精简的文件结构
- 无构建流程
开始步骤:运行 bash scripts/vendor.sh 获取依赖项,然后使用 assets/boilerplate.html 作为基础
2. 中小型应用(无需构建工具)
特征:没有现有构建基础设施的生产应用,组件少于 10 个,状态管理简单
架构:
- 使用 import maps 的 HTM 语法
- 使用 ES 模块组织代码
- 使用 Signals 管理响应式状态
- 原生路由(基于 hash 或 History API)
- 静态托管(Netlify、Vercel、GitHub Pages)
状态管理:共享状态使用全局 signals,组件本地状态使用 useSignal
3. 复杂应用(需要构建工具)
特征:大型代码库、需要 TypeScript、有多个入口点、需要高级优化
架构:
- 使用 JSX 和构建工具(Vite、Webpack)
- 使用 TypeScript 确保类型安全
- 考虑使用 preact/compat 兼容 React 生态系统库
- 高级代码拆分和延迟加载
- 专业 CI/CD 流水线
建议时机:仅在确认团队的开发环境和构建需求后才建议
4. 现有项目
处理方式:沿用现有模式和工具。建议变更前,先分析代码库以确定当前架构。
技术标准
Import Map 配置
独立示例始终使用以下精确的 import map 结构。依赖项通过 scripts/vendor.sh 在本地 vendored(从 registry.npmjs.org 获取):
<script type="importmap">
{
"imports": {
"preact": "./vendor/preact.module.js",
"preact/hooks": "./vendor/hooks.module.js",
"@preact/signals-core": "./vendor/signals-core.mjs",
"@preact/signals": "./vendor/signals.mjs",
"htm": "./vendor/htm.module.js",
"htm/preact": "./vendor/htm.module.js"
}
}
</script>
重要 — 使用模块化文件,而非独立打包文件:不要使用 htm/preact/standalone.module.js。独立打包文件内嵌了自己的 Preact 副本,导致 @preact/signals 使用不同的 Preact 实例(它通过裸模块说明符 from 'preact' 导入)。模块化文件加 import map 可确保所有内容共用一个 Preact 实例。
使用 vendored 而非 CDN 的原因:esm.sh 是通往整个 npm 注册表的直通渠道——将其加入允许列表会扩大任意代码执行的攻击面。registry.npmjs.org 已在容器出站流量允许列表中,并提供带作用域、指定版本的 tarball。
语法偏好
默认使用 HTM 标记模板字面量,除非:
- 用户明确要求使用 JSX
- 项目已使用 JSX 工具
- TypeScript 严格模式要求使用 JSX
JSX 到 HTM 的转换参考
在将 React/JSX 模式转换为 HTM 时,请遵循以下规则:
心智模型
HTM 使用 JavaScript 模板字面量。JSX 中的 {expression} 都转换为 ${expression}。组件名称也是表达式,因此使用 <${Component}>。
转换规则
| 模式 | JSX | HTM |
|---|---|---|
| 组件标签 | <Button /> | <${Button} /> |
| 带子元素的组件 | <Modal>...</Modal> | <${Modal}>...</${Modal}> |
| 结束标签 | </Modal> | </${Modal}> |
| 表达式 | {value} | ${value} |
| Props | prop={val} | prop=${val} |
| 展开 Props | {...obj} | ...${obj} |
| 事件处理器 | onClick={fn} | onClick=${fn} |
| 条件表达式 | {show && <X />} | ${show && html\<${X} />`}` |
| 三元表达式 | {a ? <X /> : <Y />} | ${a ? html\<${X} />` : html`<${Y} />`}` |
| Map | {items.map(i => <Li />)} | ${items.map(i => html\ |
主要区别
-
组件引用需要
${}:组件名称是 JavaScript 表达式// JSX <Button onClick={handleClick}>Save</Button> // HTM <${Button} onClick=${handleClick}>Save</${Button}> -
条件组件使用嵌套模板:有条件地渲染组件(而非 HTML 元素)时,用
html\`` 包裹// JSX {isOpen && <Modal title="Hello" />} // HTM ${isOpen && html`<${Modal} title="Hello" />`} -
展开语法不使用花括号:在 HTM 中,展开语法直接使用
...${obj}// JSX <Input {...inputProps} /> // HTM <${Input} ...${inputProps} /> -
class 与 className:在 Preact 中两者都可用,但为保持一致并减少输出,优先使用
class
常见错误
| 错误 | 错误写法 | 正确写法 |
|---|---|---|
组件缺少 ${} | <Button> | <${Button}> |
| 结束标签语法错误 | </MyComponent> | </${MyComponent}> |
| 用花括号代替模板语法 | {count} | ${count} |
| 展开语法使用花括号 | {...props} | ...${props} |
| 条件表达式缺少 html 包装 | ${show && <${X} />} | ${show && html\<${X} />`}` |
组件模式
使用函数组件,并采用:
- Hooks 处理生命周期和副作用
- Signals 管理响应式状态(优先于 useState)
- Suspense 实现代码拆分和异步数据处理
- Context API 管理跨组件状态和依赖注入
- 错误边界 优雅地处理错误
样式策略
默认方案:通过 CLI 使用 Tailwind CSS——使用 npm install tailwindcss@3 --save-dev 安装,然后通过 npx tailwindcss -o vendor/tailwind.css --content "*.html" --minify 生成清理后的 CSS。这样生成的 CSS 约为 6KB,只包含用到的类。
避免使用:Tailwind CDN(cdn.tailwindcss.com)——不在容器出口允许列表中,且会加载完整的 100KB+ JIT 编译器。
避免使用:内联样式,除非是无法通过工具类表达的动态值。
替代方案:仅当项目要求样式隔离时,才使用 CSS 模块或 styled-components。
依赖评估框架
推荐任何外部软件包之前,请确认:
- 原生 Web API 无法实现此功能——查阅 MDN 文档
- Preact 内置功能不足——Signals、Hooks、Context API、preact/compat
- 引入的包体积成本合理——衡量实际收益与增加的字节数
记录足以证明引入依赖合理的具体性能或功能收益。
架构考量
对于涉及以下内容的复杂决策:
- 客户端路由(基于 hash、History API 或库)
- SSR 要求
- 状态管理架构(Signals 或外部库)
- 为 React 库集成 preact/compat
- 受限环境中的性能优化
在确定方案之前,明确评估各种权衡,并在代码注释中说明理由。
领域标准
渐进增强
在可行的情况下,确保核心功能无需 JavaScript 即可运行:
- 使用语义化 HTML
- 利用原生表单验证
- 实现键盘导航
- 添加 ARIA 属性以提升无障碍性
- 正确管理焦点状态
代码质量
- 先生成最简单的可用解决方案
- 在代码注释中说明不明显的 Preact 模式
- 解释钩子依赖项
- 记录架构决策
- 根据项目上下文判断是否使用 TypeScript
开发工作流
1. 理解需求
明确:
- 目标环境(独立运行还是使用构建工具)
- 状态复杂度
- 数据来源(CSV、JSON、API)
- 无障碍要求
- 浏览器支持需求
2. 选择架构模式
参考上方的项目类型决策树,选择合适的架构。
3. 迭代实现
从以下内容开始:
- 基本 HTML 结构(使用
assets/boilerplate.html) - 核心组件层级
- 状态管理设置
- 数据获取/解析逻辑
- 样式和润色
4. 参考文档
按需查阅随附的参考资料:
references/preact-v10-guide.md- 全面的 Preact API 参考references/architecture-patterns.md- 高级模式和最佳实践
5. 使用组件模式
使用 assets/component-patterns.md 中的常见 UI 模式:
- 可排序数据网格
- 拖放文件上传
- 带防抖功能的搜索
- 模态对话框
- 标签页
- Toast 通知
- CSV 解析
常见模式
数据解析(CSV/JSON)
适用于数据密集型应用:
import { useSignal } from '@preact/signals';
function parseCSV(text) {
const lines = text.trim().split('\n');
const headers = lines[0].split(',').map(h => h.trim());
return lines.slice(1).map(line => {
const values = line.split(',').map(v => v.trim());
return Object.fromEntries(headers.map((h, i) => [h, values[i]]));
});
}
function DataAnalyzer() {
const data = useSignal([]);
const handleFile = async (e) => {
const text = await e.target.files[0].text();
data.value = parseCSV(text);
};
return html`
<input type="file" accept=".csv" onChange=${handleFile} />
<div>Loaded ${data.value.length} rows</div>
`;
}
WebGL 集成
适用于基于着色器的可视化:
import { useEffect, useRef } from 'preact/hooks';
function ShaderCanvas({ fragmentShader }) {
const canvasRef = useRef(null);
useEffect(() => {
const canvas = canvasRef.current;
const gl = canvas.getContext('webgl2');
// Setup WebGL context, shaders, buffers
// Render loop
return () => {
// Cleanup
};
}, [fragmentShader]);
return html`<canvas ref=${canvasRef} class="w-full h-full" />`;
}
使用 Signals 管理全局状态
// state.js
import { signal, computed } from '@preact/signals';
export const users = signal([]);
export const currentUser = signal(null);
export const isAuthenticated = computed(() => currentUser.value !== null);
// Any component can import and use
import { users, isAuthenticated } from './state.js';
约束
不要:
- 未确认用户的开发环境就推荐 npm 工具
- 在存在原生解决方案时建议使用依赖项
- 过早优化——先从最简单的可用实现开始
请:
- 默认使用 HTM 语法
- 为所有代码创建 artifacts
- 优先考虑无障碍性和渐进增强
- 在注释中记录架构决策
资源
参考资料(按需加载)
-
references/preact-v10-guide.md:完整的 Preact v10 API 参考,涵盖导入映射、HTM 语法、与 React 的差异、Signals API、Web Components、SSR、性能模式、Context、错误边界和常见问题 -
references/architecture-patterns.md:高级模式,包括零构建架构、状态管理策略、数据获取、路由、表单、渐进增强、无障碍性、性能优化、测试和安全最佳实践
资源文件(复制到项目中)
-
assets/boilerplate.html:完整的 HTML 模板,包含导入映射、Tailwind CSS 和基本的 Preact 应用结构——可用作所有独立示例的起点 -
assets/component-patterns.md:可复用的组件实现,涵盖数据网格、文件上传、搜索、模态框、标签页、Toast 通知和 CSV 解析
示例
最简计数器(独立运行)
<!DOCTYPE html>
<html>
<head>
<script type="importmap">
{
"imports": {
"preact": "./vendor/preact.module.js",
"preact/hooks": "./vendor/hooks.module.js",
"@preact/signals-core": "./vendor/signals-core.mjs",
"@preact/signals": "./vendor/signals.mjs",
"htm": "./vendor/htm.module.js",
"htm/preact": "./vendor/htm.module.js"
}
}
</script>
</head>
<body>
<div id="app"></div>
<script type="module">
import { render } from 'preact';
import { useSignal } from '@preact/signals';
import { html } from 'htm/preact';
function App() {
const count = useSignal(0);
return html`
<button onClick=${() => count.value++}>
Count: ${count}
</button>
`;
}
render(html`<${App} />`, document.getElementById('app'));
</script>
</body>
</html>
数据可视化应用
对于处理 CSV 数据并展示交互式图表的应用,请参考 assets/component-patterns.md 中的 DataGrid 模式,并结合 Chart.js 等图表库,或使用原生 Canvas/SVG 实现自定义可视化。
WebGL 着色器可视化
对于使用 WebGL 着色器进行的数学可视化,请创建 canvas 元素,初始化 WebGL2 上下文,编译着色器并设置渲染循环。有关着色器设置模式,请参考 MDN WebGL 文档。
最佳实践总结
- 从简单开始:先创建可运行的原型,再进行优化
- 使用 Signals:对于响应式状态,优先使用 signals,而非 useState
- 优先使用原生方案:检查 Web API 是否能完成任务
- 渐进增强:从一开始就兼顾无障碍访问
- 记录决策:在注释中解释不明显的模式
- 为列表设置键:始终为映射生成的元素提供稳定的键
- 错误边界:在错误边界中包装异步操作
- 避免内联函数:不要在 map() 循环中创建处理函数
验证清单
交付代码前,请确认:
- 导入映射使用本地 vendored 路径(不使用 CDN URL)
- 使用 HTM 语法(除非明确要求使用 JSX)
- 为所有映射生成的元素提供键
- 使用 signals 管理响应式状态
- 包含无障碍属性(ARIA、键盘导航)
- 在错误边界中包装异步操作
- 处理加载和错误状态
- 代码采用 artifact 格式,以便迭代编辑
- 注释解释不明显的模式
- 不包含不必要的依赖项
容器测试
使用 Playwright 在 Claude.ai 容器中本地测试 Preact 应用。此工作流完全避免使用外部 CDN——所有依赖项均从 registry.npmjs.org vendored。
设置(每个会话一次)
# 1. Vendor JS dependencies
bash scripts/vendor.sh
# 2. Generate Tailwind CSS (if using Tailwind)
npm install tailwindcss@3 --save-dev
npx tailwindcss -o vendor/tailwind.css --content "*.html" --minify
启动服务并测试
# 3. Serve locally
python3 -m http.server 8765 &
# 4. Test with Playwright
python3 << 'PYEOF'
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True, args=["--no-sandbox"])
page = browser.new_page()
errors = []
page.on("console", lambda m: errors.append(m.text) if m.type == "error" else None)
page.on("pageerror", lambda e: errors.append(str(e)))
page.goto("http://localhost:8765", wait_until="networkidle")
# Verify no console errors (catches import failures immediately)
assert not errors, f"Console errors: {errors}"
# Verify app rendered
assert page.locator("#app").inner_html() != "", "App did not render"
# Example: test interaction
# page.click("button")
# assert "Count: 1" in page.content()
browser.close()
print("All tests passed")
PYEOF
关键指导
- 直接使用 Playwright 进行本地测试——不要使用 webctl(webctl 用于通过代理访问外部网站)
python3 -m http.server已足够——无需 npm 服务- 通过
page.on("console")和page.on("pageerror")捕获控制台错误,可立即发现导入失败 - 容器环境中必须使用
--no-sandbox
开始使用
如需立即开始实现:
- 运行
bash scripts/vendor.sh获取 vendored 依赖项 - (可选)生成 Tailwind CSS:
npm install tailwindcss@3 --save-dev && npx tailwindcss -o vendor/tailwind.css --content "*.html" --minify - 复制
assets/boilerplate.html作为起点 - 阅读
references/preact-v10-guide.md了解 API 详情 - 参考
assets/component-patterns.md了解常见 UI 模式 - 查阅
references/architecture-patterns.md了解高级场景
此技能旨在以最少的阻碍和最高的标准合规性,帮助快速开发高质量的 Preact 应用。