vue中使用web worker踩坑

15,239 阅读3分钟

vue中使用web worker踩坑

web worker介绍

web worker是h5的一个新特性,主要是为了解决js在处理一些耗时任务时阻塞页面的渲染交互导致用户体验不好的问题,因为web worker可以为页面额外开启一个自包含的执行环境(js是单线程的),web worker开启一个额外线程靠的是浏览器支持。开启的这个线程用于为js处理那些耗时任务,然后js主线程继续处理页面渲染交互,用户体验就不会变差了。

html文件使用web worker

在vue中使用web worker和在普通html文件中方法不太一样。在普通的html文件中, web worker使用方法为:

 // index.html
   <script type="text/javascript">
   // 参数1是页面路径,参数2是配置参数
   let worker=new Worker('worker.js');
   // postMessage发送消息
   worker.postMessage('hello world!')
   // onmessage接收消息
   worker.onmessage=function(e){
    console.log('test文件接收到:',e);
   }
  </script>
  // worker.js
  // self表示的是子线程自身,也就是当前worker的全局对象
  // 所以可以把self替换成this,或者直接onmessage,不需要xxx.onmessage
  self.onmessage=function(e){
    self.postMessage('worker发送消息啦~')
  }
  • 需要注意,虽然new Worker()中的参数url指的是网络脚本文件,但是当index.html以进程形式运行(也就是占据了一个端口),那么此时相邻的worker.js文件也在本地网络上。url不能使用本地文件指的是Url为file://这种形式
  • 在普通html文件下的web worker就介绍到这里,有兴趣可以去看看 阮一峰老师的教程

在vue项目中使用web worker

  1. 首先声明一下初始项目配置:vue-cli2.9,webpack3
  2. 在vue中使用web worker的使用方法不一样,如:
   // App.vue
    import Worker from './worker/web.worker'
   
     // 参数1是页面路径,参数2是配置参数
  let worker=new Worker();
  // onmessage接收消息
  worker.onmessage=function(e){
   console.log('app.vue文件接收到:',e);
  }
    
  // web.worker.js
    // self表示的是子线程自身,也就是当前worker的全局对象
    // 所以可以把self替换成this,或者直接onmessage,不需要xxx.onmessage
    onmessage=function(e){
      postMessage('worker发送消息啦~')
    }
  • 但是会报错,提示 _worker_web_worker__WEBPACK_IMPORTED_MODULE_9___default.a is not a constructor"
  • 解决方法:(1)npm install worker-loader -D 安装worker.loader插件 (2)在vue.config.js文件中添加
  //对内部的 webpack 配置进行更细粒度的修改
  chainWebpack: config => {
    config.module
      .rule('worker')
      .test(/\.worker\.js$/)
      .use('worker-loader')
      .loader('worker-loader')
      .options({
        inline'fallback'
      })
    // 解决 "window is undefined", 这是因为 worker 线程中不存在 window 对象, 要用 this 代替
    config.output.globalObject('this')
  },
    // 解决打包的时报错
    parallel: false,
  • 虽然此时可以在打印台看到监听到了之前那样的数据,但是在终端会报错/worker/web.worker.js' is not a module.
  • 具体原因还不清楚,但是的确是可以用。

webpack踩坑

  1. 初始webpack的版本是3,结果没法使用web worker,究竟是否是webpack的原因犹未可知,就是在网络看到的升级为webpack4这种解决方法,然后用了也的确生效了
  2. (1)npm cache clean --force清除npm缓存 (2)删除node_modules (3)删除package.json中的webpack相关的库,需要注意的是需要上网查那些库,什么版本合适,例如vue-loader升级到15就错误了。
  3. const {merge} = require('webpack-merge') // 改为使用{} ,merge报错是因为版本改变,源码改变,需要改为{merge}形式使用

vue-cli2踩坑

  1. 虽然使用vue-cli2+webpack4可以使用web worker了,但是在项目打包的时候出了问题,需要更改CommonsChunkPlugin为SplitChunksPlugin,但是很多坑。改完一个问题又一个
  2. 最后升级vue-cli4,重新构建项目才解决。。

更好的web worker实现

  1. 在vue中实现worker可以使用vue-worker
  2. npm install vue-worker -save-dev
  3. 在main.js中导入import VueWorker from 'vue-worker';Vue.use(VueWorker);
  4. 使用例子
 created(){
    this.worker = this.$worker.create([
     {
      message:'hello',
      func:function(e){
       console.log('hello',e)  //hello i am yiye
       // 接收到消息之后发送
       return 'hi yiye'
      }
     },
     {
      message:'world!',
      func:function(e){
       console.log(e)
      }
     }
    ])
 },
  mounted(){
  this.worker.postMessage('hello',['i am yiye']).then(function(e){
   console.log('post:',e); //post: hi yiye
  })
 }