乐趣区

你可能不需要workloader来处理worker

相信很多人为了在 webpack 开发的时候使用 web-worker 而使用了 worker-loader 去进行处理,但是这个 loader 也存在一些问题,其实在 webpack 下不通过 worker-loader 也是可以使用的,仅仅需要非常简单的配置就可以。

背景:在多个 worker 中使用相同的包,最终 build 后,每个使用的 worker 中都集成了相同的第三方包,导致打包出来的 app.js 体积暴增,相同的第三方包无法抽离的情况。所以需要将这种方式剔除掉。并且该 loader 在 github 上的 issue 很多问题都没人解决,并不是很稳定。于是决定替换成 web-worker 原生方式

未抽离 worker-loader 时打包出来的包情况

从上图可以看出,同一个 xlsx-populate.min.js 包,在 worker 中使用后,和 worker 的逻辑代码打包到了一起,在非 worker 中使用则被抽离到了 vendor 中,等于多打包了一次,如果多个 worker 都要用到这个包,那就每个 worker 都会打包一次。想想都可怕。。。

抽离 worker-loader 后打包出来的情况

从上面打包后的结果来看 xlsx-populate 这个包已经不存在了,整个 app.js 的体积明显减少。

解决思路: 既然使用原生 web-worker 方式,那么在 worker 中引入第三方包的话,就只能使用远程资源的方式了,相应的其他地方用到 这个包的时候,如果使用 import 方式引入,那么就需要设置 external 来解决

在抽离过程中出现的一些坑记录如下

  1. 配置 external 属性时,如下的方式配置会导致 xlsx 为 undefined

    // webpack 配置
    externals: {'xlsx-populate': 'xlsx-populate'},
      
    // 组件内使用
    import xlsx from 'xlsx-populate';

    正确配置如下:其中 externals 中的 value 值,应该是引入该 scripts 后,该 scripts 在 window 上暴露出来的全局变量名称,在这里就是 XlsxPopulate,全局变量不一定和包名相同。这一点在 webpack 的文档中虽然给了一个 jquery 设置 external 的例子,但是如果不注意很容易忽略掉。

    // webpack 配置
    externals: {'xlsx-populate': 'XlsxPopulate'},
      
    // 组件内使用
    import xlsx from 'xlsx-populate';
  2. 在 worker 中使用时,importScripts 并不是返回一个暴露出来的模块供我们使用,所以去哪找挂载在 worker 中的这个模块呢?其实这个模块被挂载在了 该 worker 的 self 对象上,self 就等于页面中的 windows 对象

    importScripts('https://cdn-src.aiyunxiao.com/xlsx-populate/1.20.1/xlsx-populate.min.js');
    const XlsxPopulate = self.XlsxPopulate;
    // ... 使用 XlsxPopulate 做接下来的事 

看一下最后上线后的结果:

页面中使用 script 标签引入 xlsx-populate

在导出 excel 时,直接使用的缓存的 xlsx-populate 文件,所以整体只加载一次。

原文:chaijinsong-blog

退出移动版