SharedArrayBufferを使うための環境設定など

何かとSharedArrayBufferを使うことが多いです。

Shared Array Bufferとは、ブラウザ上でマルチスレッドを行う際にメモリ上にデータを載せてやりとりする時に使います。

自分は、AudioWorkletとかWasm、Web Worker周りで使うことがあります。

Scrollingというブラウザ上でスクラッチができるWebサイトを作った際には、Audio Workletを使用してカスタムのWavプレイヤーを作成したときにShared Array Bufferを使用しました。

(Audio Workletはメインのレンダリングスレッドに影響を与えないように、別スレッドで実行されます)

scrolling.73ch.work

ただその性質上、脆弱性となりやすいため、セキュリティが厳しめでAPIを使用するためにいくつか設定しなければ使えません。この辺もSpectreが見つかったことによるものだと思うと意外に最近ですし、ニュースで見たようなことが現実に影響してるなと思うと共に、セキュリティ意識の重要性を感じます。

今回は、Shared Array Bufferの使い方は省いて、Shared Array Bufferを使うための一種の環境設定について書いておきたいと思います。

本記事の内容については以下の記事にも一部書いてあり、また使用方法も書かれていたりしてわかりやすいです。

note.affi-sapo-sv.com

やらなければならないこと

  • cross origin isolationを行う
  • (https化を行う)

Cross Origin Isolation

Cross Origin Isolationをするためには、COOP(Cross Origin Opener Policy)とCOEP(Cross Origin Embedder Policy)、CORP(Cross Origin Resource Policy)を設定する必要があります。

基本的には、コンテキストを分離することをCOOPで宣言して、各リソース(img, js...)に対してCORPを設定し、最後に全てのドキュメント(HTML)にCOEPを設定します。

ブラウザからは以下でクロスオリジン分離ができているかを確認することができます。

window.crossOriginIsolated

Cross Origin IsolationやCOOP、COEPについては以下の記事が詳しいです。 web.dev

なお、お気づきの方もいるかもしれませんがCOEPは伝染するので、一つのドキュメントでCOOPやCOEPCOEPを設定する必要があるとiframeなどを通して関連する全てのドキュメントに設定する必要があるため、とても大変です。(つまり、全てのCORSリソースに対してCORPを設定する必要が出てきます。)

HTTPS化

localhostで開発を行うだけならいいのですが、モバイルでデバッグする時などLAN内で通信した場合には当たり前のようにHTTPSが求められます。 ローカルでオレオレ認証局を立ててHTTPS化するだけで済むならいいのですが、基本的にこの辺の機能に関してはちゃんとして認証チェーンに乗ったちゃんとしたHTTPS化が求められます。

ローカル開発

ローカルで開発したい場合、2通りのやり方があります。

ChromeのオプションでShared Array Bufferを有効化する

これが一番シンプルかもしれません。

Chromeコマンドラインから起動し、オプションとして以下を設定する方法です。

--enable-features=SharedArrayBuffer

自分は、Chrome自体は開発中の調べ物に使用するので、Canaryにこのフラグをつけて起動しています。

"/Applications/Google\\ Chrome\\ Canary.app/Contents/MacOS/Google\\ Chrome\\ Canary --enable-features=SharedArrayBuffer"

しかし、この方法はおそらくChromeでしか使えない(Safariなどに同様のオプションあるのか不明)ですし、モバイル端末でPCに立てたサーバーを見に行く際などにとても不便です(自分はこのケースがとても多い)

devServerでもヘッダーを使用する

まあ、基本的にHTTP Headerを付けるだけではあるので、そこまで難しくないかと思います。 以下のヘッダをつけてあげれば大丈夫です。

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

もし、そのサイトで出てきたCORSリソースなどは以下のヘッダをつけてあげると良いです。

Cross-Origin-Resource-Policy: cross-origin

viteを使用する場合

vite-plugin-cross-origin-isolationを使用すると楽に行けます github.com

HTTPS化

これは、ngrokが早いです。

ngrok.com

デプロイ

基本的にローカルと変わらないです。

静的サイトホスティング系のサービスだと、Netrifyは昔やった時に行けなかったイメージがあります。

Vercelだとできたので、以降Vercelを使用するようにしています。

vercel.com

Safari対応

はい、厄介です。ここでもか、と。

基本的に、上記の設定をすれば使えるはずなのですが、Safariはややこしい問題が起きます。

症状としては、1回目見た時にはうまく行くのですが、2回目以降アクセスするとうまくいかなくなります。

いや、これはどういうことなんだと思っていたのですが、以下のブログに行き当たりました。

predr.ag

記事をざっと要約すると、この症状はSafariのWebのキャッシュ周りの実装が悪さをしています。

キャッシュがヒットした場合に、CORPなどのヘッダを返した時のように振る舞わないというのが問題になります。

細かい部分は、上記のブログにお任せするとして、いかに簡単に対応を示します。

これもHTTP HeaderでCacheをしないように設定すればよく以下のヘッダを設定します。

Cache-Control: no-store

まとめ

以上になります。とても厄介でなんだかんだ調べるのにとても時間がかかっていたりするのですが、対応自体は意外にシンプルだったりしたり、、、

ただ、結構理解するためにはWebに関する細かい知識が必要だったりするので、調べつつなかなか勉強になりますね。

本記事がどなたかの役に立てば幸いです。