Files
tsl-devkit/skills/thirdparty/ui-ux-pro-max/data/react-performance.csv
T
csh 3d83740f88 Squashed 'docs/standards/playbook/' changes from c3f8137..25d895d
25d895d 🐛 fix(gitea_workflow): clean up temp repos after job steps
2bc3b11 🐛 fix(gitea_workflow): clean up temporary repo dirs in workflows
98c3f30 📝 docs(agent_rules): allow plan execution on current branch
16c7230 📝 docs(prompts): define custom verify layering
8efc4dd 🐛 fix(skills): quote commit-message description
bc8498f 🐛 fix(ci): install tomli for gitea tests
55cda3b 🐛 fix(tests): report missing toml parser clearly
c0729c7 🐛 fix(playbook): import Optional for cli compatibility
63e24bf 📦 deps(skills): sync thirdparty skills
d2f9356 🐛 fix(ci): isolate gitea workflow repos
588b81d 🐛 fix(ci): inline gitea workflow bootstrap
e0b1c3a ♻️ refactor(skills): standardize first-party skill contracts
2c5050d ♻️ refactor(skills): rename repo skills source dir
f049dfb 📦 deps(skills): drop duplicate first-party superpowers skills
234b335  feat(workflow): add superpowers planning and execution state tracking
c1702a6 📝 docs(markdown): format tracked markdown and drop stale templates
2325409 📝 docs(markdown): clarify optional markdownlint usage
214c44e 🔧 chore(markdown): add markdownlint baseline and lint fixes
a22b324 📝 docs(templates): add execution and memory-bank prompt templates
223a797 📝 docs(templates): update README for Claude Code and current features
4ac8672 📝 docs: simplify README + platform-agnostic tools + auto-create local rules
2431c9d 📝 docs: add claude_md config and use cross-platform paths
d64b248 📝 docs: fix README.md inaccuracies and add Claude Code info
c8d6bf2 🐛 fix(playbook): use relative paths in CLAUDE.md when not at project root
6518f0f  feat(playbook): auto-create CLAUDE.md with path discovery
6ec9a45  feat(skills): add skill_link symlink support + platform-agnostic prompt
9f8b6b5 📝 docs: update README and config example for Claude Code support
79cff6c 📝 docs(skills): add Claude Code platform support
452c6f5  feat(playbook): auto-inject AGENTS.md into CLAUDE.md
e1dbf3c 🐛 fix(skills): remove dual-path from commit-message skill
f3a7259 🔧 chore(ci): use prepare_repo.sh in both workflows
da08212 🔧 chore(ci): extract prepare_repo.sh and clean up workflows
7ade85e 🗑️ remove(tsl): drop syntax_book/, data/ source and build script
f94dba0 ♻️ refactor(skills): update playbook.py and tests for thirdparty/ layout
b3df412 ♻️ refactor(skills): separate thirdparty skills into thirdparty/ subdirectory
64950e7 📦 deps(skills): sync thirdparty skills
a2e3cb0  feat(playbook): add no_backup deploy controls
8609d59 🐛 fix(docs): repair reference catalog source links
956da11 🐛 fix(playbook): publish hidden ci test fixes
3f67754 📦 deps(skills): sync thirdparty skills
08ca87b 📦 deps(skills): add karpathy thirdparty sync
96b705b 📝 docs(tsl): rebuild canonical syntax and routing manual
3ed5052 📦 deps(skills): sync thirdparty skills
60108dd 📦 deps(skills): sync thirdparty skills
da85d4e 🐛 fix(thirdparty): prune nested project snapshots
a2a697e 📦 deps(skills): sync thirdparty skills
9df610a 🐛 fix(thirdparty): exclude duplicated superpowers skills
33dd5bb 🐛 fix(thirdparty): preserve optional manifest fields
91b0ea7 🐛 fix(thirdparty): preserve manifest during snapshot update
2e26f98 🔧 chore(thirdparty): generalize skills sync pipeline
5b9c1e3 📦 deps(skills): sync superpowers
2f2d34a 📝 docs(readme): normalize subtree command spacing
62db7db 🐛 fix(ci): serialize superpowers update and sync
3463223 🐛 fix(ci): use literal superpowers sync paths
48f6de8 📦 deps(skills): sync superpowers
4b23529 🔧 chore(ci): merge superpowers update and sync workflow
a56d75b 📦 deps(skills): sync superpowers
84bcefa 🔧 chore(ci): use ci[bot] commit author name
00a07e5 📦 deps(skills): sync superpowers
7b84daf 🐛 fix(templates): enforce main loop progress tracking
51373d7 🔧 chore(ci): automate superpowers sync workflow
eaaa39c 🐛 fix(ci): prevent stale superpowers sync from restoring skills block
79755c6 📦 deps(skills): sync superpowers
836d878 📦 deps(skills): sync superpowers
8216c9f 📦 deps(skills): sync superpowers
9439505 🐛 fix(playbook): address reported repo issues

git-subtree-dir: docs/standards/playbook
git-subtree-split: 25d895d8b3f56624ccfe99ad7289e9eb49e0f316
2026-05-24 13:04:14 +08:00

14 KiB

1NoCategoryIssueKeywordsPlatformDescriptionDoDon'tCode Example GoodCode Example BadSeverity
21Async WaterfallDefer Awaitasync await defer branchReact/Next.jsMove await into branches where actually used to avoid blocking unused code pathsMove await operations into branches where they're neededAwait at top of function blocking all branchesif (skip) return { skipped: true }; const data = await fetch()const data = await fetch(); if (skip) return { skipped: true }Critical
32Async WaterfallPromise.all Parallelpromise all parallel concurrentReact/Next.jsExecute independent async operations concurrently using Promise.all()Use Promise.all() for independent operationsSequential await for independent operationsconst [user, posts] = await Promise.all([fetchUser(), fetchPosts()])const user = await fetchUser(); const posts = await fetchPosts()Critical
43Async WaterfallDependency Parallelizationbetter-all dependency parallelReact/Next.jsUse better-all for operations with partial dependencies to maximize parallelismUse better-all to start each task at earliest possible momentWait for unrelated data before starting dependent fetchawait all({ user() {}, config() {}, profile() { return fetch((await this.$.user).id) } })const [user, config] = await Promise.all([...]); const profile = await fetchProfile(user.id)Critical
54Async WaterfallAPI Route Optimizationapi route waterfall promiseReact/Next.jsIn API routes start independent operations immediately even if not awaited yetStart promises early and await lateSequential awaits in API handlersconst sessionP = auth(); const configP = fetchConfig(); const session = await sessionPconst session = await auth(); const config = await fetchConfig()Critical
65Async WaterfallSuspense Boundariessuspense streaming boundaryReact/Next.jsUse Suspense to show wrapper UI faster while data loadsWrap async components in Suspense boundariesAwait data blocking entire page render<Suspense fallback={<Skeleton />}><DataDisplay /></Suspense>const data = await fetchData(); return <DataDisplay data={data} />High
76Bundle SizeBarrel Importsbarrel import direct pathReact/Next.jsImport directly from source files instead of barrel files to avoid loading unused modulesImport directly from source pathImport from barrel/index filesimport Check from 'lucide-react/dist/esm/icons/check'import { Check } from 'lucide-react'Critical
87Bundle SizeDynamic Importsdynamic import lazy nextReact/Next.jsUse next/dynamic to lazy-load large components not needed on initial renderUse dynamic() for heavy componentsImport heavy components at top levelconst Monaco = dynamic(() => import('./monaco'), { ssr: false })import { MonacoEditor } from './monaco-editor'Critical
98Bundle SizeDefer Third Partyanalytics defer third-partyReact/Next.jsLoad analytics and logging after hydration since they don't block interactionLoad non-critical scripts after hydrationInclude analytics in main bundleconst Analytics = dynamic(() => import('@vercel/analytics'), { ssr: false })import { Analytics } from '@vercel/analytics/react'Medium
109Bundle SizeConditional Loadingconditional module lazyReact/Next.jsLoad large data or modules only when a feature is activatedDynamic import when feature enabledImport large modules unconditionallyuseEffect(() => { if (enabled) import('./heavy.js') }, [enabled])import { heavyData } from './heavy.js'High
1110Bundle SizePreload Intentpreload hover focus intentReact/Next.jsPreload heavy bundles on hover/focus before they're neededPreload on user intent signalsLoad only on clickonMouseEnter={() => import('./editor')}onClick={() => import('./editor')}Medium
1211ServerReact.cache Dedupreact cache deduplicate requestReact/Next.jsUse React.cache() for server-side request deduplication within single requestWrap data fetchers with cache()Fetch same data multiple times in treeexport const getUser = cache(async () => await db.user.find())export async function getUser() { return await db.user.find() }Medium
1312ServerLRU Cache Cross-Requestlru cache cross requestReact/Next.jsUse LRU cache for data shared across sequential requestsUse LRU for cross-request cachingRefetch same data on every requestconst cache = new LRUCache({ max: 1000, ttl: 5*60*1000 })Always fetch from databaseHigh
1413ServerMinimize Serializationserialization rsc boundaryReact/Next.jsOnly pass fields that client actually uses across RSC boundariesPass only needed fields to client componentsPass entire objects to client<Profile name={user.name} /><Profile user={user} /> // 50 fields serializedHigh
1514ServerParallel Fetchingparallel fetch component compositionReact/Next.jsRestructure components to parallelize data fetching in RSCUse component composition for parallel fetchesSequential fetches in parent component<Header /><Sidebar /> // both fetch in parallelconst header = await fetchHeader(); return <><div>{header}</div><Sidebar /></>Critical
1615ServerAfter Non-blockingafter non-blocking loggingReact/Next.jsUse Next.js after() to schedule work after response is sentUse after() for logging/analyticsBlock response for non-critical operationsafter(async () => { await logAction() }); return Response.json(data)await logAction(); return Response.json(data)Medium
1716ClientSWR Deduplicationswr dedup cache revalidateReact/Next.jsUse SWR for automatic request deduplication and cachingUse useSWR for client data fetchingManual fetch in useEffectconst { data } = useSWR('/api/users', fetcher)useEffect(() => { fetch('/api/users').then(setUsers) }, [])Medium-High
1817ClientEvent Listener Dedupevent listener deduplicate globalReact/Next.jsShare global event listeners across component instancesUse useSWRSubscription for shared listenersRegister listener per component instanceuseSWRSubscription('global-keydown', () => { window.addEventListener... })useEffect(() => { window.addEventListener('keydown', handler) }, [])Low
1918RerenderDefer State Readsstate read callback subscriptionReact/Next.jsDon't subscribe to state only used in callbacksRead state on-demand in callbacksSubscribe to state used only in handlersconst handleClick = () => { const params = new URLSearchParams(location.search) }const params = useSearchParams(); const handleClick = () => { params.get('ref') }Medium
2019RerenderMemoized Componentsmemo extract expensiveReact/Next.jsExtract expensive work into memoized components for early returnsExtract to memo() componentsCompute expensive values before early returnconst UserAvatar = memo(({ user }) => ...); if (loading) return <Skeleton />const avatar = useMemo(() => compute(user)); if (loading) return <Skeleton />Medium
2120RerenderNarrow Dependencieseffect dependency primitiveReact/Next.jsSpecify primitive dependencies instead of objects in effectsUse primitive values in dependency arraysUse object references as dependenciesuseEffect(() => { console.log(user.id) }, [user.id])useEffect(() => { console.log(user.id) }, [user])Low
2221RerenderDerived Statederived boolean subscriptionReact/Next.jsSubscribe to derived booleans instead of continuous valuesUse derived boolean stateSubscribe to continuous valuesconst isMobile = useMediaQuery('(max-width: 767px)')const width = useWindowWidth(); const isMobile = width < 768Medium
2322RerenderFunctional setStatefunctional setstate callbackReact/Next.jsUse functional setState updates for stable callbacks and no stale closuresUse functional form: setState(curr => ...)Reference state directly in setStatesetItems(curr => [...curr, newItem])setItems([...items, newItem]) // items in depsMedium
2423RerenderLazy State Initusestate lazy initializationReact/Next.jsPass function to useState for expensive initial valuesUse function form for expensive initCompute expensive value directlyuseState(() => buildSearchIndex(items))useState(buildSearchIndex(items)) // runs every renderMedium
2524RerenderTransitionsstarttransition non-urgentReact/Next.jsMark frequent non-urgent state updates as transitionsUse startTransition for non-urgent updatesBlock UI on every state changestartTransition(() => setScrollY(window.scrollY))setScrollY(window.scrollY) // blocks on every scrollMedium
2625RenderingSVG Animation Wrappersvg animation wrapper divReact/Next.jsWrap SVG in div and animate wrapper for hardware accelerationAnimate div wrapper around SVGAnimate SVG element directly<div class='animate-spin'><svg>...</svg></div><svg class='animate-spin'>...</svg>Low
2726RenderingContent Visibilitycontent-visibility autoReact/Next.jsApply content-visibility: auto to defer off-screen renderingUse content-visibility for long listsRender all list items immediately.item { content-visibility: auto; contain-intrinsic-size: 0 80px }Render 1000 items without optimizationHigh
2827RenderingHoist Static JSXhoist static jsx elementReact/Next.jsExtract static JSX outside components to avoid re-creationHoist static elements to module scopeCreate static elements inside componentsconst skeleton = <div class='animate-pulse' />; function C() { return skeleton }function C() { return <div class='animate-pulse' /> }Low
2928RenderingHydration No Flickerhydration mismatch flickerReact/Next.jsUse inline script to set client-only data before hydrationInject sync script for client-only valuesUse useEffect causing flash<script dangerouslySetInnerHTML={{ __html: 'el.className = localStorage.theme' }} />useEffect(() => setTheme(localStorage.theme), []) // flickersMedium
3029RenderingConditional Renderconditional render ternaryReact/Next.jsUse ternary instead of && when condition can be 0 or NaNUse explicit ternary for conditionalsUse && with potentially falsy numbers{count > 0 ? <Badge>{count}</Badge> : null}{count && <Badge>{count}</Badge>} // renders '0'Low
3130RenderingActivity Componentactivity show hide preserveReact/Next.jsUse Activity component to preserve state/DOM for toggled componentsUse Activity for expensive toggle componentsUnmount/remount on visibility toggle<Activity mode={isOpen ? 'visible' : 'hidden'}><Menu /></Activity>{isOpen && <Menu />} // loses stateMedium
3231JS PerfBatch DOM CSSbatch dom css reflowReact/Next.jsGroup CSS changes via classes or cssText to minimize reflowsUse class toggle or cssTextChange styles one property at a timeelement.classList.add('highlighted')el.style.width='100px'; el.style.height='200px'Medium
3332JS PerfIndex Map Lookupmap index lookup findReact/Next.jsBuild Map for repeated lookups instead of multiple .find() callsBuild index Map for O(1) lookupsUse .find() in loopsconst byId = new Map(users.map(u => [u.id, u])); byId.get(id)users.find(u => u.id === order.userId) // O(n) each timeLow-Medium
3433JS PerfCache Property Accesscache property loopReact/Next.jsCache object property lookups in hot pathsCache values before loopsAccess nested properties in loopsconst val = obj.config.settings.value; for (...) process(val)for (...) process(obj.config.settings.value)Low-Medium
3534JS PerfCache Function Resultsmemoize cache functionReact/Next.jsUse module-level Map to cache repeated function resultsUse Map cache for repeated callsRecompute same values repeatedlyconst cache = new Map(); if (cache.has(x)) return cache.get(x)slugify(name) // called 100 times same inputMedium
3635JS PerfCache Storage APIlocalstorage cache readReact/Next.jsCache localStorage/sessionStorage reads in memoryCache storage reads in MapRead storage on every callif (!cache.has(key)) cache.set(key, localStorage.getItem(key))localStorage.getItem('theme') // every callLow-Medium
3736JS PerfCombine Iterationscombine filter map loopReact/Next.jsCombine multiple filter/map into single loopSingle loop for multiple categorizationsChain multiple filter() callsfor (u of users) { if (u.isAdmin) admins.push(u); if (u.isTester) testers.push(u) }users.filter(admin); users.filter(tester); users.filter(inactive)Low-Medium
3837JS PerfLength Check Firstlength check array compareReact/Next.jsCheck array lengths before expensive comparisonsEarly return if lengths differAlways run expensive comparisonif (a.length !== b.length) return true; // then comparea.sort().join() !== b.sort().join() // even when lengths differMedium-High
3938JS PerfEarly Returnearly return exit functionReact/Next.jsReturn early when result is determined to skip processingReturn immediately on first errorProcess all items then check errorsfor (u of users) { if (!u.email) return { error: 'Email required' } }let hasError; for (...) { if (!email) hasError=true }; if (hasError)...Low-Medium
4039JS PerfHoist RegExpregexp hoist moduleReact/Next.jsDon't create RegExp inside render - hoist or memoizeHoist RegExp to module scopeCreate RegExp every renderconst EMAIL_RE = /^[^@]+@[^@]+$/; function validate() { EMAIL_RE.test(x) }function C() { const re = new RegExp(pattern); re.test(x) }Low-Medium
4140JS PerfLoop Min Maxloop min max sortReact/Next.jsUse loop for min/max instead of sort - O(n) vs O(n log n)Single pass loop for min/maxSort array to find min/maxlet max = arr[0]; for (x of arr) if (x > max) max = xarr.sort((a,b) => b-a)[0] // O(n log n)Low
4241JS PerfSet Map Lookupsset map includes hasReact/Next.jsUse Set/Map for O(1) lookups instead of array.includes()Convert to Set for membership checksUse .includes() for repeated checksconst allowed = new Set(['a','b']); allowed.has(id)const allowed = ['a','b']; allowed.includes(id)Low-Medium
4342JS PerftoSorted Immutabletosorted sort immutableReact/Next.jsUse toSorted() instead of sort() to avoid mutating arraysUse toSorted() for immutabilityMutate arrays with sort()users.toSorted((a,b) => a.name.localeCompare(b.name))users.sort((a,b) => a.name.localeCompare(b.name)) // mutatesMedium-High
4443AdvancedEvent Handler Refsuseeffectevent ref handlerReact/Next.jsStore callbacks in refs for stable effect subscriptionsUse useEffectEvent for stable handlersRe-subscribe on every callback changeconst onEvent = useEffectEvent(handler); useEffect(() => { listen(onEvent) }, [])useEffect(() => { listen(handler) }, [handler]) // re-subscribesLow
4544AdvanceduseLatest Hookuselatest ref callbackReact/Next.jsAccess latest values in callbacks without adding to dependency arraysUse useLatest for fresh values in stable callbacksAdd callback to effect dependenciesconst cbRef = useLatest(cb); useEffect(() => { setTimeout(() => cbRef.current()) }, [])useEffect(() => { setTimeout(() => cb()) }, [cb]) // re-runsLow