Web workers - how to use in Quasar



  • There’s many libs for web workers. One which is quite simple and working in Quasar is described below.

    Lets create a new test Quasa project, with javascript and simple options:

    quasar create qworkers
    

    We will be using this library and integrate it with our test project:
    https://github.com/developit/workerize-loader

    In file package.json we will add this:

      "devDependencies": {
        ...
        "workerize-loader": "^1.3.0"
      },
    
    

    In file quasar.conf.js we will add this:

        build: {
          ...
          // https://quasar.dev/quasar-cli/handling-webpack
          chainWebpack (chain) {
            chain.output.set('globalObject', 'this')
          },
          extendWebpack (cfg) {
            ...
            cfg.module.rules.push({
              test: /\.worker\.js$/,
              exclude: /node_modules/,
              loader: 'workerize-loader',
              options: { inline: true }
            })
          }
        },
    

    Our index.vue should look like this:

    <template>
      <q-page class="flex flex-center">
        <img
          alt="Quasar logo"
          src="~assets/quasar-logo-full.svg"
        >
        <q-btn @click="start1">start worker</q-btn>
        <q-btn @click="start2">start DOM function</q-btn>
      </q-page>
    </template>
    
    <script>
    import worker from './test.worker'
    
    export default {
      name: 'PageIndex',
      methods: {
        async start1 () {
          const instance = worker()
          const count = await instance.expensive(5000)
          console.log(`Ran1 ${count} loops`)
        },
        expensive (time) {
          const start = Date.now()
          let count = 0
          while (Date.now() - start < time) {
            count++
          }
          return count
        },
        start2 () {
          const count = this.expensive(5000)
          console.log(`Ran2 ${count} loops`)
        }
      }
    }
    </script>
    

    We will add a new file src/pages/test.worker.js with content:

    export function expensive (time) {
      const start = Date.now()
      let count = 0
      while (Date.now() - start < time) {
        count++
      }
      return count
    }
    
    export default expensive
    

    Next we execute commands:

    npm install
    quasar dev
    

    And the browser should popup:

    dcdbeb92-5703-476c-85fe-a2979fe8bdf9-image.png

    Pressing “start worker” button will execute CPU expensive function in web worker. Observe, that the page is fully responsive. The result will be shown in the console.
    Pressing “start dom function” will execute CPU expensive function in main DOM browser thread. The page will NOT be responsive! The result will be shown in the console.

    Discussion:

    1. Why this library? Well, it’s simple and it works. The integration by webpack in inline mode allows nice HMR and quasar bundling.
    2. Why there are strange CSP comments in firefox? Yes, the web workers has some security quirks and there are differences in handling them in Chrome and Firefox. There is a section about Content Security Policy in MDN about that:
      https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
    3. Why do you need web workers in Quasar? In Quasar there are many potential optimizations which could benefit from using web workers. They are not only typical sorting, filtering, querying but even less obvious parts of Quasar component where the CPU work could be transferred to web worker. Yes, it could make Quasar the fastest framework in the market.
    4. Oh, but I’m just a user and I want web workers in Quasar, too! Well, I would like also! I think it is time to include web workers support in base library - similar as it was done with support for other browser API as local storage, full screen, resize. The one, working Quasar interface to web workers would be a game changer.
    5. What if somebody will create an App Extension with web workers support instead? This IMHO would be less optimal, because the Quasar API for web workers should be the same for internal Quasar components and for user apps. The example above is rather simple in terms of communication, but in real life, probably one would want a more advanced communnication between components. It comes to mind the excellent BEX mode and the concept of bridge. I think, if Quasar would implement support for web workers, the existing bridge concept as a means of communication would be just right.


  • @qyloxe

    Obviously amazing! a few question:

    1. Is it possible/useful to offload heavy UI components (with render functions i Quess) to workerize-loader?

    2. can you use Quasar current workbox webworkers( for install to deceive, auto updating, cache, offline support ect) and workerize-loader at the same time?



  • @dobbel said in Web workers - how to use in Quasar:

    @qyloxe
    Obviously amazing! a few question:

    1. Is it possible/useful to offload heavy UI components (with render functions i Quess) to workerize-loader?

    YES! q-table filtering, q-tree node searching and much, much more could be optimized by web workers.

    1. can you use Quasar current workbox webworkers( for install to deceive, auto updating, cache, offline support ect) and workerize-loader at the same time?

    workbox uses “service workers” we are using something different “web workers”. More here:

    https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API

    There are more types of workers also.



  • @qyloxe

    Ah that’s something I did not know about workers. Thanks

    Would it be possible/feasible to have the offloading of ‘expensive’ code be (auto)managed by Vue or Quasar? For example: offloading the entire template (UI) rendering process (in maybe multiple webworkers)?

    I am all excited 🙂



  • @dobbel said in Web workers - how to use in Quasar:

    @qyloxe

    Would it be possible/feasible to have the offloading of ‘expensive’ code be (auto)managed by Vue or Quasar? For example: offloading the entire template (UI) rendering process (in maybe multiple webworkers)?

    well, web workers does not have access to DOM, so it’s tricky. There are projects like this:

    https://github.com/ampproject/worker-dom

    BUT i think it should be done (in most cases) at the Vue level not Quasar. At the Quasar level, there’s possibility to use worker threads for many, many cpu intensive tasks. AND it should be possible, to use workers in user apps easily in Quasar framework.



  • @qyloxe

    Thanks for the info. I have fiddled with that worker-dom project. Have you ever used it in a Quasar project?



  • There’s a web worker wrapper out there for Vue, called vue-worker.



  • @dobbel said in Web workers - how to use in Quasar:

    @qyloxe

    Thanks for the info. I have fiddled with that worker-dom project. Have you ever used it in a Quasar project?

    Nope. I mentioned it as an idea or possibility of DOM accessibility from web workers. Anyway, worker-dom abstraction works rather at the vue (or react, or svelte) level than at the Quasar. IMHO such interface from workers should be available as another browser API.

    I will be needing in the near future a massive boost in CPU processing in Quasar, so I’m looking for a way to deal with that. The web worker is OK in terms of user experience, but I’m afraid, that the real performance boost will need the WASM technology. Nevertheless, using web workers at the Quasar level would be so much cool!



  • @metalsadman said in Web workers - how to use in Quasar:

    There’s a web worker wrapper out there for Vue, called vue-worker.

    Yeah, I saw that and this is what took my attention:

    • the last commit is from three years ago - deal breaker 😞
    • it is a simple API wrapper, the functions are mostly inlined so this will be a problem in Quasar apps or bigger projects
    • the model of communication is actually mimicking the web workers API so there’s no real gain. I would prefer to have something like RPC (as in workerize-loader) or the adjusted model of processing with external message bus - strongly similar to BEX and bridge in Quasar
    • I need to have HMR, debuggability and easy bundling of workers with tree shaking. I’m afraid that interfacing vue-worker with Quasar could be tricky.

    The workerize-loader took my attention because of webpack. This is a fun idea! I was very curious if it will work with Quasar and I’m happy that it is.


Log in to reply