- 2024/3/15
- https://repro-tech.connpass.com/event/311742/
- ブラウザAPIの話を聞けるのは珍しいので面白かったです
- Service Worker static routing APIが名前だけ知ってて気になってたので詳細聞けたのがよかったです
No more parser-inserted js
- sugiさん
- https://docs.google.com/presentation/d/1jGaUfP5-BVJRKTkxnsIoYRD_0I3ua4mV0LXi59O51PQ/edit?usp=drivesdk
script要素
- 標準は同期実行 & parser-inserted mode
- DLと実行待ちでHTMLパーサが停止する
- これが標準なのは互換性のため
- JavaScript1.0(1996)
- document.write
- 今は警告出るしもう使わない
- JavaScript1.0
- ブラウザのすべてをスクリプトで制御
HTMLパーサとJS実行
- parser-insertedな実行
- HTMLだけなら普通のパース処理
- 順番に処理してく
- JSが入るとややこしくなる
- JSでHTML入力ストリームにインサートできる
- JSでDOMツリーを改変できる
- 当然かなり遅い
- HTMLだけなら普通のパース処理
- 今はもうquerySelectorがあれば十分
- DOM APIがあればパースとめて処理実行する必要ない
- それを実現するのがdeferとasync
defer/asyncの話
- defer
- ダウンロードは並行
- 入力ストリームの終端で実行
- document.writeは虫
- async
- ダウンロードは並行
- パーサを止めて実行
- document.writeは虫
document.write再考
document.write
- 文字列で渡されたHTMLをHTMLに追加する
- 壊れてても入れられる
いいところ
悪いところ
- レンダリングプロセスに介入してしまう
- 同期的でブロックされる
- 実行タイミングがずれるとページを壊す
何が問題化
- 適切に使えば問題ないがそれが難しい
- 文字列渡すので何でも実行されてしまう
document.writeへの介入
- chromeは介入して止める
- scriptが実行されない
- ただし介入するのはいろんな条件を満たした時
Render Blocking
- 特定の要素にたどり着くまでブロッキングする
- レイアウトシフトを防ぐのが目的
- ABテストで画面の表示が確定するまで止めるとか
エディタ付きのReact開発環境をブラウザだけで実装した話
- steelydylanさん
ブラウザエディタ
- https://mosya.dev/react
- StackBlitzのブラウザでnode動かす製品とかあるが有料なので自分で作った
- lintエラーとか型情報とかちゃんと表示される
- Biomeのwasm webをブラウザで動かせる
- workerで動かさないと重すぎる
- ComLinkが便利
プレビュー環境
- SWを活用
- 通信に介入するのを利用した
- 必要なファイルを通信しにいってSWでァイルを返す
- 全部mjs化して返して解決させてる
- reactなどのライブラリはimportmapで対応
- SWでHonoを動かしてる
- tsは@swc/wasm-webでトランスパイル
採点機能
- ブラウザでtesting-libraryを動かしてる
- jest-liteで実行
Memory leaks in Web Application
メモリ管理
- アプリの変化
- SPで滞在時間長期化JSの肥大化
- ヒープを圧迫すると最悪タブクラッシュ
- なぜリークするか
- GC言語なのでメモリは自動管理
- 到達可能だけど不要なオブジェクトがリークしてるオブジェクト
- windowから参照されてる
- listener
- 頻出パターン
- https://arxiv.org/abs/2308.08144
- RxJSのUnsubscribedSubscription
どうやって特定する
- Memory heap snapshot diffing
- snapshotをn回とって+nなオブジェクトが怪しい
- Retainer treeを確認
- 参照元を確認できる
- 3snapshot
- 2回だとキャッシュとか意図的に残ってるかも
- ノイズが多くて大変
自動化
- fuite
- puppeteer使ってる
- MemLab
- meta製
- BLeak
- Proxy使ってJS書き換えて
- LeakPair
- ASTで解析してリークしやすいパターンを見つけてパッチあてる
モニタリング
- フィールドデータが貴重
- 実際のユーザがどれだけメモリ使ってるか
Service Worker static routing API
- sisidovskiさん
- https://docs.google.com/presentation/d/1aw8KYpEC0bad9m2CTwapiQOpTDQVVRaibm_C9Vsms0w/edit?usp=drivesdk
SorviceWorker
- fetchをproxyするがその時には起動済みでないといけない
- SWの起動はnavigationにクリティカル
- Androidだとp95で500ms
- cold状態からの起動だとp95で940ms
- 30%くらいでこっちの挙動になる
- SWが介入しなかった時のコストも無駄がある
- SWがなにもせずブラウザから通信を改めてするので
- navigationPreloadを使うとnavigationと起動を並行できる
- とはいってもswの方が時間かかると待たされて遅い
SorviceWorkerのコスト改善
- いらない時は動かさない
- Static Routing API
- どういうリソースにどう介入させるのかを宣言的に指定する
event.addRoutes
に定義する- confition
- URLPatternやmethodなどの指定
- source
- networkなのかcacheなのかなど
- or
- pngかjpgならchacheからといった使い方
Use case
- navigationはキャッシュしてないとか
- formのPOSTはキャッシュしてないとか
- サブリソースはキャッシュにあればキャッシュがいいとか
dev tools
- networkタブでserviceworker routerと出るようになる
- 指定した定義も確認できる