ssheleg/sheleg-dev

frontend-performance

Use when building or auditing web pages for speed: Core Web Vitals (LCP, INP, CLS), Lighthouse and PageSpeed scores, render-blocking resources, bundle size, fonts and caching.

소스 보기

사용 방법

  1. 설치 명령을 복사하고 자신의 에이전트 환경에 설치하기 전에 소스 패키지를 확인하세요.
  2. 필요한 도구, 인증 정보, 지원 환경은 원본 문서에서 확인하세요.
  3. 입력과 원하는 산출물을 설명하고 출처와 결과를 대조하세요.
npx skills add https://github.com/ssheleg/sheleg-dev --skill frontend-performance

시작 전 확인

  • 설치에는 모델 구독, API 한도, 파일 접근 권한이 포함되지 않습니다.
  • 별점 수와 설치 수는 활동 지표이며 독립적인 품질·보안 검증이 아닙니다.
원본 Skill 문서

원본 저장소의 제목, 예시, 코드, 표, 링크, 이미지를 유지해 표시합니다.

Frontend Performance

Optimize frontend applications for maximum Lighthouse scores and real-user performance. This skill covers the technical performance layer -- for how it looks, see sheleg-design; for what the interface must do, see super-ux.

Audit Workflow

  1. Measure -- Run PageSpeed Insights or Lighthouse (Chromium) and load the same scenario in WebKit first (see Test browser below). Record scores, failing audits and the engine of each number.
  2. Diagnose -- Map each failing audit to a specific code-level cause (see checklist below).
  3. Prioritize -- Fix by impact: P0 blocks rendering, P1 hurts metrics, P2 is informational.
  4. Implement -- Apply fixes per the reference guides.
  5. Validate -- next build (or framework equivalent) + re-run Lighthouse and the WebKit run. Verify no regressions in either engine.

Test browser — WebKit (Safari) first

Load and profile the page in WebKit first: Safari through safaridriver (WebDriver; sudo safaridriver --enable once) for a real browser, Playwright's webkit (the webkit project, --browser webkit, installed with npx playwright install webkit) for scripted runs and traces, Safari Web Inspector's Timelines for debugging. On macOS open a page with open -a Safari <url>, not the system default browser, which may be another engine. An automation library (browser-use and the like) runs on its WebKit/Safari backend where it has one. WebKit has the narrowest support envelope of the big three — a regression that only iOS Safari users feel is invisible to every Chrome tool below.

Lighthouse, PageSpeed Insights, CrUX, a CDP trace and the chrome-devtools MCP are Chromium by definition — they stay in this workflow as the stated Chromium exception: use them when the task needs Chrome itself, and say which and why. Prefer the Chrome Dev build for a Chrome run you start; give it a temporary profile (never the user's), record what you started, and close every process you started before you finish. A page checked only in Chromium is reported as "checked only in Chromium", never as "tested in a browser"; a Lighthouse score is a Chrome lab number, not a cross-browser verdict.

Core Web Vitals, and the diagnostics beside them

Two INDEPENDENT axes, and conflating them is the common error. Axis one: is it a Core Web Vital — what Google reports and ranks on (LCP, INP, CLS) — or not. Axis two: where can you measure it — in the FIELD (real users, CrUX) or only in the LAB (a synthetic run). These do not line up: a metric can be not-CWV and still field-measurable. FCP is the case that breaks the one-axis story — it is NOT a Core Web Vital, yet it IS field-measurable (CrUX reports FCP; web.dev lists both lab and field tools for it). The earlier claim that "only the three CWV are field-measurable" was wrong.

MetricCore Web Vital?Field-measurable?GoodNeeds WorkPoor
LCPyesyes (CrUX)< 2.5s2.5-4.0s> 4.0s
INPyesyes (CrUX)< 200ms200-500ms> 500ms
CLSyesyes (CrUX)< 0.10.1-0.25> 0.25
FCPnoyes (CrUX)< 1.8s1.8-3.0s> 3.0s
TBTnono (lab only)< 200ms200-600ms> 600ms
SInono (lab only)< 3.4s3.4-5.8s> 5.8s

A field claim carries its provenance, always: p75 (the 75th-percentile value Google classifies on, never a mean), the device/cohort (phone vs desktop, and which population), the period (CrUX is a 28-day trailing window), and the sample size (a thin origin has no field data — that is unknown, not good). A number without these four is a lab number wearing a field label.

TBT is a diagnostic CORRELATE of INP, never a substitute for its evidence. A good lab TBT is a hint that INP may be fine; it does NOT PROVE INP, because INP is measured on real interactions the lab did not perform. So a page with CrUX FCP data and a Lighthouse TBT but no field INP reports FCP = field-supported, INP = unknown — never "INP passed by TBT". Telling a client their Speed Index is a failing Core Web Vital is telling them about a thing Google does not rank; telling them INP passed because TBT did is telling them about a measurement nobody took.

Thresholds and the classification verified against web.dev/articles/vitals, 2026-08-16.

Performance Checklist

Fonts (LCP, FCP)

  • Self-host fonts -- Never load from external CDNs via <link> tags. Use framework font optimization (next/font/google, @fontsource, etc.) to inline CSS and self-host files.
  • Preload critical fonts -- The font used by the LCP element must load early.
  • Limit font families -- Max 3 families. Each family adds ~20-50KB.
  • Subset fonts -- Only load needed character sets (latin, latin-ext).
  • Use `font-display: swap` -- Prevents invisible text during load (FOIT).
  • Remove unused preconnects -- If fonts are self-hosted, preconnect to font CDNs is dead weight.

Before any of these changes: MEASURE, don't prescribe. The items below are optimization HEURISTICS, not blanket rules — each is conditional on evidence, and applied blind it can lose function for a score. Before changing anything, check three things: the performance trace + the scenarios (what a low-end device on a slow network actually waits for), the browser-support contract (who must the page still work for), and the accessibility owner (structure is theirs, not the score's). A change ships only with acceptance covering: low-end/slow-network scenarios, keyboard + heading structure intact, the supported-browser matrix still served, NO new unapproved CSP origin, and several comparable before/after measurements showing the win with no functional loss.

JavaScript (TBT, FCP, LCP)

  • Code split by the MEASURED waterfall -- lazy-load what the trace shows the first paint does not need; "only hero + nav in the initial bundle" is a starting hypothesis, not a rule — a section the scenario needs above the fold stays, whatever the score says.
  • Defer third-party scripts -- GA, analytics, chat widgets load after interactive (afterInteractive or defer).
  • Target the browsers your USERS run -- browserslist follows a stated user-support policy (your analytics, your contract), not a default "last 2". The last 2 line below is an EXAMPLE; shipping it without checking who it drops is how a working browser stops being served for a polyfill saving:
  # example only — replace with your measured support matrix
  last 2 Chrome versions, last 2 Firefox versions, last 2 Safari versions, last 2 Edge versions
  • Tree-shake imports -- prefer named imports where the bundle analyzer shows import * as pulling dead weight; it is a tree-shaking aid, not a ban — a namespace import that costs nothing measured is not a defect.
  • Analyze bundles -- Use @next/bundle-analyzer, source-map-explorer, or vite-plugin-visualizer.

CSS & Animations (CLS)

  • Composite-only animations -- Only animate transform and opacity (GPU-composited). Never animate background-position, width, height, top/left, margin, padding.
  • Use `will-change` sparingly -- Add will-change: transform or will-change: filter only on elements that actually animate.
  • Inline critical CSS -- Framework should handle this (Next.js does automatically).
  • Avoid layout shifts -- Set explicit width/height on images and embeds. Reserve space for dynamic content.

Images (LCP, CLS)

  • Use `<Image>` component -- Framework-optimized components (next/image, Astro <Image>) auto-resize, convert to WebP/AVIF, and add width/height.
  • Priority-load LCP image -- Add priority (Next.js) or fetchpriority="high" to the hero/LCP image.
  • Lazy-load below-fold -- All images below the initial viewport get loading="lazy".
  • Size budget: Hero < 200KB, thumbnails < 50KB, icons as SVG.
  • Responsive `sizes` -- Always provide sizes attribute for responsive images.

Caching (Repeat Visits)

  • Static assets: Cache-Control: public, max-age=31536000, immutable for hashed files (JS, CSS, fonts, images).
  • HTML: Cache-Control: public, max-age=0, must-revalidate (or framework default).
  • Verify patterns -- Test cache header source patterns against actual URLs. Common mistake: glob-style patterns ({.svg,.png}) don't work in all frameworks' path-matching (e.g., Next.js uses path-to-regexp). Use regex parameter syntax instead:
  /:path*.:ext(svg|png|jpg|jpeg|gif|webp|ico|woff|woff2)

Content Security Policy (Best Practices)

  • Approve origins by FUNCTIONAL NECESSITY, not for the score -- an origin enters the CSP because the page genuinely needs it, and each is reviewed; whitelisting everything the page happens to load to silence console errors trades the whole point of a CSP for a Best-Practices number. No new origin ships unapproved.
  • Audit after every third-party change -- Adding analytics, fonts, or CDN scripts requires CSP updates.
  • Tighten after migration -- If you move from external fonts to self-hosted, remove the old CSP entries.
  • Common CSP origins:
  • Google Analytics: https://www.googletagmanager.com, https://www.google-analytics.com
  • Cloudflare: https://static.cloudflareinsights.com
  • Stripe: https://js.stripe.com

Accessibility (Lighthouse A11y Score)

These directly affect the Lighthouse Accessibility score:

  • Contrast ratio -- WCAG AA requires 4.5:1 for normal text, 3:1 for large text. Avoid opacity modifiers on text colors (e.g., text-primary/80 in Tailwind reduces contrast). Use full-opacity color tokens.
  • Heading hierarchy follows STRUCTURE, decided with the accessibility owner -- sequential h1->h2->h3, no skipped levels. Demote a heading to <p> only when it is genuinely NOT a section title; downgrading a real footer-section heading to <p> to quiet a Lighthouse audit removes structure a screen-reader user navigates by. Accessibility is the owner here, not the score.
  • Alt text -- Decorative images next to identical text get alt="". Informative images get descriptive alt. Never duplicate adjacent text.
  • Tap targets -- Minimum 48x48px on mobile. Applies to buttons, links, form inputs.

Framework-Specific Guides

  • Next.js: See references/nextjs.md for next/font, next/image, next/dynamic, next/script, cache headers in next.config, CSP configuration, and bundle analysis.
  • CSS/Animation: See references/css-performance.md for compositing rules, gradient animation alternatives, will-change usage, and critical CSS strategies.
  • Accessibility: See references/accessibility-perf.md for contrast calculations, heading hierarchy rules, and ARIA patterns that affect Lighthouse.

Common PageSpeed Failures & Fixes

AuditCauseFix
"Eliminate render-blocking resources"External font CSS, large CSS filesSelf-host fonts, inline critical CSS
"Reduce unused JavaScript"Full page bundle loaded upfrontCode-split with dynamic imports
"Avoid non-composited animations"Animating background-position, width, etc.Replace with transform/opacity/filter
"Serve static assets with efficient cache policy"Missing or short Cache-Control headersSet max-age=31536000, immutable for hashed assets
"Background/foreground colors do not have sufficient contrast"Opacity modifiers on text colorsUse full-opacity color tokens
"Heading elements not in sequential order"Skipped heading levels (h1 -> h4)Fix hierarchy or use <p> for non-structural headings
"Browser errors logged to console"CSP blocking scripts/stylesWhitelist required origins in CSP
"Image elements do not have [alt] attributes"Missing or redundant alt textAdd descriptive alt, or alt="" for decorative
"Avoid chaining critical requests"Waterfall of blocking resourcesPreload critical resources, self-host
"Legacy JavaScript"Polyfills for modern APIsUpdate browserslist targets

Performance Budget Template

Set these limits for landing pages:

ResourceBudget
Total page weight< 1.5 MB
JavaScript (compressed)< 200 KB
CSS (compressed)< 50 KB
Fonts (total)< 150 KB
Hero image< 200 KB
LCP< 2.5s (mobile)
FCP< 1.8s (mobile)
CLS< 0.1
TBT< 200ms

Related Skills

  • sheleg-design -- how it looks and moves, including the motion budget this page's

numbers constrain

  • super-ux -- what the interface must do, and the flows a slow page loses
  • seo-aeo-audit -- technical SEO and crawlability, which reads the same Core Web

Vitals from the field rather than the lab

Four names that used to sit here — frontend-design, landing-page-design, next-best-practices, responsive-design — resolved to nothing installable, and seo-audit was one character-class away from the real seo-aeo-audit, which is how a typo survives review.

Degradation

  • Not Claude Code (Cursor, Codex, the skills CLI, the API container): the pack's

PreToolUse gate does not run — every rule here still applies, enforced by a person instead of a hook.

  • No browser channel (no safaridriver, no Playwright webkit, no Chrome DevTools MCP): a page is judged from

the diff and the numbers are not measured on this machine. Record the weaker claim; a Lighthouse score nobody ran is not a score.

  • No network: PageSpeed Insights and field data are unavailable. Lab reasoning is

still worth doing — say which half you did.

Triggers

More phrases that route here: "performance audit", "LCP", "CLS", "INP", "render-blocking", "code splitting", "lazy loading", "cache headers", "оптимизация скорости".

같은 저장소의 Skills

더 많은 Skills

모든 Skills
ssheleg
커뮤니티

ad-tracking

Use when wiring or auditing ad pixels and conversion tracking on the web: GA4, Google Ads, Meta Pixel and CAPI, LinkedIn Insight Tag, under Consent Mode v2 and GDPR/DMA. Not for running the campaigns, or the charge itself (stripe-billing). Opt out: no wiring, без обвязки. Triggers - "conversion tracking", "meta pixel", "consent mode", "GA4", "CAPI", "отслеживание конверсий", "пиксель Meta", "ретаргетинг".

설치 수
2
GitHub Stars
4
업데이트
10월 24일
ssheleg
커뮤니티

google-auth

Use when a Node.js or Python server authenticates to Google: OAuth 2.0 flows, server-side ID token verification, service accounts, Application Default Credentials, Workload Identity Federation, API keys. Not for end-user web sign-in (google-signin). Opt out: no wiring, без обвязки. Triggers - "google auth", "google-auth-library", "service account", "ADC", "verifyIdToken", "авторизация Google", "сервисный аккаунт".

설치 수
2
GitHub Stars
4
업데이트
10월 24일
ssheleg
커뮤니티

stripe-billing

Use when connecting a product to Stripe, fixing a payment bug ("баг в оплате") or auditing a live integration: checkout, renewals, refunds, cancellation and the retention coupon, and the webhook that grants an entitlement. Not for crypto (crypto-payments). Opt out: no wiring, без обвязки. Triggers - "add Stripe", "Stripe checkout", "subscription billing", "webhook signature", "cancel subscription", "подключить Stripe", "оплата подпиской", "вебхук Stripe".

설치 수
2
GitHub Stars
4
업데이트
10월 24일