New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Resurrect Service Worker #7108
Resurrect Service Worker #7108
Conversation
ServiceWorkerが起動した時にメインプロセスがいるかどうかはわからず(ブラウザ起動したけどMisskey開いてないとか)、したがってpostMessageされる保証もないので、一度postMessageされたら(= service worker register時?)その結果をService Workerから扱えるLocalStorageかなんかにキャッシュしておいて、以後はそれを参照するようにしないとだめそう |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
コメントしました
盲点だった LocalStorageはService Workerで使えないので、やっぱりindexedDBで保存しておく必要がありそう |
postMessageでlocaleまるまるじゃなくて言語情報だけ渡して、その言語情報をもとにServiceWorkerがlocaleをAPI叩いてフェッチしてくる、とかでも良さそうと思った(思いつきで喋っているので実現できるかどうかは不明) |
アレそうだったっけまじか |
元サイトのデータにアクセスできないだけで、localStorage自体は使用できると思い込んでたわ |
@syuilo MDN曰く
だね |
できるからそうするほうがいいならそうするか…? |
(ちなみに、Service Workerのバージョン変更は、同じURLであっても更新を勝手に検知してくれる |
ServiceWorkerが自身が己に必要な情報をフェッチしてくる設計の方が、関心が分離されてて良さそうな気はしている |
(サーバーのバージョンが新しくなってlocaleのURLが新しくなっても、Service Workerのバージョンが古いと古いlocaleを探してしまう話 |
まあそうするにしても言語情報などをキャッシュしておく必要はあるから、やはりIndexedDBの利用は必須だなあ |
通常のクライアントからごってり実装するのではなく、Service WorkerからindexedDBに簡単に保存する感じでいいと思う… |
iを保存しておくのに複数アカウントをどうするのかという問題に気付いた |
とりあえず今回は、アカウントの問題は考えずにlangだけを考えることにする (langがidb-keyvalとlocalStorageで両方存在するのはよくなさそうだけど、boot.jsあたりをいじり始めるとキリがつかない…) |
メモ: クライアントがない(バックグラウンド)状態のService Workerの挙動について
|
localeはいちいちサーバーに取りに行かずともcacheで取得しておいてもいいかも |
適当に IndexedDB をVue→SW用データ押し付けストアとして使うだけでうまくいきそうな気がする (Vueから見ずに書き込み失敗を無視すれば Firefox のプライベートブラウザでも動くはず) |
localStorageと同じ情報をIndexedDBに保存するのはどうなのかの話か Firefoxのプライベートでも使えるようにするのは、フォールバックでlocalStorageを使うようにするようなものを作ればいいんじゃないかなと プッシュ通知のactionsの実装ではService Workerがtokenを必要とするので、accountsまわりはindexeddb(使えなければlocalStorage)に統一するようになると思われる |
やった このPRはこれでおわり |
} | ||
|
||
if (typeof ev.data === 'object') { | ||
const otype = Object.prototype.toString.call(ev.data).slice(8, -1).toLowerCase(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sliceの 8 とか -1 がマジックナンバーに見えて何やってるかイマイチ把握できないので、コメントなりあると嬉しいかも
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
やったけどこんな感じでいいかしら
yosasou |
ちょっとテストしてみるか(ローカルでservice workerのテストできたっけ) |
できるはず |
一応c2鯖でうごいてる |
src/client/init.ts
Outdated
//if (this.store.state.instance.meta.swPublickey) this.registerSw(this.store.state.instance.meta.swPublickey); | ||
if (instance.swPublickey && | ||
('serviceWorker' in navigator) && | ||
('PushManager' in window) && | ||
$i && $i.token) { | ||
navigator.serviceWorker.register(`/sw.js`); | ||
|
||
navigator.serviceWorker.ready.then(registration => { | ||
registration.active?.postMessage({ | ||
msg: 'initialize', | ||
lang, | ||
}); | ||
// SEE: https://developer.mozilla.org/en-US/docs/Web/API/PushManager/subscribe#Parameters | ||
registration.pushManager.subscribe({ | ||
userVisibleOnly: true, | ||
applicationServerKey: urlBase64ToUint8Array(instance.swPublickey) | ||
}).then(subscription => { | ||
function encode(buffer: ArrayBuffer | null) { | ||
return btoa(String.fromCharCode.apply(null, new Uint8Array(buffer))); | ||
} | ||
|
||
// Register | ||
api('sw/register', { | ||
endpoint: subscription.endpoint, | ||
auth: encode(subscription.getKey('auth')), | ||
publickey: encode(subscription.getKey('p256dh')) | ||
}); | ||
}) | ||
// When subscribe failed | ||
.catch(async (err: Error) => { | ||
// 通知が許可されていなかったとき | ||
if (err.name === 'NotAllowedError') { | ||
return; | ||
} | ||
|
||
// 違うapplicationServerKey (または gcm_sender_id)のサブスクリプションが | ||
// 既に存在していることが原因でエラーになった可能性があるので、 | ||
// そのサブスクリプションを解除しておく | ||
const subscription = await registration.pushManager.getSubscription(); | ||
if (subscription) subscription.unsubscribe(); | ||
}); | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
この辺別ファイルに切り出しても良いかも
c2鯖でテストしてみたけど通知来ないな(service workerのインスペクタにも何もエラーなどは出ない) |
うーん?ちゃんとタブ閉じて検証してみたよね…? OS・ブラウザは何でしょうか? |
yes
Windows10 / Chrome 88.0.4324.104 |
通知の許可設定はどうなってますか? |
許可してる |
まあaqzが通知受け取れているならおま環だと思うので無視してもらってOK |
うん、私は普通に受け取れているんですよね…なんでだろう… |
👍👍👍 |
@tamaina |
必要…だと思っていたけど必要ではないかも PWAとして認識されるための条件としてオフラインでも200で応答することというのがあるんだけど、キャッシュではなく適当な文字列でResponse.Response()を返せばいいことに最近ようやく気がついた |
消してみたけどまだPWAとしてインストールできそう |
いやこれは嘘 |
* Resolve misskey-dev#7106 * fix lint * fix lint * save lang in idb * fix lint * fix * cache locale file * fix lint * ✌️ * wip * fix [wip] * fix [wip] Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
* Resolve misskey-dev#7106 * fix lint * fix lint * save lang in idb * fix lint * fix * cache locale file * fix lint * ✌️ * wip * fix [wip] * fix [wip] Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
Summary
Resolve #7106
Service Workerへの情報共有を、indexedDBを使うのをやめてpostMessageで渡して変数として保持にすることにして解決した
$i.tokenも渡せるので、Service Woker系のIssueを進められるようになった