Performance Rules
Review performance only where there is realistic impact. Do not request memo, useMemo, useCallback, virtualization, or caching as style preferences.
Async Waterfalls
Flag:
- Awaiting remote feature flags or fetches before checking cheap synchronous conditions.
- Sequential awaits for independent operations.
- API routes or server components starting requests late when they could start early.
- Nested per-item fetches running serially when each item can fetch in parallel.
- Suspense boundaries that force the whole page to wait when a lower boundary could stream or isolate loading.
Prefer Promise.all for independent work and branch-local awaits for conditionally needed data.
Bundle Size
Flag:
- Barrel imports from heavy libraries or
@langgenius/dify-ui. - Dynamic paths that prevent static trace analysis.
- Heavy components loaded eagerly when hidden behind a dialog, tab, command, or feature activation.
- Analytics, logging, editor, visualization, or third-party SDK code loaded before it is needed.
- Feature-local optional modules imported at top level only for rare flows.
Use direct imports and next/dynamic where the user-visible path benefits.
Server Rendering
Flag:
- Request-specific mutable state stored at module scope in SSR/RSC paths.
- Large duplicate data serialized across RSC/client boundaries.
- Static I/O repeated per request when it could be hoisted safely.
- Cross-request cache without a bounded invalidation strategy.
- Server actions lacking API-route-equivalent auth checks.
Use request-scoped deduplication such as React.cache() when repeated server reads in one request are the problem.
Re-rendering
Flag:
- Effects or subscriptions reading broad state when a derived boolean or narrower selector is enough.
- Components defined inside components.
- Derived rendering state stored in state/effects.
- Non-primitive default props recreated for memoized children.
- Expensive work recalculated on every render where it affects real interaction cost.
- High-frequency transient values stored in state when refs or CSS variables would avoid render loops.
Do not flag simple primitive expressions wrapped or not wrapped in useMemo; prefer no memo for simple work.
Require stable object/array/function identity only when:
- The child is memoized and identity affects renders.
- The value is an effect/query dependency.
- A library API requires stable references.
- Profiling or local behavior shows avoidable re-rendering.
DOM, Lists, And Rendering
Flag:
- Layout reads in render (
getBoundingClientRect,offset*,scrollTop). - Interleaved DOM reads/writes that can cause layout thrashing.
- Large lists rendering without virtualization, pagination, or
content-visibility. - SVG/animation code animating expensive properties when transform/opacity would work.
transition-all.- Long-running non-critical browser work performed immediately instead of idle/deferred scheduling.
React Flow
For workflow React Flow components, keep this Dify-specific rule:
- UI consumption should use React Flow hooks such as
useNodes/useEdges. - Callback-only reads or mutations can use
useStoreApi. - Node components under
web/app/components/workflow/nodes/[nodeName]/node.tsxmust not depend on workflow stores that are absent in RAG Pipe template rendering.