squirrelscan
GitHub

Performance audit rules: page speed and Core Web Vitals

Audit rules for page speed: render-blocking resources, JavaScript and CSS weight, caching, compression and fonts, the causes of slow Core Web Vitals.

Performance rules read the HTML and the response headers to find what makes a page slow: render-blocking resources, oversized CSS and JavaScript, missing caching and compression, and the markup patterns behind each Core Web Vital. They report the causes a static read can see, not the metrics themselves, which need a real browser to measure.

Run only these rules

squirrel audit https://example.com --rule-include perf

Reliability, the other category in the Performance score group, has its own code. Add it with --rule-include perf,reliability.

Where to start

These carry the highest severity and weight in the category.

Rules

RuleWhat it flagsSeverityScope
Animated GIF on a page: convert to video for the bytesGIF images used for animation, and videos with no modern codec source. squirrel finds both in the markup.warningPer-page
Audits that need a browser: what a static crawl cannot seeThe runtime metrics no HTML analysis can produce. squirrel lists them so the gap in a static audit is explicit.infoPer-page
Cache-Control on a page: what squirrel reads and expectsA response with no caching headers, no-cache with no validator, or a static asset cached for under a day. squirrel reads the headers per page.warningPer-page
core-js and Babel helpers: legacy JavaScript in a bundlePolyfill bundles and ES5 transpilation helpers shipped to browsers that do not need them. squirrel reads script URLs and inline code.infoPer-page
Critical request chains: the blocking head resources countedBlocking stylesheets and scripts in head, plus every inline CSS @import a browser fetches. squirrel counts each as a link in the chain before first paint.warningPer-page
CSS file too large: the 150 KB and 500 KB thresholdsStylesheets over 150 KB warn and over 500 KB fail. squirrel measures every CSS file the crawl found and names the pages that load it.errorSite-wide
Exposed source maps: sourceMappingURL in production outputA sourceMappingURL comment or SourceMap header pointing at a map anyone can fetch. squirrel finds them in the page.infoPer-page
fetchpriority=‘high’: the LCP image hint squirrel checksA hero image loaded eagerly with neither fetchpriority=‘high’ nor a matching preload. squirrel picks the likely LCP candidate per page.warningPer-page
font-display swap: the @font-face rule squirrel looks forAn @font-face block with no font-display, or Google Fonts loaded without a preconnect. squirrel reads the inline CSS on every page.warningPer-page
Google Fonts blocking render: the font CSS squirrel flagsA stylesheet from a hosted font service in head, blocking first paint. squirrel checks eight providers and inline @import too.warningPer-page
Hidden carousel slides still download: eager images insideImages in inactive carousel slides loaded eagerly, so the browser fetches them anyway. squirrel walks up eight ancestors to find them.warningPer-page
HTTP/2 and HTTP/3: what the response headers can tell youWhether the server advertises HTTP/2 or HTTP/3. squirrel reads Alt-Svc and the Server header, and says when it cannot tell.infoPer-page
Images without width and height: the CLS risk squirrel findsImages and iframes with no dimensions, so the browser cannot reserve space before they load. squirrel lists every one by page.warningPer-page
JavaScript bundle too large: the 250 KB and 1 MB limitsScripts over 250 KB warn and over 1 MB fail. squirrel measures every JavaScript file the crawl found and names the pages that load it.errorSite-wide
Large DOM: node count, depth and children per elementA page at 1,500 DOM nodes or more, deeper than 32 levels, or with an element holding more than 60 children. squirrel counts all three.warningPer-page
LCP image not preloaded: what squirrel counts as a heroLikely Largest Contentful Paint images loaded with no preload. squirrel checks the first three eligible candidate images on every page.warningPer-page
loading=lazy on a hero image: the LCP delay squirrel findsAn above-fold image marked loading=lazy, which delays the paint that matters. squirrel checks the first three eligible images.warningPer-page
No compression detected: gzip and Brotli on the responseA text response served with no Content-Encoding, or with compression explicitly disabled. squirrel reads the headers on every page.warningPer-page
Outdated jQuery and friends: the libraries squirrel detectsTwenty-two known JavaScript libraries detected by URL, bundled code or markup, with a version check against known CVEs.warningPer-page
rel=preconnect: the CDN origins squirrel checks for a hintA page loading from a known CDN with no preconnect for that origin. squirrel checks thirteen common hosts.infoPer-page
Render-blocking resources: the ones squirrel counts in headStylesheets and scripts in head that hold up first paint. squirrel counts them per page and lists each URL.warningPer-page
Same library loaded twice: duplicate JavaScript on a pageOne library loaded from two script tags, or at two different versions. squirrel reads library names out of the script URLs.warningPer-page
Script URL redirects: a 3xx in front of every script loadJavaScript files that answer with a 3xx before serving. squirrel reports every one with the pages that reference it.warningSite-wide
Third-party scripts and INP: what squirrel counts per pageMore than five known third-party scripts, or more than three that block the parser. squirrel counts both on every page.infoPer-page
Time to First Byte: the 600ms and 1000ms thresholdsA server that takes over 600ms to send the first byte, or over 1000ms. squirrel measures TTFB on every fresh fetch.warningPer-page
Total page weight: the 1600 KB and 5000 KB thresholdsEach page scored on its own weight: its HTML, CSS, JavaScript, images and fonts. squirrel warns at 1600 KB and fails at 5000 KB.warningSite-wide, scored per page
Uncompressed CSS and JS: assets served without gzipLarge text sub-resources served with no Content-Encoding, while the HTML around them is compressed. squirrel checks every crawled asset.warningSite-wide
Unminified CSS: how squirrel tells minified from formattedStylesheets that read as source rather than build output. squirrel analyses inline CSS and judges linked files by their filename.warningPer-page
Unminified JavaScript: the signals squirrel reads in a fileScripts that read as source rather than build output. squirrel analyses the content it has and judges the rest by filename.warningPer-page
Weak caching across a site: freshness, validators, gzipMost pages missing a freshness lifetime, an ETag, or compression. squirrel measures the share across every crawled HTML response.warningSite-wide

Key terms

  • Client-side redirect: A redirect done in the page (meta refresh or JavaScript) rather than with an HTTP 3xx response.
  • Client-side rendering: Building page content in the browser with JavaScript; agents and many fetchers that do not run JavaScript see an empty page.
  • Core Web Vitals: Google’s three user-experience metrics: LCP for loading, INP for responsiveness and CLS for visual stability, judged at the 75th percentile of real visits.
  • Cumulative Layout Shift (CLS): A score for how much visible content moves unexpectedly while the page is in use; good is 0.1 or less.
  • DOM size: The number and depth of elements in a page’s document tree; large DOMs slow style calculation and interactions.
  • fetchpriority: An HTML attribute (high, low, auto) that hints how urgently the browser should fetch an image, script or link.
  • font-display: The @font-face descriptor (swap, optional, fallback) that decides what text shows while a web font loads.
  • HTTP caching: Response headers (Cache-Control, ETag, Expires) that let browsers and CDNs reuse a response instead of fetching it again.
  • HTTP compression: Compressing text responses (HTML, CSS, JS, JSON) with gzip, Brotli or zstd, signalled by Content-Encoding.
  • Image width and height attributes: Declared width and height on <img> that let the browser reserve space before the file loads, preventing layout shift.
  • Interaction to Next Paint (INP): The latency from a user interaction to the next frame, taken across the visit; good is 200 milliseconds or less. It replaced FID in March 2024.
  • Largest Contentful Paint (LCP): The time until the largest image or text block in the viewport renders; good is 2.5 seconds or less.
  • Lazy loading: Deferring off-screen images and iframes with loading=“lazy” so they load as the visitor scrolls.
  • Leaked secrets: Credentials or private keys shipped to the browser in HTML, scripts or source maps.
  • Minification: Removing whitespace, comments and long names from CSS and JavaScript so the file is smaller without changing behaviour.
  • Modern image formats: WebP and AVIF, which encode the same image in fewer bytes than JPEG or PNG.
  • Page weight: The total bytes a page downloads across HTML, CSS, JavaScript, images and fonts.
  • Redirect chain: A sequence of two or more redirects between the requested URL and the final response.
  • Render-blocking resources: Stylesheets and synchronous scripts in the head that the browser must fetch before it can paint anything.
  • Time to First Byte (TTFB): The time from the request until the first byte of the response arrives, covering redirects, DNS, connection and server time.

Images covers image file size, formats, responsive sizes and the width and height attributes that reserve space. Accessibility checks the same pages for people using a screen reader, a keyboard or zoom. Agent experience asks how heavy a page is for an agent to read, and whether its content needs JavaScript at all.

Learn more

Disable all Performance rules

[rules]
disable = ["perf/*"]

Type to search…

↑↓ navigate↵ openesc close