Why Use a CDN for Assets?

A Content Delivery Network (CDN) helps speed up a website by caching static assets (like JavaScript and CSS) on servers distributed around the world. This reduces latency and offloads traffic from the origin server, improving load times and user experience.

Cloudflare has a WordPress plugin that will help you cache everything, including dynamic content, on the Cloudflare edge. I didn’t want to do that, preferring more control over caching HTML content and less complexity around invalidating the Cloudflare cache. However, I still want to take advantage of Cloudflare’s CDN to cache my site’s static assets. I’ve found that you can still get great performance without proxying dynamic content through Cloudflare. (I do cache full HTML pages in Nginx.)

I’m already serving images from Cloudflare the imgproxy plugin I mentioned previously. It’s harder to target image URLs in WordPress posts, but you could use that plugin for inspiration.

Setting Up Cloudflare for WordPress Assets

Instead of placing my whole domain behind Cloudflare, I added a new subdomain dedicated to serving assets:

1. Add a new domain (or subdomain) to Cloudflare

  • In Cloudflare, I added cdn.example.com as a new site.
  • This domain is configured as a CNAME pointing to my WordPress site.

2. Enable Cloudflare caching

  • Since WordPress appends query strings for versioning (e.g., ?ver=6.4.2), new styles and scripts will always be available right after updating.

3. Ensure the subdomain serves assets correctly

  • If your web server allows wildcard domains, this should work without any additional configuration.
  • WordPress itself doesn’t care about the domain name for assets.

At this point, assets should be accessible via cdn.example.com, but WordPress is still serving them from the main domain. The next step is to rewrite asset URLs to use the CDN. I recommend testing that you can load static assets from Cloudflare before continuing. A good test is https://cdn.example.com/wp-includes/css/editor.min.css. That should load the expected stylesheet before switching asset URLs to your new CDN domain.

Rewriting WordPress Asset URLs

To make WordPress use the CDN, I created a small plugin to rewrite script and style URLs. This plugin ensures that any assets hosted on my WordPress site are served from cdn.example.com instead.

<?php

namespace CFCDN;

// Define your CDN URL
define( 'CDN_URL', 'https://cdn.example.com' );

/**
 * Replace the URL with CDN URL.
 *
 * @param string $url The original URL.
 * @return string The modified URL with CDN.
 */
function replace_url_with_cdn( $url ) {
    // Only modify the URL if it's a local URL
    $host = parse_url( $url, PHP_URL_HOST );
    $home_host = parse_url( home_url(), PHP_URL_HOST );
    if ( $host === $home_host ) {
        $parsed = parse_url( CDN_URL );
        $replace = $parsed['scheme'] . '://' . $parsed['host'];

        // Replace the site's URL with the CDN URL
        $url = str_replace( home_url(), $replace, $url );
    }

    return $url;
}

/**
 * Use the CDN URL everywhere we currently use a stylesheet URL
 *
 * For example, the favicon URL and preload URLs.
 * @param string stylesheet_dir_uri The source URL of the script.
 * @return string The modified script URL.
 */
function stylesheet_directory_uri( $stylesheet_dir_uri ) {
    return replace_url_with_cdn( $stylesheet_dir_uri );
}
add_filter( 'stylesheet_directory_uri', 'CFCDN\stylesheet_directory_uri' );

/**
 * Enqueue CDN URLs for scripts.
 *
 * @param string $src The source URL of the script.
 * @param string $handle The script's registered handle.
 * @return string The modified script URL.
 */
function enqueue_cdn_scripts( $src, $handle ) {
    return replace_url_with_cdn( $src );
}
add_filter( 'script_loader_src', 'CFCDN\enqueue_cdn_scripts', 10, 2 );

/**
 * Enqueue CDN URLs for styles.
 *
 * @param string $src The source URL of the style.
 * @param string $handle The style's registered handle.
 * @return string The modified style URL.
 */
function enqueue_cdn_styles( $src, $handle ) {
    return replace_url_with_cdn( $src );
}
add_filter( 'style_loader_src', 'CFCDN\enqueue_cdn_styles', 10, 2 );

This plugin works by:

  • Checking if the URL belongs to the WordPress site.
  • Rewriting it to use the CDN domain instead.
  • Applying this change to all scripts, styles, and even theme-related assets.

Once activated, WordPress automatically loads JavaScript and CSS from the Cloudflare CDN. It’s worth noting that this even serves scripts and styles from the CDN in wp-admin.

Final Thoughts

This approach lets me use Cloudflare’s caching for JavaScript and CSS assets without putting my entire site behind Cloudflare. The setup is straightforward:

  • Create a new Cloudflare domain as a CNAME to WordPress.
  • Enable caching for static assets.
  • Rewrite asset URLs using a small WordPress plugin.

With minimal effort, this improves page speed, reduces server load, and provides a better user experience. If you’re looking for a simple way to boost your WordPress site’s performance, this method is worth considering.