Last active
September 20, 2024 09:22
-
-
Save brandomeniconi/1dfc5558e24e0010c6e22c4a46bc1a9a to your computer and use it in GitHub Desktop.
Basic Cloudflare Worker that allows efficient page caching for Wordpress websites
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Version 1.4 | |
const DAY_IN_SECONDS = 60*60*24; | |
const BLACKLISTED_URL_PARAMS = [ | |
'fbclid', // Google Ads click Id | |
'gclid', // Facebook click Id | |
'msclkid', // Micorosft Ads Click Id | |
]; | |
addEventListener('fetch', event => { | |
event.respondWith(fetchAndApply(event.request)) | |
}) | |
async function fetchAndApply(request) { | |
let cloudflareOptions = {} | |
let url = new URL(request.url) | |
// Bypass Cache if is a non cachable WP request or is not a GET request | |
let bypassCache = isWordpressNoCache( request ) || (request.method !== 'GET'); | |
if ( bypassCache ) { | |
// Disable page Cache, this shoud keep the static assets cache on. | |
cloudflareOptions.cacheEverything = false; | |
} else { | |
// Force request caching | |
cloudflareOptions.cacheEverything = true; | |
// Set Edge Cache default TTL | |
cloudflareOptions.cacheTtl = 365 * DAY_IN_SECONDS; | |
// Set thje edge cache TTL by response status | |
cloudflareOptions.cacheTtlByStatus = { | |
"200-299": 365 * DAY_IN_SECONDS, | |
404: 60 * DAY_IN_SECONDS, | |
"500-599": 100 | |
}; | |
//blacklisted url params | |
BLACKLISTED_URL_PARAMS.forEach((blParam) => { | |
url.searchParams.delete(blParam); | |
}); | |
//or delete all URL parameters unconditionally | |
//url.search = ''; | |
} | |
//create a new editable request | |
let newRequest = new Request(url.toString(), request ); | |
// Pipe the request to the CF servers and wait for the response | |
let response = await fetch(newRequest, {cf : cloudflareOptions} ); | |
// Copy the response so that we can modify headers. | |
response = new Response(response.body, response) | |
// Lower the browser max-age for pages to 1 mins. This is done to avoid caching a website page | |
// on user device for the entire edge cache TTL (default CF behavior). We can't purge or invalidate it! | |
if ( !bypassCache && !isStaticFile( response ) ) { | |
response.headers.set("Cache-Control", "max-age=60"); | |
} | |
// return the response to client | |
return response | |
} | |
// Checks if we should not cache the request due to one of the following reasons: | |
// * user logged in | |
// * user is commenting a post | |
// * user has some products in cart or is using woocommerce | |
// * user is in the wp-admin section or other WP related resources | |
function isWordpressNoCache( request ) { | |
// Get full URL from the request | |
const url = new URL(request.url) | |
// Get raw cookies from the request | |
const cookie = request.headers.get('Cookie'); | |
//Create a regex to match cookies that suggeest: user logged-in, comments or woocomerce session | |
const wpRegex = /;\s?(wordpress_logged_in_|comment_|woocommerce_)[^=]+=/g; | |
return ( | |
// If request contains cookies check if there are WP related cookies | |
( cookie && cookie.match(wpRegex) ) | |
// Check if the URL path is WP Core related | |
|| url.pathname.startsWith('/wp-') | |
// Check if the URL path is WP Core related (roots/bedrock version) | |
|| url.pathname.startsWith('/wp/wp-') ); | |
} | |
// Check if a response is a static file or a document or API response | |
function isStaticFile( response ){ | |
// Get content-type from the response | |
let contentType = response.headers.get('content-type'); | |
// Check if the response content type is an HTML page or a JSON object | |
if ( contentType && ( contentType.startsWith('text/html') || contentType.startsWith('application/json') ) ) { | |
return false; | |
} | |
return true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment