Localize External Resources
Download and self-host third-party scripts, stylesheets, and images to eliminate external DNS and connection overhead.
Metrics
This technique can move up to 67% of LCP's share of the Lighthouse score.
This technique does not move TBT.
This technique does not move CLS.
This technique can move up to 67% of FCP's share of the Lighthouse score.
This technique can move up to 33% of SI's share of the Lighthouse score.
This technique does not move TTFB.
Overview
Many WordPress plugins and themes load scripts, stylesheets, and images from external CDNs and third-party servers — jQuery from code.jquery.com, font files from fonts.gstatic.com, tracking pixels from ad networks, and icon fonts from cdnjs.cloudflare.com. Each new origin requires a fresh DNS lookup, TCP handshake, and TLS negotiation — adding 100–600 ms of latency per origin before any data can be received. Localizing these resources — downloading and serving them from your own server — eliminates this per-origin connection cost and enables full control over caching headers.
Impact grade, A+ to D: how much of the Lighthouse score this technique can move. Unaffected: TBT, CLS, TTFB.
The Problem
The browser’s connection budget for a new origin is expensive: a cold connection to a new domain over HTTPS requires DNS resolution (~50ms), TCP handshake (~100ms), TLS negotiation (~100–200ms), and then the first HTTP request (~100ms) — totaling 350–500ms before a single byte of the resource arrives. A page that loads resources from 6 different external origins pays this overhead 6 separate times, in parallel but all competing for the early connection window. External resources also cannot be controlled for cache headers — a CDN may specify a 1-hour max-age when a 1-year immutable cache would be more appropriate.
Performance Impact
LCP
Indirect
faster CSS and font delivery means the LCP element renders sooner
FCP
100–400ms
eliminating external origins removes connection setup latency for render-blocking resources
SI
Moderate
resources from same origin load faster and with better cache hit rates
Risk: Low
localized files do not auto-update — set calendar reminders for security patch audits
How it works
01
Identify external resources loading on every page
Open DevTools → Network tab, filter by domain (not your own), and note every external origin loading CSS, JS, or fonts. Focus on resources that appear on all pages (navigation, theme assets) rather than page-specific embeds.
02
Download and host the files locally
Download the file at the version currently being loaded. Place it in your theme’s assets directory or a CDN path you control. Update your enqueue calls (
wp_enqueue_script,wp_enqueue_style) to point to the local URL.03
Set aggressive cache headers
Localized files should be served with
Cache-Control: public, max-age=31536000, immutable. If the file is versioned (the URL includes a hash or version number), it is safe to cache for a full year — users get the new file when the URL changes at the next update.04
Dequeue the original external enqueue
In WordPress, use
wp_dequeue_script()orwp_deregister_script()to remove the plugin’s or theme’s original external enqueue, then re-enqueue from the local path. Thewp_enqueue_scriptshook with a priority higher than the plugin’s original enqueue ensures the replacement fires after the original registration.
Code Example
<!-- jQuery UI from external CDN: new DNS + TCP + TLS per visitor -->
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"
integrity="sha256-..." crossorigin="anonymous"></script><!-- Local copy: same origin, cached 1 year, no connection overhead -->
<script src="/wp-content/themes/my-theme/js/jquery-ui.1.13.2.min.js"></script>In WordPress functions.php: wp_deregister_script('jquery-ui-core'); wp_enqueue_script('jquery-ui-core', get_theme_file_uri('js/jquery-ui.1.13.2.min.js'), ['jquery'], '1.13.2', true);
Limitations
- Locally hosted libraries are not automatically updated. If the external library releases a security patch, you must manually download and replace the local copy — set a calendar reminder for version audits.
- The shared-cache benefit of CDN-hosted libraries (e.g., many sites using the same jQuery CDN URL sharing a browser cache entry) no longer applies. In practice, browser cache partitioning in modern browsers eliminates this benefit anyway.
- Some libraries load additional resources from their own CDN (sub-resources). Localizing the entry-point JS does not help if that script then fetches its own dependencies from external origins — inspect each script’s network activity individually.
Common Mistakes
Localizing a library but not dequeuing the original external version
If both the original external enqueue and your local version are active simultaneously, the browser loads the library twice — doubling the cost. Always deregister or dequeue the original before adding your local version.
Localizing libraries with long-running CORS dependencies
Some external scripts (Google Fonts CSS, certain analytics SDKs) are designed to receive authenticated or personalized responses from their origin. Localizing these files caches a static response that may lack the personalization the library expects — test carefully after localizing.