| name | nuxt-data-audit |
| description | Audit a Nuxt consumer's data-fetching and performance patterns against the golden path checklist (14 items). Scans .vue/.ts files for useFetch/useAsyncData/$fetch/useQuery/useMutation usage, checks dedupe/cache/key/payload/lazy/routeRules compliance. Outputs a graded report with per-item scores and top-3 actionable improvements. Use when 要審計 Nuxt 專案的 data-fetching 模式、檢查 useFetch/useAsyncData 最佳實踐、或跑效能 checklist。 |
| effort | medium |
| metadata | {"author":"clade","version":"1.0"} |
/nuxt-data-audit — Nuxt data-fetching & performance golden path audit.
Reference rule:rules/core/nuxt-data-perf.md
Cookbook:~/offline/clade/vendor/snippets/nuxt-data-perf/
何時跑
- 定期稽核:跨 consumer fleet 完善度掃描(從 clade home 跑,指定 consumer path)
- 新功能完成後:對 consumer 當前 codebase 的 data-fetching 品質做 baseline check
- code-review 輔助:reviewer 可跑此 skill 取得量化數據輔助 review
- 新 consumer onboard:day-1 baseline 建立
怎麼跑
/nuxt-data-audit # 掃當前 cwd 的 consumer
/nuxt-data-audit ~/offline/TDMS # 掃指定 consumer
/nuxt-data-audit --fleet # 掃全 fleet(從 clade home 用 registry/consumers.json)
Phase 1 — Dependency Detection
判斷 consumer 的 data-fetching stack:
grep -E '@pinia/colada|@pinia/colada-nuxt|@pinia/nuxt' package.json
分為兩類:
- Colada consumer:安裝了 @pinia/colada → 全 14 項 checklist 適用
- Non-Colada consumer:未安裝 → E9/E10 標 N/A,其他 12 項適用
Phase 2 — Automated Scan
對每項 checklist 跑 grep/AST 掃描。以下是每項的掃描方法:
E1 — setup 無裸 $fetch(HR-1)
find . -name '*.vue' -not -path '*/node_modules/*' -not -path '*/.nuxt/*' -not -path '*/test/*' \
| xargs grep -l '\$fetch\|\$csrfFetch'
對每個命中檔案:讀取 <script setup> 區塊,判斷 $fetch 是否在 top-level(fail)還是在 function/handler 內(pass)。Top-level = 不在任何 function/arrow/method 定義內的 await $fetch。
判定:
- pass:所有 $fetch 都在 event handler / function 內
- partial:部分在 top-level 但有 useAsyncData 包裹
- fail:有裸 top-level $fetch
E2 — useFetch 有適當 key(HR-4 useFetch 部分)
grep -rn 'useFetch\|useAsyncData' --include='*.ts' --include='*.vue' \
| grep -v node_modules | grep -v .nuxt | grep -v test/
判定:custom composable(composables/*.ts / queries/*.ts)內的 useFetch 是否手動指定 key。Page/component 內的 useFetch 自動生成 key 通常 OK。
E3 — 高頻 endpoint 有 dedupe:'defer'(HR-2)
grep -rn 'useFetch\|\.refresh(' --include='*.vue' --include='*.ts' \
| grep -v node_modules | grep -v .nuxt
grep -rn "dedupe" --include='*.vue' --include='*.ts' \
| grep -v node_modules | grep -v .nuxt
判定:有 @click / @submit handler 觸發 fetch 且無 dedupe → fail。
E4 — Reference data 有 cache 策略(HR-3)
grep -rn 'staleTime' --include='*.ts' --include='*.vue' | grep -v node_modules | grep -v .nuxt
grep -rn 'getCachedData' --include='*.ts' --include='*.vue' | grep -v node_modules | grep -v .nuxt
判定:staleTime/getCachedData count vs useQuery/useFetch count。比率 > 50% = pass,> 20% = partial,< 20% = fail。
E5 — 大 payload 有 pick/transform(SR-1)
grep -rn 'pick:\|transform:' --include='*.ts' --include='*.vue' \
| grep -v node_modules | grep -v .nuxt | grep -v test/ | grep -v nuxt.config | grep -v vite.config
判定:有 useFetch/useQuery 但 0 pick/transform → fail。有至少一些 → partial。
E6 — 非首屏 component 有 Lazy prefix(SR-2)
grep -rn '<Lazy' --include='*.vue' | grep -v node_modules | grep -v .nuxt
判定:0 = fail。> 0 但 < component 總數 10% = partial。> 10% = pass。
E7 — routeRules 有 performance 設定(SR-3)
grep -A20 'routeRules' nuxt.config.ts | grep -E 'prerender|swr|isr|ssr:\s*false'
判定:有 prerender/swr/isr = pass。只有 csurf/security = partial。完全沒有 = fail。
E8 — NuxtImg 最佳化(SR-5)
grep -rn '<NuxtImg\|<nuxt-img' --include='*.vue' | grep -v node_modules | grep -v .nuxt
grep -rn 'format=.*webp\|loading=.*lazy\|fetchpriority\|:preload=' --include='*.vue' | grep -v node_modules
判定:@nuxt/image 已安裝 + NuxtImg 有 format/loading → pass。裝了但沒 optimize → partial。沒裝 → N/A(不強制)。
E9 — Colada key factory(HR-4,Colada only)
grep -rn 'Keys\s*=\|KEYS\.\|queryKeys\|defineQueryOptions' --include='*.ts' | grep -v node_modules | grep -v .nuxt
grep -rn "key:\s*\['" --include='*.ts' --include='*.vue' | grep -v node_modules | grep -v .nuxt | grep -v test/
判定:factory count > magic string count = pass。反之 = fail。
E10 — useMutation 有 cache invalidation(HR-5,Colada only)
mutation_files=$(grep -rl 'useMutation' --include='*.ts' --include='*.vue' | grep -v node_modules | grep -v .nuxt | grep -v test/)
invalidate_files=$(grep -rl 'invalidateQueries' --include='*.ts' --include='*.vue' | grep -v node_modules | grep -v .nuxt | grep -v test/)
判定:invalidation files >= mutation files = pass。差距 > 30% = fail。
E11 — 無跨 request state 污染
grep -rn 'export const.*= ref(\|export const.*= reactive(' --include='*.ts' \
| grep -v node_modules | grep -v .nuxt | grep -v test/ | grep -v defineStore
判定:0 hits = pass。> 0 = fail(嚴重 — SSR cross-request 污染)。
E12 — Error handling 完整
對 useFetch/useQuery 呼叫:檢查 error ref 是否被 template 消費(v-if="error"、{{ error }})或 watch。
判定:> 50% 有 error 消費 = pass。< 50% = partial。0 = fail。
E13 — 平行 request 用 Promise.all
grep -rn 'Promise.all' --include='*.ts' --include='*.vue' | grep -v node_modules | grep -v .nuxt
判定:advisory,有就加分。
E14 — watch/immediate 合理
grep -rn 'immediate:\s*false\|watch:\s*\[' --include='*.ts' --include='*.vue' \
| grep -v node_modules | grep -v .nuxt | grep -v test/
判定:有使用 = pass。全部預設 = partial。
Phase 3 — Grading
| Grade | 條件 |
|---|
| A | 全部 HR pass + ≥ 80% SR pass |
| B | 全部 HR pass(SR 可 partial) |
| C | ≥ 3 HR pass,其他 partial |
| D | < 3 HR pass |
| F | E1 或 E11 fail(SSR 安全問題) |
HR(Hard Rules)= E1, E3, E4 (cache), E9 (key factory), E10 (invalidation), E11 (state safety)
SR(Should Rules)= E2, E5, E6, E7, E8, E12, E13, E14
Phase 4 — Report Output
Single consumer
## nuxt-data-audit report: <consumer>
Grade: B+
Stack: Pinia Colada 1.3.1 + useFetch (mixed)
| # | Check | Score | Detail |
|---|-------|-------|--------|
| E1 | setup 無裸 $fetch | ✅ pass | 0 violations |
| E2 | useFetch key | ✅ pass | 3/3 custom composables have explicit key |
| E3 | dedupe | ❌ fail | 0/15 high-freq endpoints have dedupe |
| ... | ... | ... | ... |
### Top 3 Improvements
1. **E3 dedupe** — 15 endpoints in 8 files need dedupe:'defer' [files listed]
2. **E9 key factory** — 7 magic string keys should migrate to factory [files listed]
3. **E5 pick/transform** — 5 list endpoints return full rows [files listed]
Fleet mode(--fleet)
## nuxt-data-audit fleet report
| Consumer | Grade | E1 | E2 | E3 | E4 | E5 | E6 | ... |
|----------|-------|----|----|----|----|----|----|-----|
| perno | A- | ✅ | ✅ | ❌ | ✅✅ | ⚠️ | ❌ | ... |
| TDMS | B+ | ⚠️ | ✅ | ❌ | ✅ | ✅ | ✅✅ | ... |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
### Fleet-wide gaps (priority order)
1. E3 dedupe — 0/7 consumers pass
2. E7 routeRules — 1/7 consumers pass
3. E6 Lazy — 2/7 consumers pass
Enforcement Integration
本 skill 的 rule(rules/core/nuxt-data-perf.md)透過 paths frontmatter 在觸及 .vue/.ts 時自動載入。但 rule 被載入 ≠ rule 被遵守。以下是三層 enforcement:
Layer 1 — Rule Self-check Gate(寫 code 時)
Rule 內含:每次寫完新的 useFetch / useQuery / $fetch 呼叫後,MUST 對照 HR-1~HR-5 自查。4.8 會字面遵守此指令。
Layer 2 — Code Review Cross-check(review 時)
/code-review 對 diff 中新增的 data-fetching 呼叫,SHOULD 跑以下 quick check:
- 新的 useFetch 有 dedupe 嗎?
- 新的 useQuery 有 staleTime 嗎?
- 新的 useMutation 有 invalidateQueries 嗎?
- 新的 $fetch 在 setup top-level 嗎?
Layer 3 — Periodic Fleet Audit(定期)
從 clade home 跑 /nuxt-data-audit --fleet,更新 HANDOFF.md 稽核 baseline。