Closed alexhx5 closed 5 years ago
Never mind. I figured out how to make it work. For anyone else having troubles with this, here's what I did:
Install worker-loader
:
yarn add -D worker-loader
Add the following in your vue.config.js
:
module.exports = {
configureWebpack: {
module: {
rules: [
{
test: /\.worker\.js$/,
use: { loader: 'worker-loader' }
}
]
}
...
background.js
(main Electron file), inside webPreferences: {}
of the window, add nodeIntegrationInWorker: true
if you want to be able to use Node's modules inside the worker. Create a worker file (e.g. workers/worker1.js
) and create a listener in there, here's some example:const path = require('path')
// Listen to messages from parent thread
self.addEventListener('message', (event) => {
console.log('Worker received message:', event.data)
// Do some calculations and send the result back to parent thread
let parsedPath = path.parse('C:/test')
self.postMessage({result: parsedPath})
})
<script>
import Worker1 from 'worker-loader!../workers/worker1'
let worker = new Worker1()
...
mounted() {
worker.addEventListener("message", function (event) {
console.log('Received data from worker:', event.data)
})
}
...
methods: {
someMethod() {
// Send some message to the worker
worker.postMessage({parse: 'C:/test'})
}
}
Notes:
Don't try to use node's native worker_threads
, they don't work in Electron
Tags for people who's trying to find it:
Thanks for providing such a detailed guide! I will link to this in the docs when I get the chance.
@nklayman sure thing! As a junior developer I had no idea that I have to use webpack loaders. At least others won't need to spend several hours trying to figure out how to make it work. There's almost no information about this issue on the internet.
@AlexSHoffman Nice guide ! But after build I get the following error:
Uncaught Error: ENOENT, worker\api\exports\electron.js not found in C:\path-to-code-folder\dist_electron\win-unpacked\resources\electron.asar
@dooodgers not sure, but it seems the app doesn't have that worker folder bundled. Try messing about with vue.config.js
, maybe add and specify files: []
:
module.exports = {
configureWebpack: {
...
},
pluginOptions: {
electronBuilder: {
builderOptions: {
files: [
"**/*",
"./build/**/*",
"./worker/api/exports/**"
],
}
}
}
}
Perhaps @nklayman knows how to fix it?
Required node module should be bundled along with my worker file?
I builed with asar: false
and required node module and worker are bundled in one file.
Update: I checked with simple worker (without importing module) and it works.
Please understand that English is not my native language
I am try use vim-wasm
in my project
it has some problem
Firstly i have to explain vim-wasm
use the Web Worker's structure
Major script is vimwasm.js
and vim.js
in his offical example
vimwasm.js: ES Module to manage lifetime of Web Worker vim.js: Web Worker script to drive vim.wasm
in my code
import {VimWasm}from 'vim-wasm'
to source code in vimwasm.js
VimWasm
is a eport class and for use fllowing three argument
canvas: document.getElementById('vimcanvas'),
input: document.getElementById('viminput'),
workerScriptPath: '../../node_modules/vim-wasm/vim.js
use the above in his script vimwasm.js
internal to do a new Worker
so
webpack can't work it ( i don't how to dispose in any way it make be agiated 😡 )
when launch app it become Uncaught SyntaxError: Unexpected token '<'
export class VimWasm {
constructor(opts) {
const script = opts.workerScriptPath;
if (!script) {
throw new Error("'workerScriptPath' option is required")
}
this.handleError = this.handleError.bind(this);
this.worker = new VimWorker(script, this.onMessage.bind(this), this.handleError);
if ("canvas" in opts && "input" in opts) {
this.screen = new ScreenCanvas(this.worker, opts.canvas, opts.input)
} else if ("screen" in opts) {
this.screen = opts.screen
} else {
throw new Error("Invalid options for VimWasm construction: " + JSON.stringify(opts))
}
this.perf = false;
this.debug = false;
this.perfMessages = {};
this.running = false;
this.end = false
}
```node
export class VimWorker {
constructor(scriptPath, onMessage, onError) {
this.worker = new Worker(scriptPath);
this.worker.onmessage = this.recvMessage.bind(this);
this.worker.onerror = this.recvError.bind(this);
this.sharedBuffer = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 128)); //mark
this.onMessage = onMessage;
this.onError = onError;
this.onOneshotMessage = new Map;
this.debug = false;
this.pendingEvents = []
}
<template lang="html">
<div>
<canvas id="vimcanvas" ref="vimcanvas"></canvas>
<input autocomplete="off" ref="viminput" id="viminput" autofocus>
</div>
</template>
<script>
// import {
// VimWasm
// } from '../../node_modules/vim-wasm/vimwasm.js'
import {VimWasm}from 'vim-wasm'
export default {
name: 'vim',
mounted:function(){
const vim = new VimWasm({
canvas: document.getElementById('vimcanvas'),
input: document.getElementById('viminput'),
workerScriptPath: '../../node_modules/vim-wasm/vim.js'
})
vim.start()
}
}
</script>
<style lang="css" scoped>
canvas{
width: 500px;
height: 500px;
background: #add8e6;
}
</style>
I will add some tips from my own experience.
Do not insert the configuration into the vue.config.js:
module.exports = {
configureWebpack: {
module: {
rules: [
{
test: /\.worker\.(js|ts)$/,
use: { loader: 'worker-loader' }
}
]
}
...
Use only inline syntax
import MyWorker from 'worker-loader!../workers/my-worker'
For using with TypeScript add the following in your typings:
declare module "worker-loader!*" {
class WebpackWorker extends Worker {
constructor();
}
export default WebpackWorker;
}
If you encounter a TypeError: Cannot read property 'app' of undefined
, try to pass all the associated code to a separate chunk and load it asynchronously.
I think the above guide is no longer relevant. I had a lot of problems with this approach. (https://github.com/vuejs/vue-cli/issues/5283 one of the most unpleasant)
Never mind. I figured out how to make it work. For anyone else having troubles with this, here's what I did:
1. Install `worker-loader`:
yarn add -D worker-loader
1. Add the following in your `vue.config.js`:
module.exports = { configureWebpack: { module: { rules: [ { test: /\.worker\.js$/, use: { loader: 'worker-loader' } } ] } ...
1. In your `background.js` (main Electron file), inside `webPreferences: {}` of the window, add `nodeIntegrationInWorker: true` if you want to be able to use Node's modules inside the worker. Create a worker file (e.g. `workers/worker1.js`) and create a listener in there, here's some example:
const path = require('path') // Listen to messages from parent thread self.addEventListener('message', (event) => { console.log('Worker received message:', event.data) // Do some calculations and send the result back to parent thread let parsedPath = path.parse('C:/test') self.postMessage({result: parsedPath}) })
1. Import and init the worker where you need it:
<script> import Worker1 from 'worker-loader!../workers/worker1' let worker = new Worker1() ... mounted() { worker.addEventListener("message", function (event) { console.log('Received data from worker:', event.data) }) } ... methods: { someMethod() { // Send some message to the worker worker.postMessage({parse: 'C:/test'}) } }
Notes: Don't try to use node's native
worker_threads
, they don't work in ElectronTags for people who's trying to find it:
* Web worker Module not found: Error: Can't resolve * Webpack electron-builder web worker doesn't work * How to use modules inside web worker in electron webpack
I found an easier way to use workers. Just use https://github.com/GoogleChromeLabs/worker-plugin. @nklayman, maybe you would like to include this in vue-cli-plugin-electron-builder by default?
@cawa-93 I added worker-plugin instructions to the docs, under guide. Thanks for the tip!
It works. Thanks. @alexhx5
Describe the bug Web workers don't work, I get the following error:
When I click on the error, I see the code from the
index.html
for some reason:structure
App.vue
testWorker.js
Environment: