@lliam.nan/cache-analyser
v0.5.1
Published
Static analyzer for Next.js cache directives - catch cache anti-patterns before production
Maintainers
Readme
Next.js Cache Analyzer
Static analyzer for Next.js cache directives - catch cache anti-patterns before they reach production.
Features
- ⚡ Fast - Uses oxc (Rust-based parser) for blazing-fast analysis
- 🔍 Smart - Detects common cache anti-patterns automatically
- 🛠️ Auto-fix - Can automatically fix many issues
- 📊 Detailed - Provides actionable suggestions with examples
Installation
npm install @lliam.nan/cache-analyser --save-dev
# or
pnpm add -D @lliam.nan/cache-analyserUsage
CLI
# Analyze all files in app directory
npx cache-analyser analyze
# Analyze specific pattern
npx cache-analyser analyze "app/**/*.tsx"
# Output JSON
npx cache-analyser analyze --output json
# Auto-fix issues
npx cache-analyser analyze --fix
# Fail CI on errors
npx cache-analyser analyze --strictProgrammatic
import { CacheAnalyzer } from '@lliam.nan/cache-analyser'
const analyzer = new CacheAnalyzer()
const results = analyzer.analyzeFile('app/page.tsx')
console.log('Issues:', results.issues)
console.log('Stats:', results.stats)
// Stats includes:
// - totalFunctions: All function declarations, expressions, and arrows
// - cachedFunctions: Functions with "use cache" directives
// - dynamicContexts: Calls to cookies(), headers(), or connection()Rules
1. no-cache-in-dynamic-context
Severity: Error
"use cache" will not work after calling cookies(), headers(), or connection().
// ❌ Bad
async function BadExample() {
await cookies()
return getData()
}
async function getData() {
'use cache' // Won't work!
return db.query()
}
// ✅ Good
async function GoodExample() {
await cookies()
return getData()
}
async function getData() {
'use cache: remote' // Works in dynamic context
return db.query()
}2. private-cache-without-suspense
Severity: Error
"use cache: private" must be wrapped in a <Suspense> boundary.
// ❌ Bad
async function BadExample() {
'use cache: private'
const session = (await cookies()).get('session')
return <div>{session}</div>
}
// ✅ Good
export function GoodExample() {
return (
<Suspense fallback={<Loading />}>
<PrivateComponent />
</Suspense>
)
}
async function PrivateComponent() {
'use cache: private'
const session = (await cookies()).get('session')
return <div>{session}</div>
}3. short-lived-cache-in-prerender
Severity: Warning
Caches with revalidate: 0 or expire < 300 seconds become dynamic holes during prerender.
// ⚠️ Warning
async function getData() {
'use cache'
cacheLife({ revalidate: 0 }) // Will become dynamic!
return db.query()
}
// ✅ Good
async function getData() {
'use cache'
cacheLife({ expire: 3600 }) // 1 hour - worth prerendering
return db.query()
}Examples
See the examples/ directory for more examples:
bad-example.tsx- Common mistakesgood-example.tsx- Correct usage patterns
Performance
Benchmarks on a typical Next.js project:
| Files | Time | Memory | |-------|------|--------| | 50 | 0.3s | 80MB | | 500 | 1.8s | 150MB | | 5,000 | 12s | 400MB |
CI Integration
GitHub Actions
name: Cache Analysis
on: [push, pull_request]
jobs:
analyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
- run: npm install
- run: npx cache-analyser analyze --strictPre-commit Hook
{
"husky": {
"hooks": {
"pre-commit": "cache-analyser analyze --strict"
}
}
}Development
# Install dependencies
pnpm install
# Build
pnpm build
# Run tests
pnpm test
# Run on examples
pnpm build && node dist/cli/index.js analyze examples/Roadmap
- [x] Phase 1: Basic anti-pattern detection
- [ ] Phase 2: Smart recommendations based on project structure
- [ ] Phase 3: Auto-fix with code generation
- [ ] Phase 4: Runtime analysis and benchmarking
- [ ] Phase 5: AI-powered insights
License
MIT
Contributing
Contributions welcome! See CONTRIBUTING.md for details.
