XLSX-Renderer and Comlink

これの続きです。
備忘録です。


JSONデータをPHPで作成し(PHPじゃなくてもいいんだけど。。。)、クライアント・ブラウザ側のJavaScriptでエクセルファイルを作成するまではできました。
ただ、問題なのは、取得するJSONデータが結構大きいサイズ(例えば10万件とか)になると、それはそれで厄介です。

なんせ、JSONデータをfetchするだけでそれだけで時間がかかりますし、そのデータをエクセルファイルに差し込んでエクセルファイルを作成する時にも結構な時間がかかります。
その間、「データを取得中・・・エクセルファイルを生成中・・・」とかでUIを止めてもいいのですが・・・それはイマドキのトレンドではありませんよね。

せっかくブラウザがワーカースレッドを使えるようにしてくれているので、別スレッドにそういう処理は任してしまいましょう。
そう! 我々にはグーグル様が書いてくれたComlink がある!(笑)

今回は、サンプルとして↓のように、郵便番号のデータベース(SQLite)から、リクエストに応じてJSONデータを返すPHPで書いたウェブAPIを使用し、そのデータをエクセルファイルに変換するまでを書いてみる。


まずは、ウェブAPIですが・・・これはサクッと書いてしまいましょう。
パラメータ”q”に郵便番号の先頭数文字を指定して前方一致で検索してJSONとしてレスポンスを返します。
郵便番号辞書の元になるデータは日本郵便サイトからCSVファイルが公開されているのでそれを使用しSQLiteに変換して使用しました。

次に、エクセルファイルを作成する部分のJavaScriptコードです。
以前にも書きましたが、この部分はnode.jsとnpm, babel.jsとかが必要です。この部分が全く分からなければこの先見てもワケワカンネー状態になるので、とっととブラウザを閉じてこのサイトの事は忘れてくださいm(__)m

作業ディレクトリを一個作って、以下のpackage.jsonとrenderer.jsを作成。

>> tree .
.
├── package.json
└── renderer.js

※ 2022/02/06 rendererをDedicatedWorkerGlobalScopeに追加するようにrenderer.js を若干修正しました。

で、下記を実行して renderer.pack.min.js が生成されるので、このファイルを workerスレッド内からimportScripts関数でロードします。

>> npm i
>> npm run bundle

これで準備完了です。
ここからは、実際に画面(HTML)とメインスレッドのjs、ワーカースレッドのjsを書いていきます。
例によって Web Workerを利用する際には、Comlink を使ってラクします。

HTML等はデモ画面を参照。

まずは、取得したJSONデータをExcelに差し込むための、テンプレートとなるエクセルファイルを作成します。
フツーにエクセルで作成していきます。Microsoft Officeを持っていない場合は、LibreとかオープンソースのOfficeアプリとかでも構いません。
.xlsx形式のファイルを出力できる表計算アプリであれば何でもいいと思います。

こんな感じです。テンプレート XLSXファイル

これらの書式等は、XLSX-Rendererのドキュメント参照。

次にメインスレッド側のJavaScriptコードです。
特筆すべき点はありません。見ればだいたい分かるでせう。
ワーカースレッドのやり取りに Comlink を使ってます。

このファイルをロードする際は、type属性を text/javascript 等ではなく、module にしないとなんかエラーになるみたいです。
そしてボタンのクリックハンドラを設定します。(ここだけjQueryを使用しています)

最後はワーカースレッド側のJavaScriptコードです。
Comlinkを使って、メインスレッド側に関数を公開しています。

※ 2022/02/06 若干修正

このファイル内で、上記で準備した renderer.pack.min.js をロードします。


上記デモページ


たぶんこの程度の処理なら、わざわざワーカースレッドを起こさなくても、いいかとも思います。実際問題、複雑になるだけですし。
メインスレッドはUI専用にして、雑多な処理を全部 workerスレッドに投げるようにすれば、ちょっとハッピーになれる・・・(かもしれない)。

SharedWorkerとかも興味があるんだけど、スマートフォンであまり対応していないんだよね。やっぱバッテリーの電気を食うからなんだろうか・・・。