Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Web workerを使ってUXを向上させようとした話
Search
kurisaki kazuma
September 26, 2023
1
400
Web workerを使ってUXを向上させようとした話
We Are JavaScripters! @42nd で発表した資料です。
WeJs
https://wajs.connpass.com/event/293440/
kurisaki kazuma
September 26, 2023
Tweet
Share
More Decks by kurisaki kazuma
See All by kurisaki kazuma
新規開発と並走したリファクタリング戦略.
kult0922
0
10
マインクラフトのコマンド圧縮の効率化を考えたら、40年前の論文のアルゴリズムを実装することになった話
kult0922
1
120
Next13 動的クエリ、 Server component で実装するか?Client component で実装するか?
kult0922
0
200
Featured
See All Featured
Git: the NoSQL Database
bkeepers
PRO
427
64k
jQuery: Nuts, Bolts and Bling
dougneiner
63
7.6k
Imperfection Machines: The Place of Print at Facebook
scottboms
267
13k
Thoughts on Productivity
jonyablonski
69
4.5k
Building Adaptive Systems
keathley
40
2.4k
Designing for Performance
lara
604
68k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
174
51k
A designer walks into a library…
pauljervisheath
205
24k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
9
440
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5.2k
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
Transcript
Web worker を使って UX を向上させようとした話 1
自己紹介 栗崎一真 フロントエンドエンジニア 2021 卒 楽天グループ株式会社 AI SHIFT (サイバーエージェント) X:
@KK_sep_TT GitHub: @kult0922 趣味 個人開発 旅行 ポーカー 2
はじめに 写真からマインクラフトのドット絵に変換するサービスを開発しています https://www.minecraft-dot.pictures 3
UX 改善したいところ 変換中に画面が固まらないようにしたい JS で画像処理を行っているので画面をロックしてしまう 変換中はローディングのアニメーションを出したい あったら嬉しい機能 変換の進捗を表示したい 4
なぜ画面がロックされてしまうのか JS は画面の処理をメインスレッドで行う メインスレッドで重い処理を行うと処理中は画面処理にリソースを使えない 5
そこで Web worker を使う Web worker とは メインスレッドとは独立して JS をバックグラウンドで実行できる
Web API メインスレッドのパフォーマンスに影響を与えず、時間のかかる処理ができる。 メインスレッドとは別なので UI をロックしない 6
Worker の使い方 worker を呼び出す側 worker = new Worker("worker.js"); // worker
から結果を受け取る worker.onmessage = function (event) { console.log("Received: ", event.data); }; worker.postMessage(10); // worker に 10 を引数で渡して実行 worker.js self.addEventListener("message", (e) => { const result = e.data * e.data; postMessage(result); }); 7
どこを Worker に切り出すか 時間の掛かっている処理を worker 内で行う 設計図からドット画像を構築するろころで時間がかかっていた 8
作成した Worker const constructImageFromBlueprint = (blueprint: Array<Array<string>>) => { //
設計図からドット画像を構築する処理 ... return result; }; self.addEventListener("message", (e) => { const result = constructImageFromBlueprint(e.data.blueprint); self.postMessage(result); }); 9
カスタムフックで worker の状態を管理 export function useWorker() { const [loading, setLoading]
= useState(true); const run = ( ) => { setLoading(true); const worker = new Worker( new URL("./worker", import.meta.url) ); worker.onmessage = function (e) { // worker 処理完了 setLoading(false); ... }; worker.postMessage({ blueprint, blockImageDataDict }); }; return { loading, run }; } 10
ここまで 画面のロックを防ぎたい ローディングを表示したい 進捗を知りたい 11
worker 側から進捗を伝える worker とメインスレッドの共有方法は基本的には message だけ 進捗も結果と同様 message として送る type
プロパティで進捗地なのか結果なのかを判定 const constructImageFromBlueprint = (blueprint: Array<Array<string>>) => { for (let i = 0; i < rows; i++) { if (i % step === 0) { progress += stepNum; self.postMessage({ type: "loading", payload: progress, }); } ... } self.postMessage({ type: "complete", payload: result, }); }; 12
カスタムフックも進捗を受け取るように修正 export function useImageGeneratorWorker() { const [progress, setProgress] = useState(0);
// 進捗 const [loading, setLoading] = useState(true); const run = (blueprint: string[][]) => { setLoading(true); const worker = new Worker( new URL("../worker/imageGeneratorWorker", import.meta.url) ); worker.onmessage = function (e) { if (e.data.type == "loading") { setProgress(e.data.payload); // <- 進捗を受け取る return; } setLoading(false); }; worker.postMessage({ blueprint, blockImageDataDict }); }; return { progress, loading, run }; // <- 進捗も返す } 13
結果 https://www.minecraft-dot.pictures 14
requestAnimationFrame との比較 同じようなことは requestAnimationFrame をつかってもできる。 worker マルチスレッドなので環境によってはパフォーマンスがいい worker ファイルを作成して message
でメインスレッドとやり取り message のやり取りはコピーなので大きいデータのやり取りでパフォーマンスが落ちる 可能性がある reauestnimationFrame シングルスレッドですべての処理を行う 重い処理を関数に分割して再帰的に実行 15
まとめ Web worker を使用することでメインスレッドをロックせずに重い処理を実行 進捗も message で送ることでプログレスバーを実装 16
17