performance-engineering
Web Vitals, Lighthouse CI, bundle optimization, CDN, caching, and load testing
What this skill does
# Performance Engineering
## Overview
This skill covers measuring, optimizing, and maintaining web application performance across the full stack. It addresses Core Web Vitals (LCP, INP, CLS), bundle analysis and code splitting, image optimization, browser and server-side caching, CDN configuration, database query performance, and load testing with k6 and Artillery.
Use this skill when Core Web Vitals scores are below targets, bundle sizes are growing, page load times are degrading, or when preparing for traffic spikes. Performance work should be measurement-driven: profile first, optimize second, measure the impact third.
---
## Core Principles
1. **Measure before optimizing** - Profile with real data (RUM, Lighthouse, DevTools) before writing any optimization code. Intuition about performance bottlenecks is usually wrong.
2. **Budget everything** - Set performance budgets for bundle size (< 200kb JS), LCP (< 2.5s), INP (< 200ms), CLS (< 0.1). Enforce in CI so regressions are caught before merge.
3. **Optimize the critical path** - Focus on what blocks the user from seeing and interacting with content. Everything else can load later.
4. **Cache aggressively, invalidate precisely** - Use immutable hashes for static assets, short TTLs for dynamic content, and stale-while-revalidate for the best of both worlds.
5. **Test at realistic scale** - Load test with production-like data volumes and traffic patterns, not toy datasets with 10 concurrent users.
---
## Key Patterns
### Pattern 1: Core Web Vitals Monitoring
**When to use:** Every production web application. These metrics directly affect SEO ranking and user experience.
**Implementation:**
```typescript
// Real User Monitoring (RUM) with web-vitals library
import { onLCP, onINP, onCLS, onFCP, onTTFB } from "web-vitals";
interface VitalMetric {
name: string;
value: number;
rating: "good" | "needs-improvement" | "poor";
navigationType: string;
}
function sendToAnalytics(metric: VitalMetric) {
// Send to your analytics endpoint
navigator.sendBeacon("/api/vitals", JSON.stringify({
...metric,
url: window.location.href,
userAgent: navigator.userAgent,
connectionType: (navigator as unknown as { connection?: { effectiveType: string } })
.connection?.effectiveType ?? "unknown",
timestamp: Date.now(),
}));
}
// Capture all Core Web Vitals
onLCP((metric) => sendToAnalytics({
name: "LCP",
value: metric.value,
rating: metric.rating,
navigationType: metric.navigationType,
}));
onINP((metric) => sendToAnalytics({
name: "INP",
value: metric.value,
rating: metric.rating,
navigationType: metric.navigationType,
}));
onCLS((metric) => sendToAnalytics({
name: "CLS",
value: metric.value,
rating: metric.rating,
navigationType: metric.navigationType,
}));
onFCP((metric) => sendToAnalytics({
name: "FCP",
value: metric.value,
rating: metric.rating,
navigationType: metric.navigationType,
}));
onTTFB((metric) => sendToAnalytics({
name: "TTFB",
value: metric.value,
rating: metric.rating,
navigationType: metric.navigationType,
}));
```
```typescript
// Lighthouse CI configuration
// lighthouserc.js
module.exports = {
ci: {
collect: {
url: [
"http://localhost:3000/",
"http://localhost:3000/dashboard",
"http://localhost:3000/pricing",
],
numberOfRuns: 3,
},
assert: {
assertions: {
"categories:performance": ["error", { minScore: 0.9 }],
"categories:accessibility": ["error", { minScore: 0.95 }],
"first-contentful-paint": ["warn", { maxNumericValue: 1800 }],
"largest-contentful-paint": ["error", { maxNumericValue: 2500 }],
"interactive": ["error", { maxNumericValue: 3800 }],
"cumulative-layout-shift": ["error", { maxNumericValue: 0.1 }],
"total-byte-weight": ["warn", { maxNumericValue: 500000 }],
},
},
upload: {
target: "temporary-public-storage",
},
},
};
```
**Why:** Lab metrics (Lighthouse) catch regressions before deployment. Field metrics (RUM) show real user experience across diverse devices and networks. You need both: lab for prevention, field for truth.
---
### Pattern 2: Bundle Optimization and Code Splitting
**When to use:** When JavaScript bundle size exceeds 200kb gzipped, or when initial load includes code for routes the user hasn't visited.
**Implementation:**
```typescript
// Next.js - Dynamic imports for route-based code splitting
import dynamic from "next/dynamic";
// Heavy component loaded only when needed
const RichTextEditor = dynamic(() => import("@/components/RichTextEditor"), {
loading: () => <div className="editor-skeleton" aria-busy="true">Loading editor...</div>,
ssr: false, // Client-only component
});
const ChartDashboard = dynamic(() => import("@/components/ChartDashboard"), {
loading: () => <ChartSkeleton />,
});
// Conditional feature loading
function ProjectPage({ project }: { project: Project }) {
const [showEditor, setShowEditor] = useState(false);
return (
<div>
<h1>{project.name}</h1>
<button onClick={() => setShowEditor(true)}>Edit Description</button>
{showEditor && <RichTextEditor content={project.description} />}
</div>
);
}
```
```javascript
// webpack-bundle-analyzer integration
// next.config.js
const withBundleAnalyzer = require("@next/bundle-analyzer")({
enabled: process.env.ANALYZE === "true",
});
module.exports = withBundleAnalyzer({
// Analyze specific packages for tree-shaking
experimental: {
optimizePackageImports: ["lodash-es", "date-fns", "@mui/material", "lucide-react"],
},
});
```
```bash
# Analyze bundle
ANALYZE=true npm run build
# Check specific import costs
npx import-cost # VS Code extension alternative
npx source-map-explorer .next/static/chunks/*.js
```
**Why:** Every kilobyte of JavaScript costs parse time, compile time, and execution time on the user's device. Code splitting ensures users only download the code needed for their current view. Lazy loading heavy components (editors, charts, maps) keeps initial bundle lean.
---
### Pattern 3: Image Optimization
**When to use:** Any page with images (which is most pages). Images are typically the largest assets on a page.
**Implementation:**
```tsx
// Next.js Image component with proper optimization
import Image from "next/image";
// Responsive hero image
function HeroSection() {
return (
<section>
<Image
src="/hero.jpg"
alt="Team collaborating on a project"
width={1920}
height={1080}
priority // LCP element - skip lazy loading
sizes="100vw"
quality={85}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/4AAQ..." // Low-quality placeholder
/>
</section>
);
}
// Responsive card image
function ProductCard({ product }: { product: Product }) {
return (
<article>
<Image
src={product.imageUrl}
alt={product.name}
width={400}
height={300}
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
loading="lazy" // Below the fold
/>
<h3>{product.name}</h3>
</article>
);
}
```
```typescript
// Sharp-based image processing pipeline for user uploads
import sharp from "sharp";
interface ImageVariant {
width: number;
suffix: string;
quality: number;
}
const variants: ImageVariant[] = [
{ width: 320, suffix: "sm", quality: 80 },
{ width: 640, suffix: "md", quality: 80 },
{ width: 1280, suffix: "lg", quality: 85 },
{ width: 1920, suffix: "xl", quality: 85 },
];
async function processUploadedImage(
buffer: Buffer,
filename: string
): Promise<string[]> {
const urls: string[] = [];
for (const variant of variants) {
// Generate WebP (best compression)
const webp = await sharp(buffer)
.resize(variant.width, null, { withoutEnlargement: true })
.webp({ quality: variant.quality })
.toBuffer();
Related in Cloud & DevOps
appbuilder-action-scaffolder
IncludedCreate, implement, deploy, and debug Adobe Runtime actions with consistent layout, validation, and error handling. Use this skill whenever the user needs to add actions to an App Builder project, understand action structure (params, response format, web/raw actions), configure actions in the manifest, use App Builder SDKs (State, Files, Events, database), deploy and invoke actions via CLI, debug action issues, or implement patterns such as webhook receivers, custom event providers, journaling consumers, large payload redirects, action sequence pipelines, and Asset Compute workers. Also trigger when users mention serverless functions in Adobe context, action logging, IMS authentication for actions, or cron-style scheduled actions.
orchestrating-datacloud
IncludedSalesforce Data Cloud product orchestrator for connect→prepare→harmonize→segment→act workflows. Use this skill when the user needs a multi-step Data Cloud pipeline, cross-phase troubleshooting, or data space and data kit management. TRIGGER when: user needs a multi-step Data Cloud pipeline, asks to set up or troubleshoot Data Cloud across phases, manages data spaces or data kits, or wants a cross-phase sf data360 workflow. DO NOT TRIGGER when: work is isolated to a single phase (use the matching phase-specific skill), the task is STDM/session tracing/parquet telemetry (use observing-agentforce), standard CRM SOQL (use querying-soql), or Apex implementation (use generating-apex).
github-project-automation
IncludedAutomate GitHub repository setup with CI/CD workflows, issue templates, Dependabot, and CodeQL security scanning. Includes 12 production-tested workflows and prevents 18 errors: YAML syntax, action pinning, and configuration. Use when: setting up GitHub Actions CI/CD, creating issue/PR templates, enabling Dependabot or CodeQL scanning, deploying to Cloudflare Workers, implementing matrix testing, or troubleshooting YAML indentation, action version pinning, secrets syntax, runner versions, or CodeQL configuration. Keywords: github actions, github workflow, ci/cd, issue templates, pull request templates, dependabot, codeql, security scanning, yaml syntax, github automation, repository setup, workflow templates, github actions matrix, secrets management, branch protection, codeowners, github projects, continuous integration, continuous deployment, workflow syntax error, action version pinning, runner version, github context, yaml indentation error
sf-datacloud
IncludedSalesforce Data Cloud product orchestrator for connect→prepare→harmonize→segment→act workflows. TRIGGER when: user needs a multi-step Data Cloud pipeline, asks to set up or troubleshoot Data Cloud across phases, manages data spaces or data kits, or wants a cross-phase `sf data360` workflow. DO NOT TRIGGER when: work is isolated to a single phase (use the matching sf-datacloud-* skill), the task is STDM/session tracing/parquet telemetry (use sf-ai-agentforce-observability), standard CRM SOQL (use sf-soql), or Apex implementation (use sf-apex).
fabric-cli
IncludedUse this skill for Fabric.so CLI workflows with the `fabric` terminal command: diagnose/install/login, search or browse a Fabric library, save notes/links/files, create folders, ask the Fabric AI assistant, manage tasks/workspaces, generate shell completion, check subscription usage, produce JSON output, and use Fabric as persistent agent memory. Do not use for Microsoft Fabric/Azure/Power BI `fab`, Daniel Miessler's Fabric framework, Python Fabric SSH, Fabric.js, or textile/fashion fabric.
lark
IncludedLark/Feishu CLI skills: lark-cli operations for docs, markdown, sheets, base, calendar, im, mail, task, okr, drive, wiki, slides, whiteboard, apps, approval, attendance, contact, vc, minutes, event. Use when the user needs to operate Lark/Feishu resources via lark-cli, send messages, manage documents, spreadsheets, calendars, tasks, OKRs, deploy web pages, or any Feishu/Lark workspace operations.