mirror of
https://github.com/addyosmani/agent-skills.git
synced 2026-10-26 15:05:04 +00:00
Refine performance-optimization skill and checklist based on feedback
- Optimize Hero/LCP images: use aspect-ratio, fetchpriority="high", and decoding="sync". - Optimize below-the-fold images: add decoding="async" alongside loading="lazy". - Update tree-shaking advice: clarify ESM and sideEffects: false requirements. - Add Suspense wrapper to code-splitting examples for completeness. - Ensure image checks include both dimensions and aspect-ratio as non-exclusive.
This commit is contained in:
1 parent
c2c4f56d05
commit
7a9887cedb
2 files changed
+20
-10
No files matched your search
@@ -31,14 +31,14 @@ When TTFB is slow (> 600ms), check each component in DevTools Network waterfall:
|
||||
### Images
|
||||
- [ ] Images use modern formats (WebP, AVIF)
|
||||
- [ ] Images are responsively sized (`srcset` and `sizes`)
|
||||
- [ ] Images have explicit `width` and `height` attributes (prevents CLS)
|
||||
- [ ] Below-the-fold images use `loading="lazy"`
|
||||
- [ ] Hero/LCP images use `fetchpriority="high"` and no lazy loading
|
||||
- [ ] Images have explicit `width` and `height` attributes and/or CSS `aspect-ratio` (prevents CLS)
|
||||
- [ ] Below-the-fold images use `loading="lazy"` and `decoding="async"`
|
||||
- [ ] Hero/LCP images use `fetchpriority="high"`, `decoding="sync"`, and no lazy loading
|
||||
|
||||
### JavaScript
|
||||
- [ ] Bundle size under 200KB gzipped (initial load)
|
||||
- [ ] Code splitting with dynamic `import()` for routes and heavy features
|
||||
- [ ] Tree shaking enabled (no dead code in production bundle)
|
||||
- [ ] Tree shaking enabled (verify dependency ships ESM and marks `sideEffects: false`)
|
||||
- [ ] No blocking JavaScript in `<head>` (use `defer` or `async`)
|
||||
- [ ] Heavy computation offloaded to Web Workers (if applicable)
|
||||
- [ ] `React.memo()` on expensive components that re-render with same props
|
||||
|
||||
@@ -187,20 +187,21 @@ const tasks = await db.tasks.findMany({
|
||||
type="image/webp"
|
||||
/>
|
||||
<img
|
||||
src="/hero-mobile.jpg"
|
||||
width="1200"
|
||||
height="600"
|
||||
src="/hero-desktop.jpg"
|
||||
style="aspect-ratio: 1200 / 600"
|
||||
fetchpriority="high"
|
||||
decoding="sync"
|
||||
alt="Hero image description"
|
||||
/>
|
||||
</picture>
|
||||
|
||||
<!-- GOOD: Below-the-fold image — lazy loaded -->
|
||||
<!-- GOOD: Below-the-fold image — lazy loaded + async decoding -->
|
||||
<img
|
||||
src="/content.webp"
|
||||
width="800"
|
||||
height="400"
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
alt="Content image description"
|
||||
/>
|
||||
```
|
||||
@@ -234,14 +235,23 @@ function TaskStats({ tasks }: Props) {
|
||||
#### Large Bundle Size
|
||||
|
||||
```typescript
|
||||
// Modern bundlers (Vite, webpack 5+) handle named imports with tree-shaking automatically.
|
||||
// Modern bundlers (Vite, webpack 5+) handle named imports with tree-shaking automatically,
|
||||
// provided the dependency ships ESM and is marked `sideEffects: false` in package.json.
|
||||
// Profile before changing import styles — the real gains come from splitting and lazy loading.
|
||||
|
||||
// GOOD: Dynamic import for heavy, rarely-used features
|
||||
const ChartLibrary = lazy(() => import('./ChartLibrary'));
|
||||
|
||||
// GOOD: Route-level code splitting
|
||||
// GOOD: Route-level code splitting wrapped in Suspense
|
||||
const SettingsPage = lazy(() => import('./pages/Settings'));
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Suspense fallback={<Spinner />}>
|
||||
<SettingsPage />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
#### Missing Caching (Backend)
|
||||
|
||||
Reference in new issue
Block a user