Skip to content
Beta Multi-model support (OpenAI, Gemini, and more) launching soon.

perf-render-blocking-analysis

Installable Ships in performance-auditor — or copy the raw skill below.
Open Claude.ai

Paste into Claude Code, Claude.ai, the desktop app, or the browser extension — ⌘/Ctrl+V.

ExperimentalNo security review

Render-Blocking Resource Analysis

Identify and eliminate every resource in the critical path that delays FCP and LCP. This skill goes deeper than the Lighthouse render-blocking-resources audit — it traces the exact blocking chain, quantifies each resource's contribution, and prescribes targeted fixes.

Usage

/perf-render-blocking-analysis <URL or project-root-path> [--platform sitecore|optimizely|umbraco|headless]

Examples:

  • /perf-render-blocking-analysis https://localhost:3000 — live URL analysis
  • /perf-render-blocking-analysis ./src --platform sitecore — static source analysis
  • /perf-render-blocking-analysis https://staging.client.com --platform umbraco

Phase 1 — Detect Analysis Mode

URL mode: Run Lighthouse to extract the render-blocking-resources audit and network-requests waterfall. Parse the blocking chain from the JSON output.

Source mode: Grep the project for <head> HTML templates and locate CSS/JS/font resource declarations. Identify blocking patterns statically.


Phase 2 — JavaScript Blocking Audit

2.1 Identify blocking scripts

Scan <head> for any <script> without async or defer:

<!-- BLOCKING — delays HTML parsing until script downloads + executes -->
<script src="/vendor/jquery.min.js"></script>

<!-- NON-BLOCKING — async: downloads in parallel, executes immediately on load -->
<script src="/analytics.js" async></script>

<!-- NON-BLOCKING — defer: downloads in parallel, executes after HTML parsed -->
<script src="/app.js" defer></script>

Rules:

  • async: use for scripts that are independent (analytics, ads, social widgets)
  • defer: use for scripts that depend on DOM being ready (most app scripts)
  • Neither: only acceptable for inline critical scripts with no external dependencies
  • type="module" scripts are implicitly defer — do not add defer again

2.2 Next.js / React specific

Check all <Script> component usages. Every third-party <Script> must declare a strategy:

Strategy When to use
beforeInteractive Scripts that must run before page is interactive (rarely needed)
afterInteractive (default) Scripts that can run after hydration
lazyOnload Analytics, chat, social widgets — run when browser is idle
worker Experimental — moves script to web worker via Partytown

Flag any <Script> without a strategy prop and any script loaded via bare <script> tag.

2.3 Script size and parse time

For scripts identified as render-blocking, estimate parse/compile time:

  • Mobile (slow CPU): ~1 ms per 1 KB of minified JS
  • Rule of thumb: any blocking script > 50 KB is HIGH priority
  • Webpack/Vite bundle analysis: check for un-split vendor chunks > 100 KB

Phase 3 — CSS Blocking Audit

3.1 Identify blocking stylesheets

Every <link rel="stylesheet"> in <head> is render-blocking by default. Triage:

Should be blocking (critical CSS): Styles needed for above-the-fold content. Should be non-blocking: Styles for below-fold sections, print, or deferred UI.

Non-blocking loading pattern:

<!-- Trick: media="print" loads without blocking; onload switches to all -->
<link rel="stylesheet" href="/below-fold.css" media="print" onload="this.media='all'">
<noscript><link rel="stylesheet" href="/below-fold.css"></noscript>

Or use the modern approach with <link rel="preload">:

<link rel="preload" href="/below-fold.css" as="style" onload="this.rel='stylesheet'">

3.2 Critical CSS inlining

For pages with measurable FCP delay from external CSS, inline the critical-path styles in a <style> block and defer the full stylesheet:

<head>
  <!-- Inlined critical styles (above-fold only) — eliminates render-blocking entirely -->
  <style>
    /* nav, hero, above-fold typography — typically 5-15 KB */
    body { margin: 0; font-family: 'Inter', sans-serif; }
    .nav { display: flex; ... }
    .hero { min-height: 400px; ... }
  </style>
  <!-- Full stylesheet deferred — loads without blocking -->
  <link rel="preload" href="/styles.css" as="style" onload="this.rel='stylesheet'">
  <noscript><link rel="stylesheet" href="/styles.css"></noscript>
</head>

Tools for generating critical CSS: critical, critters (used by Angular CLI and Vite).

3.3 CSS size and specificity

  • Flag any single CSS file > 100 KB (uncompressed). Estimate blocked render time.
  • Check for CSS @import inside stylesheets — each @import creates a serial request waterfall.
  • Flag any CSS file that includes a @import url('...') — hoist to HTML <link> tags.

Phase 4 — Font Loading Audit

4.1 Font blocking patterns

Fonts are render-blocking when loaded via <link rel="stylesheet"> from Google Fonts or similar CDNs without display=swap. The browser holds paint until the font resolves.

Blocking patterns to flag:

<!-- BLOCKING: Google Fonts without display=swap param -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600" rel="stylesheet">

<!-- BLOCKING: @font-face without font-display -->
<style>
@font-face { font-family: 'Inter'; src: url('/fonts/inter.woff2'); }
</style>

Fixed patterns:

<!-- Non-blocking: preconnect + swap -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap" rel="stylesheet">
/* font-display: swap prevents FOIT; shows fallback while loading */
@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter.woff2') format('woff2');
  font-display: swap;
}

4.2 Font preloading

If the LCP element is text and a custom font is loading, preload the font file:

<!-- Preload the specific weight/format used in the LCP text element -->
<link rel="preload" href="/fonts/inter-600.woff2" as="font" type="font/woff2" crossorigin>

Rules:

  • Only preload fonts actually used above the fold — preloading everything wastes bandwidth
  • Always include crossorigin attribute (required for CORS-served fonts)
  • Prefer woff2 — best compression, universally supported

4.3 Self-hosting vs. Google Fonts

Self-hosting (fonts served from your own domain/CDN) eliminates the DNS lookup + TLS handshake overhead of fonts.googleapis.com and fonts.gstatic.com. For LCP-critical fonts on high-traffic sites, self-hosting typically saves 100–300 ms.


Phase 5 — Third-Party Resource Audit

Extract from Lighthouse third-party-summary audit. For each third-party origin:

Origin Category Blocking time Action
fonts.googleapis.com Fonts > 0 ms Preconnect / self-host
www.googletagmanager.com Analytics Variable Load async; use GTM's delayed loading
connect.facebook.net Social > 0 ms Defer with lazyOnload
widget.intercom.io Chat > 0 ms strategy="lazyOnload"
cdn.cookielaw.org Consent Critical Must load early but verify async is set

Total third-party blocking time > 500 ms = HIGH finding. Flag each contributing origin.


Phase 6 — Report

Output structured findings:

## Render-Blocking Analysis Report

**URL / Path:** [target]
**Platform:** [detected/specified]

### Blocking Resource Inventory

| Resource | Type | Blocking time | Size | Priority |
|---|---|---|---|---|
| /vendor/jquery.min.js | JS (no defer) | ~320 ms | 87 KB | HIGH |
| https://fonts.googleapis.com/... | Font CSS | ~210 ms | 4 KB | HIGH |
| /styles/all.css | CSS | ~180 ms | 220 KB | MEDIUM |

**Total estimated FCP savings if all resolved:** ~XXX ms

### Findings
[one block per finding using standard finding schema]

Quality Checklist

  • Every blocking script identified with exact filename and estimated blocking time
  • Font loading strategy checked — font-display: swap present on all @font-face
  • Third-party script origins enumerated with blocking time
  • CSS @import chains identified and count noted
  • Every finding has a specific before/after code fix
  • Total estimated FCP savings calculated

Reference files

  • reference.md — resource loading attributes reference, browser parsing waterfall model
Technical details
Plugin
performance-auditor
Author
Dakota Smith
Skill name
perf-render-blocking-analysis
Maturity
experimental
Security review
No security review
Owners
  • engineering
Argument hint
<URL or project-root-path> [--platform sitecore|optimizely|umbraco|headless]
Allowed tools
  • Read
  • Write
  • Glob
  • Grep
  • Bash(npx lighthouse *)
  • Bash(node *)
  • Bash(cat *)
  • Bash(ls *)
  • WebFetch(domain:localhost)
  • WebFetch(domain:web.dev)
Source
plugins/performance-auditor/skills/perf-render-blocking-analysis/SKILL.md

Edit this skill on GitHub — opens GitHub's web editor. No git knowledge needed.