🪔

Next.jsでWeb-Workerを呼び出す

2021/08/18に公開

Next.jsとWeb-Worker

Next.jsは様々な機能を無設定で行えるように開発されています
Web-Workerに関しても同様で、next.config.jsに一切手を入れずに動かすことが出来ます
どのぐらい手軽に利用可能か、試してみたいと思います

サンプル置き場

https://github.com/SoraKumo001/next-worker
https://next-worker.vercel.app/

初期作業

yarn add next react react-dom
yarn add -D typescript @types/node @types/react

ソースコード

  • src/libs/sums.ts

1からcountで与えられた数までの合計を出すプログラムです
負荷をかけるため作業を1000回繰り返し、最後の結果を返します

export default null; //TypeScript警告避け

const worker = self as unknown as Worker;
worker.addEventListener("message", ({ data: { count } }: MessageEvent<{ count: number }>) => {
  let a: number;
  for (let j = 0; j < 1000; j++) {
    a = 0;
    for (let i = 1; i <= count; i++) {
      a += i;
    }
  }
  worker.postMessage({ value: a });
});
  • src/pages/index.tsx

実行ボタンを押すごとにWeb-Workerを起動して、結果が返ってきたら表示を更新します

import { useState } from "react";

const Page = () => {
  const [values, setValues] = useState([]);
  const handleSubmit: React.FormEventHandler<HTMLFormElement> = (e) => {
    e.preventDefault();
    const index = values.length;
    setValues([...values, "実行中"]);
    //web-workerの呼び出し
    const worker = new Worker(new URL("../libs/sums", import.meta.url));
    worker.addEventListener("message", ({ data: { value } }) => {
      setValues((values) => values.map((v, i) => (i === index ? value : v)));
    });
    worker.postMessage({ count: parseInt(e.currentTarget["count"].value) });
  };
  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input name="count" defaultValue="1000000" />
        <button>実行</button>
      </form>
      {values.map((v, index) => (
        <div key={index}>{v}</div>
      ))}
    </div>
  );
};

export default Page;

実行

yarn next

この処理を普通に行うと計算中はUIがブロックされますが、Web-Workerを利用した場合スムーズに動きます

まとめ

データのやりとりにpostMessageを介すことになるので、多少回りくどい部分がありますが、サーバと通信するのと感覚的には同じです
とてもお手軽に利用出来るので、ちょっとした重い処理がある場合などに利用していきたいところです

GitHubで編集を提案

Discussion