2024.12.19
システムの穴を運用でカバーしようとしてミス多発… バグが大量発生、決算が合わない状態から業務効率化を実現するまで
ServiceWorker Side XXX(全1記事)
リンクをコピー
記事をブックマーク
mizchi氏(以下、mizchi):では「ServiceWorker Side XXX」ということで発表させていただきます。mizchiです。よろしくお願いします。
(会場拍手)
ちょっと自己紹介とかはする気ないんですけど、最近本を書いたので、その紹介だけさせてください。
『WEB+DB PRESS Vol.106』。最近、仮想DOM芸人みたいになってるんですけど、書いたのでよろしくお願いします。
最近趣味でnedi.appというエディタを作っていて。これはブラウザで独立して動くエディタで、Gitが動くんですけど、全部IndexedDBで動いています。
いろいろブラウザで完結してGitクローンからプッシュまでいけるというもので、Patreonでちょっとお金を集めたら月2万円ぐらいになってます。
これを作っててちょっといろいろ発展があって。開発環境のためにServiceWorkerをいろいろ酷使して、いろいろできそうだけど、いろいろできなかったという話をします。
ServiceWorkerって、今はこういうステータスなんです。
Opera Miniのことはみなさんたぶんどうでもいいと思っているので、一番左のIE11ですよね。これさえ無視すればもう動きます。ほぼ動きます。
実際使ったことある人?
(会場挙手)
仕事で使ったことある人?
(会場挙手)
まぁ、意外といる感じですね。
ServiceWorkerとはなにかというと、ただのすごいローカルプロキシなんですよね。
クライアントがなぜかクライアント内でクライアントサーバモデルを取れるという。これは一番上が呼び出す例で、下がfetchを掴んでなにかログを吐くってだけの例です。
ServiceWorkerは開発者向けにはもう使ってOKだと思っています。
ただ、一般向けには2020年ぐらいにWindows 7が終わると、Windows 8……まぁWindows 10はEdgeを積んでいるので一応使えると言えるようになるので、ビジネス向けにはWindows 8も見ないといけないから2023年ぐらいなんですけど、今から作り始めるアプリはどうせリリースが2020に近い時期なので、もうやっていいと思います。
ServiceWorkerにはいろいろな使い方はあるんですけど、2つ、僕が勝手に名前をつけたんですが、透過的なServiceWorkerと積極的なServiceWorkerの2つがあると思っています。
一番上のやつがよくPWAとかで使われるやつですよね。既存の振る舞いを拡張する。だから、キャッシュ構築したり、投機的先読みしたり、消極的にオフライン化するという感じです。
例えば、これは『dev.to』の記事引っ張ってきたんですが、マウスを乗せるだけでfrom ServiceWorkerとなって、裏側で引っ張ってきている。
投機的にキャッシュをためています。いろいろ先読みしたりして、裏側にキャッシュためておくみたいな。
あと、Google製のWorkboxというプラグインがあって、これがすごく便利です。
一応webpackのworkbox-webpack-plugin突っ込むだけでそれっぽくキャッシュレイヤーが挟まってくるので、すごく便利ですね。
これにWorkbox Strategyという概念があります。
Workboxではどういうキャッシュパターンがあるか、いろいろキャッシュパターンを選べるんですね。
1つがCacheFirstといって、とりあえずキャッシュ見にいってダメだったらネットワークから返すよとか。
これはおもしろいですね。StaleWhileRevalidate。
とりあえずいったんキャッシュを返しておくんだけど、裏側でネットワークのデータを返して裏でアップデートしておく。次見たら更新するというやつです。
表向き透過なだけでもいろんなキャッシュパターンがあって。全部トレードオフがあって、わからないと嵌まるので気をつけてください。
さっきも言ったように、今すぐ使えます。レガシー環境では振る舞いが透過なので単に無視される。使えるブラウザではすごい賢くなる。プログレッシブなんですね。Progressive Web AppsのProgressive。
ただ、これにはちょっと弱点があると僕は思っています。ServiceWorkerって、その他リソースは並列で初期化されます。sw.jsというよくServiceWorkerで名前つけられるやつと、なにかほかのアセットは実は並列で読み込まれるので、どこからキャッシュされるか実は自明じゃないんです。
ちょっと簡単な図を作りました。
sw.jsがreadyになるタイミングとfoo.jsとbar.jsを読んだ段階で、foo.jsがServiceWorker Readyになる前にキャッシュが返ってしまうと、これServiceWorker通らずに返ってきてしまいます。
ServiceWorker、たぶん普通に使うと全部こうなります。だから、ServiceWorker使う人はだいたい3回リロードするんですけど。1回目でServiceWorker変えて、2回目でキャッシュ捨てて有効化して、3回目で保証された状態で見るみたいな、すごいだるい感じになります。
これは対策のしようはあります。例えば、コメントアウトされているのが本来のscript src="./main.js"だったら、開発環境だけではこのように書き換えてしまう。
navigator.serviceWorkerをregisterして、readyして、終わったらimportする。dynamic importですね。開発環境だけこうすればいいので、本番ではdeleteして上のやつを読むイメージです。
ほかにも、ServiceWorkerが更新するのも問題になるので、裏側でsetIntervalで、これはregistrationというオブジェクトが入るんですけど、registrationを毎秒更新する。
更新があったら、このcontrollerchangeが来るので、windowをreloadして無理やり入れ替える、みたいなことができなくはないです。
ただ、現実としてベストプラクティスとかはとくになくて。これらは僕が勝手にやっているだけで、ちょっと時代が早いという感じですね。よく壊れます。ポートが壊れたり、serviceWorker.readyが来なくなったりします。だから、chrome://serviceworker-internalsという開発者ツールで chromeの内部状態、内部のオブジェクトを無理やり見て破壊したりします。
ここまでが透過的なんですけど、積極的PWAという概念があると思っていて。「それってServiceWorkerじゃないとそもそも動かない機能も、たくさん使ったらなんでもできるじゃん。だってただのクライアントサーバモデルのローカルプロキシでしょ?」ということですね。
この弱点はすごく明確で、モダンブラウザでしか動かないということと、ServiceWorkerが初期化されていないとなにもかも見れないので、SEOは完全に壊滅します。
ただ、使い道はあると思っていて。例えばサーバサイドで、今回webpack疲れというのが話あったじゃないですか。webpackをインストールせずにBabelとかTypeScriptをサーバサイドでコンパイルしたりとか、Express serverをそのままServiceWorkerに放り込んじゃってそこで動かすとか、できると思います。
例えばServiceWorkerインストール後に、これは全部壊れるのでやっちゃいけないコードなんですけど、fetchですべてのオブジェクトが「event.respondWith(new Response("console.log('hello world')"))」ってやると、index.htmlですらこれになるので、2回目のリロードから壊れるのですが、まぁHello Worldにできます。
あと、これはBabelでawait fetchでevent.requestを、とりあえずサーバサイドに取りにいってオリジナルソースを取ってきて、それをbabel.transformで変換して返すということができますね。
「だったらServiceWorkerでWebpackのエミュレーションすればいいんじゃないかな?」ってちょっと思って。なんでかというと、WebpackってES Modulesのエミュレータ+αなんだけど、でも、プラスαのところがいま重点にされてしまっています。
例えば、JSXとか絶対に将来にわたってサポートされない……まぁほぼサポートされないはずなので、なんだかんだでそれに近い機能が必要と考えると、将来的にも捨てられない可能性が高いんだったら、ServiceWorkerでWebpackをエミュレートすればいいんじゃないか? やってみました。こういうモジュールを作ったので……ええと、見ておいてください。
(会場笑)
先にデモしますが、これが動いているやつです。
ネットワークがどうなっているかというとjspm.ioというCDNがあって、そこからすべてReactのソースをその場で全部構築して。これReact Reduxが動いています。Babelの変換もこの場でやっています。
例えばこういうコードが動いています。
これはなにかというと、import React 、ReactDOM、App "./components/App"、ReactDOM.render。
これはWeb標準では動かないんですけど、これを無理やり動くようにするためには、まずはBabelでコンパイルしてnpmのモジュールをCDNの、このモジュールパスを書き換えたCDNに指し直す。拡張子がさらにApp.jsみたいに省略されてるのを復元します。これ「.js」「 .ts」「/index」とか全部探索して取れたやつを返してるんですけど。あとは、外部モジュールの相対パスの解決をしたり。
ES Modulesのimportを通る際はServiceWorker.onfetchという機構を通って変換されるので、それを変換できるというやつです。外部ライブラリのコードはバージョンごとに変わらないはずなので、それをServiceWorkerでキャッシュしてしまえばいいと。
やってみました。そして、動いた。React Reduxまで動いたんですけど、実際にはいろいろ問題はあって。
これはnpmモジュールのCommonJSからES Modulesに無理やり変換してる。通常の逆をしないといけないんですね。
webpackで、npmのモジュールはCommonJSなんですけど、CommonJSをES Modulesに再変換しないといけないという処理をやっているんですが、やっぱり手がかりが少なくて、しかも可逆じゃないので、やってみたけどできなかった。
じゃあES Modulesのソースを直接参照できればいいじゃんと思ったんだけど、そもそもES Modulesのソースをそのまま公開してくれているライブラリなんて少数で、あんまりダメ。できそうにない。あと、そもそも今回使ったCDN、jspm.ioというCDNが頻繁に落ちているという。Jspm.ioはnpmのモジュールをESMに変換してくれているというやつですね。
上のコードは動くんですけど、下のコードが動かなくて。
module.exportsをESMのexport defaultとして返してくれるんですけど、それ以外のエクスポートされたオブジェクトは取れないということになっちゃいました。
なので、可逆なコンパイラを自分で書くしかないなと思ってるんですけど。本当に使いたければ。
みんながrollupを使えばES Modulesも提供することになるので動くんじゃないですかね。
あと、ほかにもいろいろできると思っていて。例えばExpressのServiceWorker。
これはモックサーバで使えると思っていて、一部のルーティング、まぁ、モックを作るのにほしいのはルーティング処理で。APIエンドポイントだけモックして、なにかJSON、適当なオブジェクトをモックサーバで返すとか。
あと、そもそもサーバでServiceWorker動かすみたいな。
これはなんとなぜかCloudflareが実装しているんですね。Cloudflare Workersといって、CDNでServiceWorkerを実装して、それを返す。
これは公式のコードで、ServiceWorkerのあのfetchでrespondWith(fetchAndApply)みたいな感じ。
これはなんでServiceWorkerなんだろうって、いまいちよくわからないです。
あとはServiceWorkerでServer Side Renderingする。
もうサーバなのかなんだかよくわからないですけど。
(会場笑)
まぁ、できます。ServiceWorkerでindex.htmlを構築して返す……これSEOにはなんの役にも立たないんですけど、First Meaningful Paintを最適化したければ、サーバサイドの中でReactDOM.renderToStringして、initialStateもembedして実行しちゃえば動きます。
ある程度いろいろ考えてみたんですけど、いろいろ変えたら開発ツールには使える。現状はまだ早いので、みなさんがんばってこれ開拓してください。僕はちょっと疲れました。
(会場笑)
あとはある種の開発者ツール。クライアントでBabelを動かす必要があるような開発者ツールとか、そういうときにServiceWorker Side Babelみたいものが便利かなという気がします。
まとめは、IEが死んだあとに動的ローダーとして使えるので。本当はIEのためにこれを利用したいのですが、IEじゃ動かないんですね。なので、デッドロックしてるんですけど、まぁIEは死ぬんで忘れましょう。
今のうちに経験値貯めておけば使えるように、2020年ぐらいにちょっと使えると思います。以上、お疲れ様でした。
(会場拍手)
関連タグ:
2024.12.12
会議で発言しやすくなる「心理的安全性」を高めるには ファシリテーションがうまい人の3つの条件
2024.12.19
12万通りの「資格の組み合わせ」の中で厳選された60の項目 532の資格を持つ林雄次氏の新刊『資格のかけ算』の見所
2024.12.16
32歳で成績最下位から1年でトップ営業になれた理由 売るテクニックよりも大事な「あり方」
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.12.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
2024.12.13
ファシリテーターは「しゃべらないほうがいい」理由 入山章栄氏が語る、心理的安全性の高い場を作るポイント
PR | 2024.12.20
モンスター化したExcelが、ある日突然崩壊 昭和のガス工事会社を生まれ変わらせた、起死回生のノーコード活用術
2024.12.18
「社長以外みんな儲かる給与設計」にした理由 経営者たちが語る、優秀な人材集め・会社を発展させるためのヒント
2024.12.12
今までとこれからで、エンジニアに求められる「スキル」の違い AI時代のエンジニアの未来と生存戦略のカギとは
PR | 2024.11.26
なぜ電話営業はなくならない?その要因は「属人化」 通話内容をデータ化するZoomのクラウドサービス活用術
Climbers Startup JAPAN EXPO 2024 - 秋 -
2024.11.20 - 2024.11.21
『主体的なキャリア形成』を考える~資格のかけ算について〜
2024.12.07 - 2024.12.07
Startup CTO of the year 2024
2024.11.19 - 2024.11.19
社員の力を引き出す経営戦略〜ひとり一人が自ら成長する組織づくり〜
2024.11.20 - 2024.11.20
「確率思考」で未来を見通す 事業を成功に導く意思決定 ~エビデンス・ベースド・マーケティング思考の調査分析で事業に有効な予測手法とは~
2024.11.05 - 2024.11.05