Skip to main content

No render-blocking third-party scripts

ab-002591 · project-snapshot.performance.no-blocking-third-party-scripts
Severity: highactive

Why it matters

A render-blocking third-party <script src> in <head> stalls the HTML parser until the external server responds, fetches, and evaluates the bundle — which directly pushes both Largest Contentful Paint and Interaction to Next Paint past Google's "good" thresholds and demotes the page in CrUX-fed Search rankings. Third-party CDNs also carry tail-latency the origin does not control; a slow day at a tag manager or chat widget vendor becomes a slow day at your site. AI coding tools reproduce the failing shape routinely: they follow a vendor's copy-paste install snippet verbatim (bare <script src="https://cdn.example.com/widget.js"> in the layout) rather than reaching for next/script strategy="afterInteractive" or a plain defer attribute. Users on slower networks see a blank page for seconds while the third-party loads.

Severity rationale

High because a single blocking external script degrades LCP and INP for every visitor and demotes Search ranking via CrUX, and the failing shape typically sits in the global layout where it affects 100% of page loads.

Remediation

Add defer or use next/script:

import Script from 'next/script'
<Script src="https://cdn.example.com/widget.js" strategy="lazyOnload" />

Deeper remediation guidance and cross-reference coverage for this check lives in the performance-load Pro audit — run that after applying this fix for a more exhaustive pass on the same topic.

Detection

  • ID: project-snapshot.performance.no-blocking-third-party-scripts
  • Severity: high
  • What to look for: Enumerate every <script src> tag in HTML files and <Script> element in JSX. For each external script (host !== same origin), check whether async, defer, or Next.js <Script strategy="afterInteractive|lazyOnload"> is present. Count blocking vs. async/deferred.
  • Pass criteria: All external third-party scripts use async, defer, or a Next.js non-blocking strategy.
  • Fail criteria: At least one external script tag with neither async nor defer nor a non-blocking strategy.
  • Skip (N/A) when: Project has no script tags at all (no <script> in HTML or <Script> in JSX).
  • Do NOT pass when: A script is loaded with async BUT placed in <head> and used by inline scripts that follow — that is effectively render-blocking.
  • Report even on pass: "Found N external scripts; all N use async/defer/non-blocking strategy."
  • Detail on fail: "Render-blocking script in app/layout.tsx: <script src='https://cdn.example.com/widget.js'> (no async/defer)".
  • Cross-reference: For full performance coverage (Core Web Vitals, bundle-size budgets, database query plans), run the performance-load audit.
  • Remediation: Add defer or use next/script:
    import Script from 'next/script'
    <Script src="https://cdn.example.com/widget.js" strategy="lazyOnload" />
    

Taxons

History