Simple DOM Manipulation via jQuery in Cloudflare Workers

I've recently been trying out Cloudflare Workers as part of another write-up which I'll be sharing soon, and I'm really excited about their potential. For those who aren't familiar with them, Cloudflare Workers allow you to write custom JavaScript code to run "on the edge" (i.e. in Cloudflare's data centres) which can modify a user's request on it's way to your origin server, or the response on the way back. This is pretty exciting, as it opens up a range of options across the board in the realms of security, performance and customisation (among others).

The Problem

The particular use-case I'm looking at involves lots of DOM manipulation – i.e. changing page content – something which is quite tricky with Cloudflare Workers currently as your only options are string manipulation and regex, which can get unwieldy very quickly. Ideally we'd be able to use the same tools that we use with JavaScript in a browser – like document.querySelectorAll to find elements matching a CSS selector – but Workers aren't Browsers, so unfortunately these methods aren't available to us.

After a number of tests I emailed to get the opinion of the Cloudflare Developer Help team, who let me know that they're planning improvements in this area in the near future, but in the meantime they were aware of another user who had managed to incorporate some DOM functionality into their Worker by browserifying the Node.js dom-parser module and including it in their Worker, so that might be an option to investigate in the meantime. I tinkered with this and got it working pretty quickly, but it got me thinking; this is a good option for getting data out of the page, but what if we could include something like jQuery in a Cloudflare worker? This would reduce the complexity of DOM manipulation massively, potentially even for non-developers, and allow us to easily modify the response before sending it to the client.

The Solution

It turns out, the cheerio module for Node.js provides exactly what we need – a server-side implementation of jQuery.

After a few hours of testing and tweaking, I've managed to get a proof of concept working which embeds Cheerio (jQuery) into a Cloudflare Worker. If you'd like to give it a go yourself, you can play around with the code in the Playground I've put together (alternatively the source is available in this gist). Feel free to make use of either in your own projects!

In the example below, I'm using jQuery to modify the response from the server and change the content of all h1 tags to be "¯\_(ツ)_/¯".

You can also apply CSS styles, as seen in the example below (note that all of the changes happen "on the edge" before the response is sent to the client – no Javascript is running in the client / browser);

The possibilities here are huge!

Bundling npm modules

If you're a developer interested in how to bundle NPM modules into a Worker script, the steps are roughly as follows;

  1. Install Browserify globally
  2. Create a new node project with npm init, and npm install the module(s) you need
  3. Create a file main.js, and add a require('module') for each module
  4. Run browserify main.js -o bundle.js
  5. Look through bundle.js and find function(require,module,exports){…} – your code will go inside of this function. Drop the sample code from the Playground site in that function, paste it back into the Playground, and check the console to see if you get any errors

As an additional step, you can minify the output of Step 4 by using an ES6-compatible minifier (like https://skalman.github.io/UglifyJS-online/) – this will give you some tidier code to work with. I did find that this required a bit of tweaking of minifier settings to get it working correctly, so if you're struggling – give me a shout via Twitter and I'm happy to chat!