🦐

Nuxt.js + ky で Service WorkerからもAjaxできるようにする

2021/05/10に公開

https://zenn.dev/tak_iwamoto/articles/1a8770c09ad6993311be

nuxt/httpでも利用されている「ky」ですが、Nuxt.jsのインスタンス管理外から使ってみたい、しかもService Worker上から、という必要性があったものの、インストールと使い方で引っかかったので備忘録。

https://github.com/nuxt/http

シンプルで良さそう!

インストール

普通にkyをインストールすると、Webpackな環境ではそのままではインポートできません。

import ky from 'ky'; // だめっぽい
import ky from '@/node_modules/ky/distribution'; // いけた

Node.js向けのpolyfillとしてky-universalというものがあるようです。

https://github.com/sindresorhus/ky-universal

ky本体とReadableStreamのpolyfillもインストールする必要があります。

$ npm i ky ky-universal web-streams-polyfill
# import ky from 'ky-universal'

$ npm run dev # Nuxt起動
..
..
This dependency was not found:
* ky in ./node_modules/ky-universal/browser.js

まだエラーが出るのでライブラリを修正する必要があります。
(プルリク案件なのか自分が間違っているのかわからない……)

~/node_modules/ky-universal/browser.js
//import ky from 'ky';
import ky from '@/node_modules/ky/distribution';

export default ky;

使い方

今回はAPIを叩くのではなく、サーバ側に置いてあるリソース(機械学習用の学習済みデータセット)を読み込むために使用しました。リソースは~/staticに置いてあるため、ルート直下にアクセスすることで取得できます。

(async () => {
  const response = await ky.get(self.location.origin + '/dataset.txt'); // response.bodyがデータ本体
  const reader = await response.body.getReader().read(); // reader.valueがUint8Array
  const result = new TextDecoder('utf-8').decode(reader.value); // データの種類に応じて適宜変換
  console.log(result); // いい感じ
})()

上記のコードだけで、メインスレッドからでも、Service Worker上からでも、データセットをテキスト形式で読み込むことができました。

Service Worker上からURL指定時の注意

console.log(self.location.href);
// メインスレッドのとき:http://localhost:3000/
// Worker上のとき:http://localhost:3000/_nuxt/ml.worker.js ※worker-loader利用

自サーバ上のリソースに対して相対URLを仕掛ける場合、Worker上で動いているかどうかでhrefが変わってくるため、self.location.originからの絶対位置URL指定にするのがよさそうです。

// 以下はService Worker上からやると404になる(メインスレッドからだと問題なし)
const response = await ky.get('./dataset.txt');
// これだとどっちからでもいける
const response = await ky.get('http://localhost:3000/dataset.txt'); // 開発時のみ
const response = await ky.get(self.location.origin + '/dataset.txt');

// self.locationはWorkerの場合はWorkerLocationオブジェクトとなる

なお、node-fetchabort-controllerは特に不要のようでした。

Discussion