Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Web workerを使ってUXを向上させようとした話
Search
kurisaki kazuma
September 26, 2023
1
460
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
17
マインクラフトのコマンド圧縮の効率化を考えたら、40年前の論文のアルゴリズムを実装することになった話
kult0922
1
180
Next13 動的クエリ、 Server component で実装するか?Client component で実装するか?
kult0922
0
220
Featured
See All Featured
Six Lessons from altMBA
skipperchong
29
4.1k
Context Engineering - Making Every Token Count
addyosmani
9
500
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
48
9.8k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
970
The Cult of Friendly URLs
andyhume
79
6.7k
Practical Orchestrator
shlominoach
190
11k
Imperfection Machines: The Place of Print at Facebook
scottboms
269
13k
Why You Should Never Use an ORM
jnunemaker
PRO
61
9.6k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
How GitHub (no longer) Works
holman
316
140k
GitHub's CSS Performance
jonrohan
1032
470k
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