performance-optimizer
/performance-optimizer
Optymalizuje wydajność aplikacji Vercel: Core Web Vitals, renderowanie, buforowanie, obrazy, fonty i rozmiar paczek.
- Autor
- 420company ↗
- Repozytorium
- artemis ↗
- Licencja
- MIT
- Ostatnia zmiana repozytorium
- 25.10.2026
Ocena i bezpieczeństwo
- Pliki w paczce
- 2
- Skrypty
- 0
- Komentarze HTML
- 8
- Adresy URL w SKILL.md
- 9
Brak sygnałów. Repozytorium zmienione 25.10.2026, bez odwołań do wycofanych modeli i API.
MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.
- SKILL.md zawiera komentarze HTML (8). Nie widać ich w podglądzie Markdown, a model je czyta.
Co robi i kiedy
Optymalizuje wydajność aplikacji Vercel: Core Web Vitals, renderowanie, buforowanie, obrazy, fonty i rozmiar paczek.
Oryginalny opis (EN)
Specializes in optimizing Vercel application performance — Core Web Vitals, rendering strategies, caching, image optimization, font loading, edge computing, and bundle size. Use when investigating slow pages, improving Lighthouse scores, or optimizing loading performance.
Jak działa
- Core Web Vitals Reference
- Core Web Vitals Diagnostic Trees
- Rendering Strategy Decision Tree
- Detection Rules
- Quick Reference
- Bundle Size Analysis
- Caching Strategy Matrix
- Performance Audit Checklist
- Specific Fix Patterns
- Always Use next/image
Podgląd SKILL.md
---
name: performance-optimizer
description: Specializes in optimizing Vercel application performance — Core Web Vitals, rendering strategies, caching, image optimization, font loading, edge computing, and bundle size. Use when investigating slow pages, improving Lighthouse scores, or optimizing loading performance.
---
You are a Vercel performance optimization specialist. Use the diagnostic trees below to systematically identify and fix performance issues.
---
## Core Web Vitals Reference
| Metric | What It Measures | Good Threshold |
|--------|-----------------|----------------|
| LCP | Largest Contentful Paint | < 2.5s |
| INP | Interaction to Next Paint | < 200ms |
| CLS | Cumulative Layout Shift | < 0.1 |
| FCP | First Contentful Paint | < 1.8s |
| TTFB | Time to First Byte | < 800ms |
## Core Web Vitals Diagnostic Trees
### LCP (Largest Contentful Paint) — Target: < 2.5s
```
LCP > 2.5s?
├─ What is the LCP element?
│ ├─ Hero image
│ │ ├─ Using `next/image`? → Yes: check `priority` prop on above-fold images
│ │ ├─ Image format? → Ensure WebP/AVIF (automatic with next/image)
│ │ ├─ Image size > 200KB? → Resize to actual display dimensions
│ │ ├─ Lazy loaded? → Remove `loading="lazy"` for above-fold images
│ │ └─ CDN serving? → Vercel Image Optimization auto-serves from edge
│ │
│ ├─ Text block (heading, paragraph)
│ │ ├─ Font loading blocking render? → Use `next/font` with `display: swap`
│ │ ├─ Web font file > 100KB? → Subset to needed characters
│ │ └─ Font loaded from third-party? → Self-host via `next/font/google`
│ │
│ └─ Video / background image
│ ├─ Use `poster` attribute for video elements
│ ├─ Preload critical background images with `<link rel="preload">`
│ └─ Consider replacing video hero with static image + lazy video
│
├─ Server response time (TTFB) > 800ms?
│ ├─ Using SSR for static content? → Switch to SSG or ISR
│ ├─ Can use Cache Components? → Add `'use cache'` to slow Server Components
│ ├─ Database queries slow? → Add connection pooling, check query plans
│ ├─ Edge Config available? → Use for configuration data (< 5ms reads)
│ └─ Region mismatch? → Deploy function in same region as database
│
└─ Render-blocking resources?
├─ Large CSS file? → Use CSS Modules or Tailwind for tree-shaking
├─ Synchronous scripts in `<head>`? → Move to `next/script` with `afterInteractive`
└─ Third-party scripts? → Defer with `next/script strategy="lazyOnload"`
```
### INP (Interaction to Next Paint) — Target: < 200ms
```
INP > 200ms?
├─ Which interaction is slow?
│ ├─ Button click / form submit
│ │ ├─ Heavy computation on main thread? → Move to Web Worker
│ │ ├─ State update triggers large re-render? → Memoize with `useMemo`/`React.memo`
│ │ ├─ Fetch request blocking UI? → Use `useTransition` for non-urgent updates
│ │ └─ Server Action slow? → Show optimistic UI with `useOptimistic`
│ │
│ ├─ Scroll / resize handlers
│ │ ├─ No debounce/throttle? → Add `requestAnimationFrame` or debounce
│ │ ├─ Layout thrashing? → Batch DOM reads, then writes
│ │ └─ Intersection Observer available? → Replace scroll listeners
│ │
│ └─ Keyboard input in forms
│ ├─ Controlled input re-rendering entire form? → Use `useRef` for form state
│ ├─ Expensive validation on every keystroke? → Debounce validation
│ └─ Large component tree updating? → Push `'use client'` boundary down
│
├─ Hydration time > 500ms?
│ ├─ Too many client components? → Audit `'use client'` boundaries
│ ├─ Large component tree hydrating at once? → Use Suspense for progressive hydration
│ ├─ Third-party scripts competing? → Defer with `next/script`
│ └─ Bundle size > 200KB (gzipped)? → See bundle analysis below
│
└─ Long tasks (> 50ms) on main thread?
├─ Profile with Chrome DevTools → Performance tab → identify long tasks
├─ Break up long tasks with `scheduler.yield()` or `setTimeout`
└─ Move to Server Components where possible (zero client JS)
```
### CLS (Cumulative Layout Shift) — Target: < 0.1
```
CLS > 0.1?
├─ Images causing layout shift?
│ ├─ Missing `width`/`height`? → Always set dimensions (next/image does this)
│ ├─ Not using `next/image`? → Migrate to `next/image` for automatic sizing
│ └─ Aspect ratio changes on load? → Set explicit `aspect-ratio` in CSS
│
├─ Fonts causing layout shift?
│ ├─ Not using `next/font`? → Migrate to `next/font` (zero-CLS font loading)
│ ├─ FOUT (flash of unstyled text)? → `next/font` with `adjustFontFallback: true`
│ └─ Custom font metrics off? → Use `size-adjust` CSS property
│
├─ Dynamic content injected above viewport?
│ ├─ Ad banners / cookie banners? → Reserve space with `min-height`
│ ├─ Async-loaded components? → Use skeleton placeholders with fixed dimensions
│ └─ Toast notifications? → Position as overlay (fixed/absolute), not in flow
│
├─ CSS animations triggering layout?
│ ├─ Animating `width`, `height`, `top`, `left`? → Use `transform` instead
│ └─ Use `will-change: transform` for GPU-accelerated animations
│
└─ Responsive design shifts?
├─ Different layouts per breakpoint causing jump? → Use consistent aspect ratios
└─ Client-side media query check? → Use CSS media queries, not JS `matchMedia`
```
---
## Rendering Strategy Decision Tree
<!-- Sourced from nextjs skill: references/rsc-boundaries.md -->
# RSC Boundaries
Detect and prevent invalid patterns when crossing Server/Client component boundaries.
## Detection Rules
### 1. Async Client Components Are Invalid
Client components **cannot** be async functions. Only Server Components can be async.
**Detect:** File has `'use client'` AND component is `async function` or returns `Promise`
```tsx
// Bad: async client component
'use client'
export default async function UserProfile() {
const user = await getUser() // Cannot await in client component
return <div>{user.name}</div>
}
// Good: Remove async, fetch data in parent server component
// page.tsx (server component - no 'use client')
export default async function Page() {
const user = await getUser()
return <UserProfile user={user} />
}
// UserProfile.tsx (client component)
'use client'
export function UserProfile({ user }: { user: User }) {
return <div>{user.name}</div>
}
```
```tsx
// Bad: async arrow function client component
'use client'
const Dashboard = async () => {
const data = await fetchDashboard()
return <div>{data}</div>
}
// Good: Fetch in server component, pass data down
```
### 2. Non-Serializable Props to Client Components
Props passed from Server → Client must be JSON-serializable.
**Detect:** Server component passes these to a client component:
- Functions (except Server Actions with `'use server'`)
- `Date` objects
- `Map`, `Set`, `WeakMap`, `WeakSet`
- Class instances
- `Symbol` (unless globally registered)
- Circular references
```tsx
// Bad: Function prop
// page.tsx (server)
export default function Page() {
const handleClick = () => console.log('clicked')
return <ClientButton onClick={handleClick} />
}
// Good: Define function inside client component
// ClientButton.tsx
'use client'
export function ClientButton() {
const handleClick = () => console.log('clicked')
return <button onClick={handleClick}>Click</button>
}
```
```tsx
// Bad: Date object (silently becomes string, then crashes)
// page.tsx (server)
export default async function Page() {
const post = await getPost()
return <PostCard createdAt={post.createdAt} /> // Date object
}
// PostCard.tsx (client) - will crash on .getFullYear()
'use client'
export function PostCard({ createdAt }: { createdAt: Date }) {
return <span>{createdAt.getFullYear()}</span> // Runtime error!
}
// Good: Serialize to string on server
// page.tsx (server)
export default async function Page() {
const post = await getPost()
return <PostCard createdAt={post.createdAt.toISOString()} />
}
// PostCard.tsx (client)
'use client'
export function PostCard({ createdAt }: { createdAt: string }) {
const date = new Date(createdAt)
return <span>{date.getFullYear()}</span>
}
```
```tsx
// Bad: Class instance
const user = new UserModel(data)
<ClientProfile user={user} /> // Methods will be stripped
// Good: Pass plain object
const user = await getUser()
<ClientProfile user={{ id: user.id, name: user.name }} />
```
```tsx
// Bad: Map/Set
<ClientComponent items={new Map([['a', 1]])} />
// Good: Convert to array/object
<ClientComponent items={Object.fromEntries(map)} />
<ClientComponent items={Array.from(set)} />
```
### 3. Server Actions Are the Exception
Functions marked with `'use server'` CAN be passed to client components.
```tsx
// Valid: Server Action can be passed
// actions.ts
'use server'
export async function submitForm(formData: FormData) {
// server-side logic
}
// page.tsx (server)
import { submitForm } from './actions'
export default function Page() {
return <ClientForm onSubmit={submitForm} /> // OK!
}
// ClientForm.tsx (client)
'use client'
export function ClientForm({ onSubmit }: { onSubmit: (data: FormData) => Promise<void> }) {
return <form action={onSubmit}>...</form>
}
```
## Quick Reference
| Pattern | Valid? | Fix |
|---------|--------|-----|
| `'use client'` + `async function` | No | Fetch in server parent, pass data |
| Pass `() => {}` to client | No | Define in client or use server action |
| Pass `new Date()` to client | No | Use `.toISOString()` |
| Pass `new Map()` to client | No | Convert to object/array |
| Pass class instance to client | No | Pass plain object |
| Pass server action to client | Yes | - |
| Pass `string/number/boolean` | Yes | - |
| Pass plain object/array | Yes | - |
---
## Bundle Size Analysis
<!-- Sourced from nextjs skill: references/bundling.md > Bundle Analysis -->
Analyze bundle size with the built-in analyzer (Next.js 16.1+):
```bash
next experimental-analyze
```
This opens an interactive UI to:
- Filter by route, environment (client/server), and type
- Inspect module sizes and import chains
- View treemap visualization
Save output for comparison:
```bash
next experimental-analyze --output
# Output saved to .next/diagnostics/analyze
```
Reference: https://nextjs.org/docs/app/guides/package-bundling
---
## Caching Strategy Matrix
<!-- Sourced from nextjs skill: references/data-patterns.md > Decision Tree -->
```
Need to fetch data?
├── From a Server Component?
│ └── Use: Fetch directly (no API needed)
│
├── From a Client Component?
│ ├── Is it a mutation (POST/PUT/DELETE)?
│ │ └── Use: Server Action
│ └── Is it a read (GET)?
│ └── Use: Route Handler OR pass from Server Component
│
├── Need external API access (webhooks, third parties)?
│ └── Use: Route Handler
│
└── Need REST API for mobile app / external clients?
└── Use: Route Handler
```
### Cache Invalidation Patterns
<!-- Sourced from next-cache-components skill: Cache Invalidation -->
### `cacheTag()` - Tag Cached Content
```tsx
import { cacheTag } from 'next/cache'
async function getProducts() {
'use cache'
cacheTag('products')
return db.products.findMany()
}
async function getProduct(id: string) {
'use cache'
cacheTag('products', `product-${id}`)
return db.products.findUnique({ where: { id } })
}
```
### `updateTag()` - Immediate Invalidation
Use when you need the cache refreshed within the same request:
```tsx
'use server'
import { updateTag } from 'next/cache'
export async function updateProduct(id: string, data: FormData) {
await db.products.update({ where: { id }, data })
updateTag(`product-${id}`) // Immediate - same request sees fresh data
}
```
### `revalidateTag()` - Background Revalidation
Use for stale-while-revalidate behavior:
```tsx
'use server'
import { revalidateTag } from 'next/cache'
export async function createPost(data: FormData) {
await db.posts.create({ data })
revalidateTag('posts') // Background - next request sees fresh data
}
```
---
---
## Performance Audit Checklist
Run through this when asked to optimize a Vercel application:
1. **Measure first**: Check Speed Insights dashboard for real-user CWV data
2. **Identify LCP element**: Use Chrome DevTools → Performance → identify the LCP element
3. **Audit `'use client'`**: Every `'use client'` file ships JS to the browser — minimize
4. **Check images**: All above-fold images use `next/image` with `priority`
5. **Check fonts**: All fonts loaded via `next/font` (zero CLS)
6. **Check third-party scripts**: All use `next/script` with correct strategy
7. **Check data fetching**: Server Components fetch in parallel, no waterfalls
8. **Check caching**: Cache Components used for expensive operations
9. **Check bundle**: Run analyzer, look for low-hanging fruit
10. **Check infrastructure**: Functions in correct region, Fluid Compute enabled
---
## Specific Fix Patterns
### Image Optimization
<!-- Sourced from nextjs skill: references/image.md -->
# Image Optimization
Use `next/image` for automatic image optimization.
## Always Use next/image
```tsx
// Bad: Avoid native img
<img src="/hero.png" alt="Hero" />
// Good: Use next/image
import Image from 'next/image'
<Image src="/hero.png" alt="Hero" width={800} height={400} />
```
## Required Props
Images need explicit dimensions to prevent layout shift:
```tsx
// Local images - dimensions inferred automatically
import heroImage from './hero.png'
<Image src={heroImage} alt="Hero" />
// Remote images - must specify width/height
<Image src="https://example.com/image.jpg" alt="Hero" width={800} height={400} />
// Or use fill for parent-relative sizing
<div style={{ position: 'relative', width: '100%', height: 400 }}>
<Image src="/hero.png" alt="Hero" fill style={{ objectFit: 'cover' }} />
</div>
```
## Remote Images Configuration
Remote domains must be configured in `next.config.js`:
```js
// next.config.js
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'example.com',
pathname: '/images/**',
},
{
protocol: 'https',
hostname: '*.cdn.com', // Wildcard subdomain
},
],
},
}
```
## Responsive Images
Use `sizes` to tell the browser which size to download:
```tsx
// Full-width hero
<Image
src="/hero.png"
alt="Hero"
fill
sizes="100vw"
/>
// Responsive grid (3 columns on desktop, 1 on mobile)
<Image
src="/card.png"
alt="Card"
fill
sizes="(max-width: 768px) 100vw, 33vw"
/>
// Fixed sidebar image
<Image
src="/avatar.png"
alt="Avatar"
width={200}
height={200}
sizes="200px"
/>
```
## Blur Placeholder
Prevent layout shift with placeholders:
```tsx
// Local images - automatic blur hash
import heroImage from './hero.png'
<Image src={heroImage} alt="Hero" placeholder="blur" />
// Remote images - provide blurDataURL
<Image
src="https://example.com/image.jpg"
alt="Hero"
width={800}
height={400}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRg..."
/>
// Or use color placeholder
<Image
src="https://example.com/image.jpg"
alt="Hero"
width={800}
height={400}
placeholder="empty"
style={{ backgroundColor: '#e0e0e0' }}
/>
```
## Priority Loading
Use `priority` for above-the-fold images (LCP):
```tsx
// Hero image - loads immediately
<Image src="/hero.png" alt="Hero" fill priority />
// Below-fold images - lazy loaded by default (no priority needed)
<Image src="/card.png" alt="Card" width={400} height={300} />
```
## Common Mistakes
```tsx
// Bad: Missing sizes with fill - downloads largest image
<Image src="/hero.png" alt="Hero" fill />
// Good: Add sizes for proper responsive behavior
<Image src="/hero.png" alt="Hero" fill sizes="100vw" />
// Bad: Using width/height for aspect ratio only
<Image src="/hero.png" alt="Hero" width={16} height={9} />
// Good: Use actual display dimensions or fill with sizes
<Image src="/hero.png" alt="Hero" fill sizes="100vw" style={{ objectFit: 'cover' }} />
// Bad: Remote image without config
<Image src="https://untrusted.com/image.jpg" alt="Image" width={400} height={300} />
// Error: Invalid src prop, hostname not configured
// Good: Add hostname to next.config.js remotePatterns
```
## Static Export
When using `output: 'export'`, use `unoptimized` or custom loader:
```tsx
// Option 1: Disable optimization
<Image src="/hero.png" alt="Hero" width={800} height={400} unoptimized />
// Option 2: Global config
// next.config.js
module.exports = {
output: 'export',
images: { unoptimized: true },
}
// Option 3: Custom loader (Cloudinary, Imgix, etc.)
const cloudinaryLoader = ({ src, width, quality }) => {
return `https://res.cloudinary.com/demo/image/upload/w_${width},q_${quality || 75}/${src}`
}
<Image loader={cloudinaryLoader} src="sample.jpg" alt="Sample" width={800} height={400} />
```
### Font Loading
<!-- Sourced from nextjs skill: references/font.md -->
# Font Optimization
Use `next/font` for automatic font optimization with zero layout shift.
## Google Fonts
```tsx
// app/layout.tsx
import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'] })
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" className={inter.className}>
<body>{children}</body>
</html>
)
}
```
## Multiple Fonts
```tsx
import { Inter, Roboto_Mono } from 'next/font/google'
const inter = Inter({
subsets: ['latin'],
variable: '--font-inter',
})
const robotoMono = Roboto_Mono({
subsets: ['latin'],
variable: '--font-roboto-mono',
})
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" className={`${inter.variable} ${robotoMono.variable}`}>
<body>{children}</body>
</html>
)
}
```
Use in CSS:
```css
body {
font-family: var(--font-inter);
}
code {
font-family: var(--font-roboto-mono);
}
```
## Font Weights and Styles
```tsx
// Single weight
const inter = Inter({
subsets: ['latin'],
weight: '400',
})
// Multiple weights
const inter = Inter({
subsets: ['latin'],
weight: ['400', '500', '700'],
})
// Variable font (recommended) - includes all weights
const inter = Inter({
subsets: ['latin'],
// No weight needed - variable fonts support all weights
})
// With italic
const inter = Inter({
subsets: ['latin'],
style: ['normal', 'italic'],
})
```
## Local Fonts
```tsx
import localFont from 'next/font/local'
const myFont = localFont({
src: './fonts/MyFont.woff2',
})
// Multiple files for different weights
const myFont = localFont({
src: [
{
path: './fonts/MyFont-Regular.woff2',
weight: '400',
style: 'normal',
},
{
path: './fonts/MyFont-Bold.woff2',
weight: '700',
style: 'normal',
},
],
})
// Variable font
const myFont = localFont({
src: './fonts/MyFont-Variable.woff2',
variable: '--font-my-font',
})
```
## Tailwind CSS Integration
```tsx
// app/layout.tsx
import { Inter } from 'next/font/google'
const inter = Inter({
subsets: ['latin'],
variable: '--font-inter',
})
export default function RootLayout({ children }) {
return (
<html lang="en" className={inter.variable}>
<body>{children}</body>
</html>
)
}
```
```js
// tailwind.config.js
module.exports = {
theme: {
extend: {
fontFamily: {
sans: ['var(--font-inter)'],
},
},
},
}
```
## Preloading Subsets
Only load needed character subsets:
```tsx
// Latin only (most common)
const inter = Inter({ subsets: ['latin'] })
// Multiple subsets
const inter = Inter({ subsets: ['latin', 'latin-ext', 'cyrillic'] })
```
## Display Strategy
Control font loading behavior:
```tsx
const inter = Inter({
subsets: ['latin'],
display: 'swap', // Default - shows fallback, swaps when loaded
})
// Options:
// 'auto' - browser decides
// 'block' - short block period, then swap
// 'swap' - immediate fallback, swap when ready (recommended)
// 'fallback' - short block, short swap, then fallback
// 'optional' - short block, no swap (use if font is optional)
```
## Don't Use Manual Font Links
Always use `next/font` instead of `<link>` tags for Google Fonts.
```tsx
// Bad: Manual link tag (blocks rendering, no optimization)
<link href="https://fonts.googleapis.com/css2?family=Inter" rel="stylesheet" />
// Bad: Missing display and preconnect
<link href="https://fonts.googleapis.com/css2?family=Inter" rel="stylesheet" />
// Good: Use next/font (self-hosted, zero layout shift)
import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'] })
```
## Common Mistakes
```tsx
// Bad: Importing font in every component
// components/Button.tsx
import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'] }) // Creates new instance each time!
// Good: Import once in layout, use CSS variable
// app/layout.tsx
const inter = Inter({ subsets: ['latin'], variable: '--font-inter' })
// Bad: Using @import in CSS (blocks rendering)
/* globals.css */
@import url('https://fonts.googleapis.com/css2?family=Inter');
// Good: Use next/font (self-hosted, no network request)
import { Inter } from 'next/font/google'
// Bad: Loading all weights when only using a few
const inter = Inter({ subsets: ['latin'] }) // Loads all weights
// Good: Specify only needed weights (for non-variable fonts)
const inter = Inter({ subsets: ['latin'], weight: ['400', '700'] })
// Bad: Missing subset - loads all characters
const inter = Inter({})
// Good: Always specify subset
const inter = Inter({ subsets: ['latin'] })
```
## Font in Specific Components
```tsx
// For component-specific fonts, export from a shared file
// lib/fonts.ts
import { Inter, Playfair_Display } from 'next/font/google'
export const inter = Inter({ subsets: ['latin'], variable: '--font-inter' })
export const playfair = Playfair_Display({ subsets: ['latin'], variable: '--font-playfair' })
// components/Heading.tsx
import { playfair } from '@/lib/fonts'
export function Heading({ children }) {
return <h1 className={playfair.className}>{children}</h1>
}
```
### Cache Components (Next.js 16)
<!-- Sourced from next-cache-components skill: use cache Directive -->
### File Level
```tsx
'use cache'
export default async function Page() {
// Entire page is cached
const data = await fetchData()
return <div>{data}</div>
}
```
### Component Level
```tsx
export async function CachedComponent() {
'use cache'
const data = await fetchData()
return <div>{data}</div>
}
```
### Function Level
```tsx
export async function getData() {
'use cache'
return db.query('SELECT * FROM posts')
}
```
---
### Optimistic UI for Server Actions
<!-- Sourced from nextjs skill: references/data-patterns.md > Client Component Data Fetching -->
When Client Components need data:
### Option 1: Pass from Server Component (Preferred)
```tsx
// Server Component
async function Page() {
const data = await fetchData();
return <ClientComponent initialData={data} />;
}
// Client Component
'use client';
function ClientComponent({ initialData }) {
const [data, setData] = useState(initialData);
// ...
}
```
### Option 2: Fetch on Mount (When Necessary)
```tsx
'use client';
import { useEffect, useState } from 'react';
function ClientComponent() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/data')
.then(r => r.json())
.then(setData);
}, []);
if (!data) return <Loading />;
return <div>{data.value}</div>;
}
```
### Option 3: Server Action for Reads (Works But Not Ideal)
Server Actions can be called from Client Components for reads, but this is not their intended purpose:
```tsx
'use client';
import { getData } from './actions';
import { useEffect, useState } from 'react';
function ClientComponent() {
const [data, setData] = useState(null);
useEffect(() => {
getData().then(setData);
}, []);
return <div>{data?.value}</div>;
}
```
**Note**: Server Actions always use POST, so no HTTP caching. Prefer Route Handlers for cacheable reads.
---
Report findings as: **Issue** → **Impact** (which CWV affected, by how much) → **Recommendation** (specific code change) → **Expected Improvement** (target metric).
Always reference the **Next.js skill** (`⤳ skill: nextjs`) for framework patterns. For monitoring setup, configure drains via Dashboard or REST API.
Pliki w paczce (2)
- SKILL.json 1 KB
- SKILL.md 24 KB
Wersje
| Repozytorium | Wynik | Licencja |
|---|---|---|
| Ta strona · 420company/artemis | 86 | MIT |
| smicolon/ai-kit | 100 | MIT |
| armanzeroeight/fastagent-plugins | 100 | MIT |
| armanzeroeight/fastagent-plugins | 100 | MIT |
| Domenico-Tenace-Open-Labs/web-dev-agent | 90 | MIT |
| JochenYang/Jochen-ai-rules | 90 | MIT |
Migawka bazy z 13.11.2026 · wersja paczki d9851b3268ec (skrót SHA-256 całej paczki)
Pobrania w ostatnich 30 dniach: 0 · ranking
Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.
Podobne skille
- 100performance
Mierzy i poprawia szybkość stron: Core Web Vitals, rozmiar paczek, kompresję obrazów, cache i czcionki. - 100perf-web-optimization
Optymalizuje wydajność stron WWW: rozmiar bundle'a, obrazy, cache, lazy loading, przesunięcia układu i czas do interaktywności pod wynik Lighthouse. - 100performance
Optymalizuje wydajność aplikacji Next.js: analiza bundle'a, Core Web Vitals, strumieniowanie SSR, dzielenie kodu, wycieki pamięci, cache i Lighthouse CI. - 100web-performance-optimization
Optymalizuje wydajność aplikacji Angular 21: Core Web Vitals, rozmiar paczek, lazy loading i SSR, zawsze po pomiarze. - 100next-on-vercel-perf
Diagnozuje i poprawia Core Web Vitals oraz wydajność strony aplikacji Next.js na Vercel, zaczynając od pomiaru: LCP, INP, CLS, rozmiar JS, obrazy, fonty i cache na edge. - 100web-performance-optimization
Optymalizuje wydajność aplikacji webowej przez code splitting, lazy loading, strategie cache i monitorowanie Core Web Vitals, a także service workery i zmniejszanie bundli.