mcpField
R
r3f-best-practices

r3f-best-practices

github.com/zebbern开发4.7k53 次安装2 天前更新
代码仓库

关于 r3f-best-practices

面向 React Three Fiber 开发者的参考技能,将生态系统建议整理为按优先级划分的规则,涵盖性能、动画、组件、加载、状态等主题。内容提供单条规则及完整指南的入口。

主要功能

  1. 01涵盖 12 类的 70 多条规则
  2. 02按优先级组织性能建议
  3. 03涉及 Drei、Zustand 和物理
  4. 04包含加载与状态管理模式
  5. 05提供详细规则和示例

适用场景

  1. 01审查 R3F 组件实现
  2. 02减少不必要的重新渲染
  3. 03选择 Drei 辅助工具与加载模式
  4. 04应用状态管理和物理建议

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/zebbern/claude-code-guide --skill r3f-best-practices

安装后在 Claude Code 中输入/r3f-best-practices确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

rules/
_sections.md
drei-use-gltf.md
frame-delta-time.md
loading-suspense.md
perf-never-set-state-in-useframe.md
perf-r3f-perf.md
perf-visibility-toggle.md
perf-zustand-selectors.md

详细介绍

React Three Fiber 最佳实践

React Three Fiber 和 Poimandres 生态系统的综合指南。包含 12 个类别、70 多条规则,并按影响力排序。

来源与致谢

更多技巧请参阅 Utsubo 的 100 条 Three.js 技巧

适用时机

在以下情况下参考这些指南:

  • 编写新的 R3F 组件
  • 优化 R3F 性能(重新渲染是头号问题)
  • 正确使用 Drei 辅助工具
  • 使用 Zustand 管理状态
  • 实现后期处理或物理效果

生态系统覆盖范围

  • @react-three/fiber - Three.js 的 React 渲染器
  • @react-three/drei - 实用辅助工具和抽象
  • @react-three/postprocessing - 后期处理效果
  • @react-three/rapier - 物理引擎
  • zustand - 状态管理
  • leva - 调试 GUI

按优先级划分的规则类别

优先级类别影响前缀
1性能与重新渲染CRITICALperf-
2useFrame 与动画CRITICALframe-
3组件模式HIGHcomponent-
4Canvas 与设置HIGHcanvas-
5Drei 辅助工具MEDIUM-HIGHdrei-
6加载与 SuspenseMEDIUM-HIGHloading-
7状态管理MEDIUMstate-
8事件与交互MEDIUMevents-
9后期处理MEDIUMpostpro-
10物理(Rapier)LOW-MEDIUMphysics-
11Leva(调试 GUI)LOWleva-

快速参考

1. 性能与重新渲染(CRITICAL)
  • perf-never-set-state-in-useframe - 绝不要在 useFrame 中调用 setState
  • perf-isolate-state - 隔离需要 React 状态的组件
  • perf-zustand-selectors - 使用 Zustand 选择器,而不是整个 store
  • perf-transient-subscriptions - 对连续变化的值使用瞬时订阅
  • perf-memo-components - 对开销大的组件进行记忆化
  • perf-keys-for-lists - 为动态列表使用稳定的键
  • perf-avoid-inline-objects - 避免在 JSX 中创建对象/数组
  • perf-dispose-auto - 了解 R3F 的自动释放行为
  • perf-visibility-toggle - 切换可见性,而不是重新挂载
  • perf-r3f-perf - 使用 r3f-perf 监控性能
2. useFrame 与动画(CRITICAL)
  • frame-priority - 使用优先级控制执行顺序
  • frame-delta-time - 始终在动画中使用 delta
  • frame-conditional-subscription - 不需要时禁用 useFrame
  • frame-destructure-state - 仅解构所需内容
  • frame-render-on-demand - 使用 invalidate() 按需渲染
  • frame-avoid-heavy-computation - 将繁重的计算移出 useFrame
3. 组件模式(HIGH)
  • component-jsx-elements - 使用 JSX 创建 Three.js 对象
  • component-attach-prop - 对非标准属性使用 attach
  • component-primitive - 对现有对象使用 primitive
  • component-extend - 对自定义类使用 extend()
  • component-forwardref - 使用 forwardRef 创建可复用组件
  • component-dispose-null - 对共享资源设置 dispose={null}
4. Canvas 与设置(HIGH)
  • canvas-size-container - 让 Canvas 填满父容器
  • canvas-camera-default - 通过属性配置相机
  • canvas-gl-config - 配置 WebGL 上下文
  • canvas-shadows - 在 Canvas 层级启用阴影
  • canvas-frameloop - 选择合适的帧循环模式
  • canvas-events - 配置事件处理
  • canvas-linear-flat - 使用 linear/flat 以确保颜色正确
5. Drei 辅助工具(MEDIUM-HIGH)
  • drei-use-gltf - 使用带预加载功能的 useGLTF
  • drei-use-texture - 使用 useTexture 加载纹理
  • drei-environment - 使用 Environment 实现逼真的光照
  • drei-orbit-controls - 使用来自 Drei 的 OrbitControls
  • drei-html - 使用 Html 添加 DOM 覆盖层
  • drei-text - 使用 Text 添加 3D 文本
  • drei-instances - 使用 Instances 优化实例化
  • drei-use-helper - 使用 useHelper 进行调试可视化
  • drei-bounds - 使用 Bounds 调整相机取景
  • drei-center - 使用 Center 将对象居中
  • drei-float - 使用 Float 实现浮动动画
6. 加载与 Suspense(MEDIUM-HIGH)
  • loading-suspense - 使用 Suspense 包裹异步组件
  • loading-preload - 使用 useGLTF.preload 预加载资源
  • loading-use-progress - 使用 useProgress 显示加载界面
  • loading-lazy-components - 延迟加载较重的组件
  • loading-error-boundary - 处理加载错误
7. 状态管理(MEDIUM)
  • state-zustand-store - 创建职责明确的 Zustand store
  • state-avoid-objects-in-store - 谨慎处理 Three.js 对象
  • state-subscribeWithSelector - 使用细粒度订阅
  • state-persist - 按需持久化状态
  • state-separate-concerns - 按职责拆分 store
8. 事件与交互(MEDIUM)
  • events-pointer-events - 在网格上使用指针事件
  • events-stop-propagation - 阻止事件冒泡
  • events-cursor-pointer - 悬停时更改光标
  • events-raycast-filter - 筛选光线投射
  • events-event-data - 了解事件数据结构
9. 后期处理(MEDIUM)
  • postpro-effect-composer - 使用 EffectComposer
  • postpro-common-effects - 常见效果参考
  • postpro-selective-bloom - 使用 SelectiveBloom 优化辉光
  • postpro-custom-shader - 创建自定义效果
  • postpro-performance - 优化后期处理
10. Rapier 物理(LOW-MEDIUM)
  • physics-setup - Rapier 基本设置
  • physics-body-types - dynamic、fixed、kinematic
  • physics-colliders - 选择合适的碰撞体
  • physics-events - 处理碰撞事件
  • physics-api-ref - 使用 ref 调用物理 API
  • physics-performance - 优化物理效果
11. Leva(LOW)
  • leva-basic - Leva 基本用法
  • leva-folders - 使用文件夹整理
  • leva-conditional - 在生产环境中隐藏

使用方法

阅读各个规则文件,了解详细说明和代码示例:

rules/perf-never-set-state-in-useframe.md
rules/drei-use-gltf.md
rules/state-zustand-selectors.md

完整汇编文档

查看包含所有扩展规则的完整指南:../R3F_BEST_PRACTICES.md

关键模式

切勿在 useFrame 中调用 setState
// BAD - 60 re-renders per second!
function BadComponent() {
  const [position, setPosition] = useState(0);
  useFrame(() => {
    setPosition(p => p + 0.01); // NEVER DO THIS
  });
  return <mesh position-x={position} />;
}

// GOOD - Mutate refs directly
function GoodComponent() {
  const meshRef = useRef();
  useFrame(() => {
    meshRef.current.position.x += 0.01;
  });
  return <mesh ref={meshRef} />;
}
Zustand 选择器
// BAD - Re-renders on ANY store change
const store = useGameStore();

// GOOD - Only re-renders when playerX changes
const playerX = useGameStore(state => state.playerX);

// BETTER - No re-renders, direct mutation
useFrame(() => {
  const { value } = useStore.getState();
  ref.current.position.x = value;
});
Drei useGLTF
import { useGLTF } from '@react-three/drei';

function Model() {
  const { scene } = useGLTF('/model.glb');
  return <primitive object={scene} />;
}

// Preload for instant loading
useGLTF.preload('/model.glb');
Suspense 加载
function App() {
  return (
    <Canvas>
      <Suspense fallback={<Loader />}>
        <Model />
      </Suspense>
    </Canvas>
  );
}
r3f-perf 监控
import { Perf } from 'r3f-perf';

function App() {
  return (
    <Canvas>
      <Perf position="top-left" />
      <Scene />
    </Canvas>
  );
}
切换可见性(而非重新挂载)
// BAD: Remounting destroys and recreates
{showModel && <Model />}

// GOOD: Toggle visibility, keeps instance alive
<Model visible={showModel} />

评论

支持 Markdown