2024.10.21
お互い疑心暗鬼になりがちな、経営企画と事業部の壁 組織に「分断」が生まれる要因と打開策
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.11.13
週3日働いて年収2,000万稼ぐ元印刷屋のおじさん 好きなことだけして楽に稼ぐ3つのパターン
2024.11.21
40代〜50代の管理職が「部下を承認する」のに苦戦するわけ 職場での「傷つき」をこじらせた世代に必要なこと
2024.11.20
成果が目立つ「攻めのタイプ」ばかり採用しがちな職場 「優秀な人材」を求める人がスルーしているもの
2024.11.20
「元エースの管理職」が若手営業を育てる時に陥りがちな罠 順調なチーム・苦戦するチームの違いから見る、育成のポイント
2024.11.11
自分の「本質的な才能」が見つかる一番簡単な質問 他者から「すごい」と思われても意外と気づかないのが才能
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.11.18
20名の会社でGoogleの採用を真似するのはもったいない 人手不足の時代における「脱能力主義」のヒント
2024.11.19
がんばっているのに伸び悩む営業・成果を出す営業の違い 『無敗営業』著者が教える、つい陥りがちな「思い込み」の罠
2024.11.13
“退職者が出た時の会社の対応”を従業員は見ている 離職防止策の前に見つめ直したい、部下との向き合い方
2024.11.15
好きなことで起業、赤字を膨らませても引くに引けない理由 倒産リスクが一気に高まる、起業でありがちな失敗