Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using webpack worker-loader with nuxt.js

I'm trying to use Web Worker within the nuxt.js framework but keep getting a reference error. ReferenceError: Worker is not defined.

I have installed worker-loader 1.1.1 via npm and added the following rule to my nuxt.config.js:

module.exports = {
  build: {
    extend (config, { isDev, isClient }) {
      if (isDev && isClient) {
        config.module.rules.push({
          enforce: 'pre',
          test: /\.(js|vue)$/,
          loader: 'eslint-loader',
          exclude: /(node_modules)/
        })
      }
      // Web Worker support
      config.module.rules.push({
        test: /\.worker\.js$/,
        use: { loader: 'worker-loader' },
        exclude: /(node_modules)/
      })
    }
  }
}

If I create a build via nuxt build it looks like the web worker file is created.

Asset                           Size                      
2a202b9d805e69831a05.worker.js  632 bytes          [emitted]

I import it inside a vuex module, like so:

import Worker from '~/assets/js/shared/Loader.worker.js'

console.log(Worker)
const worker = new Worker // <- this line fails!

In the console I get what looks like a function to create the worker:

ƒ () {
  return new Worker(__webpack_require__.p + "345c16d02e75e9312f73.worker.js");
}

Inside the worker, I just have some dummy code to see if it actually works:

const msg = 'world!'

self.addEventListener('message', event => {
  console.log(event.data)
  self.postMessage({ hello: msg })
})

self.postMessage({ hello: 'from web worker' })
like image 567
dotnetCarpenter Avatar asked Mar 07 '18 05:03

dotnetCarpenter


2 Answers

Let's first get some things settled:

  • workers are only available at client side -> no ssr

So either you need to use the no ssr component, or need to set the the application to no ssr

With this knowledge, we will modify our nuxt.config.js as follows:

mode: 'spa',
build: {
  extend(config, { isDev, isClient }) {
    ...
    // Web Worker support
    if (isClient) {
      config.module.rules.push({
        test: /\.worker\.js$/,
        use: { loader: 'worker-loader' },
        exclude: /(node_modules)/
      })
    }
  }
}

after npm run build and npm run start it should work like a charm.

I created a repo for you, it is a standard nuxt template with worker-loader utilized: Github Repo

like image 139
Greaka Avatar answered Sep 24 '22 10:09

Greaka


With worker-loader, there's the fallback option but personally (and this is what I'm doing) I would keep only the communication code inside the immediate worker file, importing a second file with the actual workload. This way the second file can also be imported serverside. Most likely in a forked thread/threadpool, unless you are in a FaaS context and your main thread has literally nothing else to do.

Also, did you have to use the following in nuxt.config.js? For me, without it, it was "window is undefined". (in the browser, when trying to instantiate worker)

extend(config, ctx) {
    /*
    ** Required for HotModuleReloading to work with worker-loader
    */
    config.output.globalObject = 'this'
}
like image 23
Mihail Malostanidis Avatar answered Sep 21 '22 10:09

Mihail Malostanidis