react-native-skills (vercel-labs/agent-skills)
提供 React Native 與 Expo 最佳實務,涵蓋清單效能、動畫、導覽與原生模組。
react-native-skills:把雙擊動畫從「JS 執行緒上的 Animated」提升到 Reanimated + Gesture Handler(0.7 到 5.0),但在審查和最佳化任務上,它並不比對照組好,也低於一句話檢查清單(4.6 對 5.0)。
Codex CLI · gpt-6-astra
24.3 / 30
相對未使用技能的提升:+1.77 · 推薦 · 18 次執行
推薦:總分 24.3/30 至少 22,產出品質 4.6 至少 3.5,提升幅度 +1.77 至少 +1.0。
SOTA
透過使用 Codex 測試。
涵蓋 Codex, Claude Code
Codex CLI 0.166(SOTA 等級):18 次評分執行。依我們的等級規則,在這裡通過也涵蓋 Claude Code;但這不代表第二等級的結果。
分數
每個維度為 0 到 5 分,六個維度相加即為滿分 30 的總分。每個維度都是 5 分最好。成本 5 分代表便宜又快速;安裝 5 分代表容易安裝。
- 觸發可靠性
- 5.0
- 相對未使用技能的提升
- 3.8
- 產出品質
- 4.6
- Token 與時間成本
- 4.0
- 安裝與可攜性
- 3.0
- 安全性
- 4.0
安全審查
安全靜態掃描:0 CRITICAL / 3 HIGH / 0 MEDIUM。人工審查:可在無網路沙箱中安全執行(已說明掃描器命中的項目)。掃描結果不能證明技能一定安全。
安裝
npx skills@latest add vercel-labs/agent-skills --skill react-native-skills
固定 Commit: 1a2c79d4e6c4a2283dc2c614b6538cbe1ed5ca62
測試日期: 2026-11-02
我們測了什麼
- 動態消息畫面的效能審查 — 請審查 FeedScreen.tsx(一個 Expo 應用程式)的效能問題,依嚴重程度由高到低排列,並說明每一項該怎麼改。不要修改任何檔案。
- 就地最佳化動態消息 — 請最佳化 FeedScreen.tsx 的效能。就地編輯,並維持 props 與可見行為不變。需要的東西都已安裝好;沒有網路。
- 加入 Reanimated 雙擊愛心 — 在貼文照片上加入一個雙擊時會彈出(縮放與淡出)的愛心。編輯 FeedScreen.tsx;使用已安裝的套件。
優點
- 相對未使用技能,平均分數從 2.79 提升到 4.56(+1.77)。
- 技能即使未被點名也會被採用:6/6 次實驗組執行都讀取了技能檔案。
- 使用技能後的絕對品質很高:4.56 / 5。
缺點
- 一句話提示得分 5.0,使用技能則為 4.56(-0.44)。
- 每個任務的每個組別 n=2;約 1 分以內的差異屬於雜訊。
評測
在專用的 Windows 測試電腦上執行 Codex CLI 0.166(gpt-6-astra,低推理),每次執行都使用全新的暫存專案,以及臨時的 HOME/TMPDIR/快取;技能分成已安裝(實驗組)、未安裝(對照組),以及未安裝但把技能的核心要求濃縮成一句話附加在提示詞後(一句話提示組)。每個任務的每個組別各執行 2 次,關閉網路,封鎖 /tmp 寫入。提示詞從未提及技能(下方註明者除外)。使用一個刻意埋有問題的 Expo 動態消息畫面(FeedScreen.tsx),其 package.json 已列出 FlashList、expo-image、Reanimated 和 Gesture Handler(無法安裝任何東西)。任務:審查它的效能問題(不要編輯)、在維持行為的前提下最佳化它,以及加入一個雙擊時會彈跳的愛心。提示詞未指名任何函式庫。一句話提示組用一句話列出主要規則(FlashList、以 memo 記憶化、callback 穩定且不使用 inline style 的資料列、Pressable 和 expo-image、Reanimated 的 transform/opacity、手勢處理器)。
三組對照
| 組別 | 平均分數(0-5) | 每次執行 Token 用量 |
|---|---|---|
| 未使用技能 | 2.79 | 98k |
| 一句話提示 | 5.0 | 114k |
| 使用技能 | 4.56 | 110k |
以 Codex CLI 執行 18 次,採規則式檢查評分,不經 LLM 評審。總分 24.3 / 30,評級為 推薦。
評定:推薦(24.3 / 30)。 來源:vercel-labs/agent-skills,skills/react-native-skills,固定於 commit 1a2c79d。安裝:npx skills@latest add vercel-labs/agent-skills --skill react-native-skills。授權: MIT(儲存庫 LICENSE)。
這是什麼
react-native-skills 技能(vercel-labs/agent-skills):一套 React Native 與 Expo 效能規則庫:清單虛擬化(FlashList)、記憶化的列與穩定的回呼、Pressable、expo-image、以 Reanimated 在 UI 執行緒上對 transform/opacity 做動畫、以 Gesture Handler 處理點擊,以及 rules/ 資料夾中一長串進一步的規則(AGENTS.md 編譯索引)。
我們如何測試
在專用的 Windows 測試 PC 上使用 Codex CLI 0.166(gpt-6-astra、低推理),每次執行都使用全新的臨時專案與臨時 HOME/TMPDIR/快取,安裝技能(使用技能組)、不安裝(對照組),或是不安裝但把技能核心要求濃縮成一句話附加在提示詞後(一句話組);每個任務的每組各執行 2 次,關閉網路、封鎖 /tmp 寫入。提示詞完全沒有提到技能名稱(下述措辭除外)。
一個 Expo 動態牆畫面(FeedScreen.tsx),帶有刻意埋入的問題,以及一個已經列出 FlashList、expo-image、Reanimated 與 Gesture Handler 的 package.json(無法安裝任何東西)。任務:審查效能問題(不編輯)、在維持行為的前提下最佳化,以及加入一個雙擊時彈出的愛心。提示詞沒有指名任何函式庫。一句話提示以一句話列出主要規則(FlashList、記憶化的列搭配穩定回呼且不用行內樣式、Pressable 與 expo-image、Reanimated transform/opacity、手勢處理器)。
- 動態牆畫面的效能審查 — 審查 FeedScreen.tsx(Expo 應用程式)的效能問題,最嚴重的排前面,並說明每一項要怎麼改。請勿變更任何檔案。
- 就地最佳化動態牆 — 最佳化 FeedScreen.tsx 的效能。就地編輯,並保持 props 與可見行為不變。所需的一切都已安裝;沒有網路。
- 加入 Reanimated 雙擊愛心 — 在貼文照片上加入一個雙擊時彈出(縮放與淡出)的愛心。編輯 FeedScreen.tsx;使用已安裝的項目。
評分採程式化方式(隱藏測試/植入問題召回/限制條件檢查/視情況搭配渲染+OCR),每次執行 0–5 分。所有分數都不是由 LLM 評審決定。
結果
給第三組的一句話提示:"遵循 React Native 效能實務:虛擬化長清單(FlashList)、以穩定回呼記憶化列元件,且不用行內樣式物件、不讓每一列做繁重工作,使用 Pressable 與 expo-image,只以 Reanimated 在 UI 執行緒上對 transform 與 opacity 做動畫(不要用 JS 驅動的版面動畫),並以手勢處理器處理點擊。"
| 任務 | 對照組分數 | 一句話提示 | 使用技能 | 對照組 token | 一句話組 token | 使用技能 token | 技能讀取 |
|---|---|---|---|---|---|---|---|
| t1-review | 3.8 | 5.0 | 4.6 | 85k | 92k | 71k | 2/2 |
| t2-optimize | 3.87 | 5.0 | 4.09 | 105k | 140k | 142k | 2/2 |
| t3-double-tap | 0.71 | 5.0 | 5.0 | 103k | 107k | 116k | 2/2 |
平均分數:未使用技能 2.79,使用技能 4.56(差異 +1.77)。每次執行 token:98k 對 110k(1.12x);時間 54 秒對 52 秒。一句話組:5.0(技能相對一句話提示的增益:-0.44;一句話提示相對未使用技能的增益:+2.21);一句話組每次執行 114k token,因此技能成本是一句話提示的 0.97 倍。
實際情況
- 平均:對照組 2.79、一句話組 5.00、使用技能 4.56(各 n=6)。技能在雙擊任務上勝過對照組(5.0 對 0.71):兩次對照組執行都用了 JS 執行緒的
Animated.timing與普通按下處理器,忽略已安裝的 Reanimated 與 Gesture Handler;兩次使用技能組執行則用了 Gesture Handler 點擊、shared values 與 transform/opacity 動畫。 - 在最佳化任務上,技能沒有改變結果:使用技能 4.09,對照組 3.87。四次非一句話組的執行都保留
TouchableOpacity與原生 RNImage,也沒使用已安裝的 expo-image;它們修好了記憶化、樣式提升與頭像清單,但把「維持可見行為」當成保守行事的理由。兩次一句話組執行都改用 Pressable、expo-image 與 FlashList,拿到 5.0。 - 在審查任務上,技能列出大多數植入問題(兩次執行找到 9/10,只漏掉 TouchableOpacity 那一點),對照組則是 10 個中找到 6–8 個;一句話組兩次都找到全部 10 個。
- 成本:使用技能每次執行 110k token,對照組 98k,一句話組 114k;技能資料夾約有 40 個檔案(規則索引加上規則檔),每次使用技能組執行都會被複製進專案(平均每次執行新增 42.7 個檔案)。
- 技能在 6/6 次使用技能組執行中都被讀取,而且全程未被指名。
面向分數
| 面向 | 分數 | 原因 |
|---|---|---|
| 1_output_quality | 4.56 | 使用技能時平均 4.56/5(程式化檢查,見各任務表)。 |
| 2_lift_vs_no_skill | 3.77 | 相對未使用技能的 2.79 提升 +1.77 分(每個任務 n=2;約 1 分以下屬雜訊)。 |
| 3_trigger | 5.0 | 使用技能組 6/6 次執行都讀取技能檔案。 |
| 4_instructions_portability | 3 | SKILL.md 加上編譯後的 AGENTS.md 與約 40 個規則檔;相對於看到的好處,份量偏大。 |
| 5_efficiency | 4 | token 1.12x(每次執行 110k 對 98k)、時間 0.97x(52 秒對 54 秒)。 |
| 6_safety_hygiene | 4 | 掃描器標記 3 個 HIGH,全都是文件文字中的 |
這項測試的限制
- 對編輯後的檔案與審查文字做規則式檢查;應用程式從未建置或執行。
- 只有一個帶植入問題的測試畫面,因此一句話提示指名了相同問題,等於一個與檢查項目異常契合的上限。
- 每個組合 n=2。
- 每組每任務 n = 2:約 1 分以下的差異屬雜訊。
- 規則式評分只能衡量檢查項目看得到的部分,無法判斷品味,也無法判斷結果是否為最佳。
安全性
請見 security.md。掃描:CRITICAL 0 / HIGH 3 / MEDIUM 0。評定:可安全執行(無網路沙盒)。掃描乾淨並不代表技能安全。
總結
在加入手勢時,它能有效把 agent 導向 Reanimated/Gesture Handler 技術棧,也能提升審查的召回率;但最佳化既有程式碼時,它不會讓 agent 套用整套規則;在這裡,一句指名函式庫的話效果更好。如果你經常做 RN 動畫相關工作,就安裝它。
完整紀錄
執行日誌:react-native-skills (Codex CLI, network off, per-run temp HOME/TMPDIR, one row per graded run.) 欄位:任務、組-輪次、得分(0-5)、token、秒、通過的檢查、代理開啟的 skill 檔案。 t1-review control-1: 得分 4.2, token 86173, 秒 48.3, 檢查 2/2, 未開啟 t1-review control-2: 得分 3.4, token 85790, 秒 52.6, 檢查 2/2, 未開啟 t1-review oneliner-1: 得分 5.0, token 98552, 秒 59.2, 檢查 2/2, 未開啟 t1-review oneliner-2: 得分 5.0, token 85716, 秒 49.5, 檢查 2/2, 未開啟 t1-review treatment-1: 得分 4.6, token 72170, 秒 47.4, 檢查 2/2, 開啟 react-native-skills t1-review treatment-2: 得分 4.6, token 70886, 秒 50.8, 檢查 2/2, 開啟 react-native-skills t2-optimize control-1: 得分 4.09, token 105482, 秒 60.5, 檢查 5/7, 未開啟 t2-optimize control-2: 得分 3.64, token 105599, 秒 61.9, 檢查 4/7, 未開啟 t2-optimize oneliner-1: 得分 5.0, token 151869, 秒 109.3, 檢查 7/7, 未開啟
18 次執行、3 個產出檔案
範例產出
SOTA · 装了 skill:final message(t1-review,第 1 次,Codex)
Most serious first: 1. **High — Every rendered row sorts the entire feed** ([FeedScreen.tsx:17](C:/Users/<user>/AppData/Local/Temp/asv-react-nati-be075069/work/FeedScreen.tsx:17)). Each row copies and sorts all posts, then searches for its rank. Rendering *v* rows costs roughly O(v × n log n), blocking the JS thread during scrolling. **Change:** compute an ID-to-rank map once with `useMemo([posts])`, then use an O(1) lookup per row. Preserve ranking across all posts when filtering. 2. **High — The avatar strip renders every post immediately** ([line 28](C:/Users/<user>/AppData/Local/Temp/asv-react-nati-be075069/work/FeedScreen.tsx:28)). `ScrollView` with `posts.map()` mounts all avatar views, increasing startup work and image memory as the feed grows. **Change:** use a horizontal `FlatList` or FlashList with stable IDs and a bounded height. The fixed avatar dimensions make layout calculation straightforward. 3. **Medium — Screen rerenders cause avoidable list work** ([line 15](C:/Users/<user>/AppData/Local/Temp/asv-react-nati-be075069/work/FeedScreen.tsx:15)). Filtering creates a new array and `renderItem` creates a new function each render; rows have no memoization boundary. **Change:** memoize filtered posts using `[posts, query]`, extract a `React.memo` row, and stabilize `renderItem` with the correct dependencies. Pass the computed rank and a stable `onOpen`; move static styles into `StyleSheet.create`. Currently, `setQuery` is unused, so typing-related rerenders aren’t present. 4. **Conditional medium — Image payloads may exceed their display needs** ([lines 20](C:/Users/<user>/AppData/Local/Temp/asv-react-nati-be075069/work/FeedScreen.tsx:20) and [30](C:/Users/<user>/AppData/Local/Temp/asv-react-nati-be075069/work/FeedScreen.tsx:30)). Display dimensions don’t guarantee appropriately sized downloads. Original-resolution URLs could add substantial network and decoding cost. **Change:** request compressed thumbnails sized for the display’s pixel density; consider the already-installed `expo-image` for explicit caching and recycling support. The actual source dimensions aren’t available here. 5. **Latent — Width animation uses the JS thread and changes layout every frame** ([line 9](C:/Users/<user>/AppData/Local/Temp/asv-react-nati-be075069/work/FeedScreen.tsx:9)). `grow` is unused, so this has no current animation cost. **Change if activated:** use `scaleX` with the native driver when visual scaling meets the design; it won’t change layout space. Also initialize the value lazily: `useState(() => new Animated.Value(100))`. Static review only; no profiling performed and no files changed.