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 额度或访问文件的权限。
  • 仓库星数和安装量反映活跃情况,不等于独立质量或安全测试。
仓库原始内容

按源仓库内容呈现,保留标题、案例、代码、表格、链接以及原文引用的演示图片。

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
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日