VueCLI + javascript環境で、WebWorkerを使用する

web workerでの記事は、webpack環境(nuxt.js環境)や、typescriptでの記事が多く存在し、
所々詰まっていたので記事にします。
[Web Worker の使用(MDN)](https://developer.mozilla.org/ja/docs/Web/API/Web_Workers_API/Using_web_workers)
[Vue.js で WebWorker を使う](https://blog.35d.jp/2020-01-27-web-worker)
[laravel-mix + Vue.js (ES) + WebWorker (TS)] (https://qiita.com/shohei_ot/items/61210e1012e9ae4f5d89)
これらの記事を参考にしました。

[今回作成したgitリポジトリ](https://github.com/imamiya-masaki/-workertest)
#導入
`vue ui` 等でvueを立ち上げたものとして、
プロジェクト直下で
`npm install worker-loader`
とし、worker-loaderを導入します。

そして、プロジェクト直下の`vue.config.js`(無ければ作成し)に、
下記の内容を記述します

 ```javascript:vue.config.js
module.exports = {
  chainWebpack: config => {
    config.module
      .rule('worker-loader')
      .test(/\.worker\.js$/)
      .use({
        loader: 'worker-loader',
        options: {
          inline: true
        }
      })
      .loader('worker-loader')
      .end()
  }
  //...
}

```

#実行準備
次に、srcフォルダ直下に
`workers`というフォルダと、`worker1`というjsファイルを作成します。
(※名称はなんでも良いと思います。また、フォルダは存在していなくても良いと思います。)

```zsh
src
 |-assets
 |-components
 |- ...
  |-workers
     |-worker1.js
 |-App.vue
 |-main.js
```
このような構成になるかと思います。
次に、worker1.jsの中身を

```javascript:worker1.js
addEventListener('message', e => {
    const { data } = e
    if (data && typeof data == 'number') {
        return postMessage(data*data)
    } else {
        return postMessage(10)
    }
})

export default {}

```
としてみます。
workerに投げられた変数が、int型の場合、二乗を返し、
それ以外の場合10を返す関数です。

次に、実際にvueファイルでworkerを呼び出します。
試しに、vuecliで生成されるHome.vueに書いていきます。

```javascript:Home.vue
<script>
import Worker1 from 'worker-loader!@/workers/worker1'
export default {
  name: 'Home',
  components: {
  },
  data () {
    return {
      reload: 0
    }
  },
  methods: {
    workerTest: function () {
      const worker = new Worker1()
      worker.onmeessage = e => {
        const { data } = e
        this.reload = data
        worker.terminate()
      }
      worker.postMessage(20)
    }
  }
}
</script>
```

このようにします。
import文に、`worker-loader!`をpath名の前に挿入することに気をつけ、また、
worker.onmessageで、workerの処理が終わった場合(つまりpostMessageが返った場合)の処理を記述します。
今回の場合は、処理が終わり次第、this.reloadに代入し他で参照できるようにします。
また処理を終えたあとにworkerが存在する意味はないので、terminateで削除します。
(※importがlintに怒られるかもしれないので、その場合はruleに記述しましょう...)

#実行
```vue:Home.vue
<template>
  <div class="home">
    <button @click="workerTest()">worker!!</button>
    {{ this.reload }}
  </div>
</template>
```

実際に、このようにして試してみると...

![スクリーンショット 2021-03-01 18.51.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518243/a46e49f5-c867-785d-93ca-79e140911703.png)

![スクリーンショット 2021-03-01 18.51.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518243/800d96e7-8b03-53bf-baee-467ac6215a21.png)

実際に、workerを通して、値が変更されたのがわかります。
また、

```javascript:Home.vue
workerTest: function () {
      const worker = new Worker1()
      worker.onmessage = e => {
        const { data } = e
        this.reload = data
      }
      worker.postMessage(20)
    }
```
とし、
開発者ツールのSourcesをみると
![スクリーンショット 2021-03-01 18.53.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518243/da3797c0-974d-e3f3-e00a-30e76a3b4000.png)
実際にworkerが立っているのがわかります。

#other

##ループの中で実行
試しに

```javascript:Home.vue
workerTestLoop: function () {
      for (let i = 0; i < 10; i++) {
        const worker = new Worker1()
        worker.onmessage = e => {
          const { data } = e
          this.reload += data
          worker.terminate()
        }
        worker.postMessage(20)
      }
    }
```

とし、先ほど同様に実行してみると、
実際に、先ほどの数字が4000(400 * 10)となっているのがわかります。
![スクリーンショット 2021-03-01 18.59.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518243/01ee4eb1-763a-9377-ad2d-e328d5f5b24a.png)