mcpField
R
r3f-best-practices

r3f-best-practices

github.com/emalorenzo开发651.5k 次安装39 周前更新
代码仓库

关于 r3f-best-practices

面向 React Three Fiber 开发者的实践指南,涵盖性能、动画、组件和 Poimandres 生态工具。它按影响优先级组织规则,并提供规则文件与示例供针对性查阅。

主要功能

  1. 01涵盖 70 多条实践规则
  2. 02按影响优先级分类
  3. 03指导性能与重渲染优化
  4. 04覆盖动画、状态和交互
  5. 05提供规则文件及代码示例

适用场景

  1. 01优化 React Three Fiber 场景性能
  2. 02实现 useFrame 动画与状态管理
  3. 03使用 Drei 加载和处理 3D 资源

安装

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

$npx skills add https://github.com/emalorenzo/three-agent-skills --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