umi4之前需要配置worker-loader,被网上各种帖子坑了一天,各种配置都试了,走不通
umi4之后,自带webpack5,什么配置都不需要,直接上代码
以下代码其他脚手架,带webpack5的话应该都适用
1.worker 代码
// src/workers/testworker.ts
function add(num0:number,num1:number){
let sum = num0+num1;
self.postMessage(sum);
}
self.addEventListener('message',event=>{
const {num0,num1} = event.data;
console.log(event);
add(num0,num1);
})
2.前端调用worker
const testWkr = new Worker(new URL('@/workers/testworker.ts', import.meta.url));;
testWkr.postMessage({num0:5,num1:6});
testWkr.addEventListener('message',event=>{
console.log(event.data);
testWkr.terminate();
});
或者封装一下,当成普通的函数执行。一般发现前台卡顿后才去考虑worker,这样worker 简单调用之前的处理代码,然后把调用worker过程新文件封装成之前的函数,就基本不用大动代码。
//封装成异步函数/promise
export function add_async_worker(num0: number, num1: number) {
return new Promise((resolve: (value: number) => void, reject: (error: ErrorEvent) => void) => {
const testWkr = new Worker(new URL('@/workers/testworker.ts', import.meta.url));
//也可以使用
//testWkr.addEventListener("message", (event) => {resolve(event.data as number);});
testWkr.addEventListener('message', event => {
resolve(event.data as number);
testWkr.terminate();
});
//也可以使用
//testWkr.onerror = (event) => {reject(event);};
testWkr.addEventListener("error", (event) => {
reject(event);
testWkr.terminate();
});
testWkr.postMessage({ num0: num0, num1: num1 });
});
}
//正常的异步函数调用
async function name() {
let sum = await add_async_worker(5, 6).catch(error=>{
console.log(error);
return NaN;
});
console.log(sum);
}
3.重型数据传递
如果要传向worker传递文件/bolb等数据,普通消息传递会影响效率,可以传递transfer
//前台
let image:File= ... ;
image.arrayBuffer().then(arrbuf=>{
const testWkr = new Worker(new URL('@/workers/testworker.ts', import.meta.url));
//传递,传递之后就不能再访问arrbuf了,因为这个对象内存已经交给worker线程了
testWkr.postMessage({ sth: "sth",data:arrbuf,type:image.type,filename:image.name},[arrbuf] );
})
//worker
self.addEventListener('message',event=>{
//接收主线程的transfer数据并封装还原File
let image=new File([event.data.data as ArrayBuffer],event.data.filename,
{type:event.data.type});
//处理之后可以像前台一样postMessage,把数据内存交给前台
//注意transfer数据交给前台之后,worker线程也是不能访问这个数据了
})
4.使用三方库
在Umi框架中,如果worker要使用三方库的话,需要配置mfsu,排除三方库,不然会报错.
需要注意的是,不是所有函数和构造函数 (或者说…类) 都可以在 Worker 中使用。具体参考页面 Worker 所支持的函数和类。
也就是说如果三方库用到了worker不支持的函数和类,就不能在worker中运行,比如我踩过的图片压缩库 compressorjs ,就使用了HTMLCanvasElement: toBlob(),前台运行尚可,worker直接报错。
// .umirc.ts
// 这里排除了两个前端加密库
export default defineConfig({
...
mfsu:{
exclude:['crypto-js','jsrsasign']
},
...
});
参考:
里面写了一句话:
As of webpack 5, you can use Web Workers without worker-loader.
3. umi MFSU 配置
4. Web Workers API