Skip to Content

Web Workers in WordPress: Part 1

Bringing modern web practices to WordPress has often been a process of pulling teeth. While that is changing thanks to a lot of hard work in the community, managing JS dependencies in WordPress is still a mixed bag.

But, it turns out I found two reliable strategies for managing web workers in WordPress. Direct path via Script Localization and via a Blob.

The difficulty on both of these options is about the same, but depends heavily on your comfort level. Additionally, this does assume that you have a Parcel or Webpack build set up for your plugin or theme.

Before we get to it, why bother?

There are a lot of reasons to keep your website fast and performant and frankly they have be covered expertly by others.

There are also a ton of strategies for improving page speed, web workers are one of many but I’m starting here, because it’s what I’ve been spending time on most recently.

A web worker runs additional JavaScript computation in a secondary thread. By moving operations off of the main thread you can free up the main thread for operations that are either more critical or only available on the main thread. Anything that requires DOM, for instance can’t be trivially offloaded to a worker as the document object isn’t available in a worker context.

In this example I’m using a worker to calculate the relative human readable time of a unix timestamp with Moment.js.

Moment.js can be a heavy dependency, but it conveniently doesn’t need anything that isn’t available inside a Worker. We can import Moment via `importScripts` and then use it just like we would in a main thread context.

Because the worker is its own thread it also has its own Event Loop, so universally calls to your worker should be treated as async operations.

The worker adds a listener for events it should act upon and returns a post message of its own back to the main thread.

The samples below should help illustrate this.

Because we’re talking about word press I’ve provided some localization valuables to ensure that my JavaScript references the worker file no matter how a user has set up their WP install.

Fig 1: Worker File

importScripts("https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js")

const relativeTime = timestamp => {
  console.log(timestamp)
  return moment.unix(timestamp).fromNow()
}

self.addEventListener("message", e => {
  console.log(e)
  const prettyTime = relativeTime(e.data[0])
  self.postMessage(prettyTime)
})

Fig 2: Simple Worker Interaction

const momentWorker = new Worker(`${window.mvt.theme_directory}/assets/dist/momentworker.${window.mvt.version}.js`)

const getRelativeTime = timestamp => {
  momentWorker.postMessage([timestamp])

  momentWorker.addEventListener('message', (evt) => {
    return evt.data
  }, false);
}
getRelativeTime(1529046600)

Fig 3: Returns a Promise wrapped Worker Function

const getRelativeTimePromise = timestamp => {
  momentWorker.postMessage([timestamp])

  return new Promise((resolve, reject) => {
    momentWorker.addEventListener('message', (evt) => {
      resolve(evt.data)
      if (!evt.data.ok) {
        reject(evt.data)
      }
    }, false);
  })
}

getRelativeTimePromise(1529046600)
  .then(result => {
    console.log('promise result')
    console.log(result)
  })
  .catch(err => {
    console.log(err)
  })
Load a File Based Web Worker with WordPress
Yield: A New Thread

Load a File Based Web Worker with WordPress

Prep Time: 5 minutes
Active Time: 20 minutes
Total Time: 25 minutes
Difficulty: Moderate

Add a file based web worker to your project.

Materials

  • A build config*

Tools

  • A computer
  • A text editor
  • A WordPress environment*

Instructions

  1. Fire Up your environment
  2. Add two files to your file tree, typically I user a worker suffix. ie. `utility.js` & `utility.worker.js` The first file is going to include the code to summon the worker. The second file is going to house the worker code.
  3. See Sample worker file at Fig 1.
  4. See Sample main thread code ad Fig's 2 & 3
Previous
Hello world!
shares