🍦
Compression Streams API に置き換えた
まとめ
- 自社製品のブラウザ向け SDK で Compression Stream API を利用するようにした
- もともとは fflate を使っていた
- fflate が唯一の依存ライブラリだったため、依存を 0 にすることができた
切り替え
自社製品のブラウザ向け SDK ではリアルタイムにメッセージをやりとりする仕組みで、その際にメッセージを圧縮して送受信する仕組みをデフォルトで用意していました。
これはやりとりするメッセージが JSON が多いことから、deflate を利用することで少しでもパケットサイズを下げる事ができるためです。実際、統計情報とかはかなりの量があるのですが似たようなデータが多いため、圧縮率が高いです。
もともとは fflate を利用していましたが、最近 Compression Streams API が全てのブラウザで利用できるようになったため、切り替えました。依存性を減らすのはとても大事です。
fflate では同期 API があり、それを利用していましたが、Compression Streams API は非同期な API になるため、思った以上に影響範囲が大きかったです。
使い方
特にこった利用はしていません。 Uint8Array を受け取って ArrayBuffer を返すだけです。
自社製品のリアルタイムメッセージは RTCDataChannel を利用しているため、そのまま渡せます。
export const compressMessage = async (binaryMessage: Uint8Array): Promise<ArrayBuffer> => {
const readableStream = new Blob([binaryMessage]).stream()
const compressedStream = readableStream.pipeThrough(new CompressionStream('deflate'))
return await new Response(compressedStream).arrayBuffer()
}
export const decompressMessage = async (binaryMessage: Uint8Array): Promise<ArrayBuffer> => {
const readableStream = new Blob([binaryMessage]).stream()
const decompressedStream = readableStream.pipeThrough(new DecompressionStream('deflate'))
return await new Response(decompressedStream).arrayBuffer()
}
decompressMessage は ArrayBuffer を受け取って Uint8Array を返すでもいい気はしますが、困るまではこのままで行きます。
参考
- Compression Streams API - Web APIs | MDN
- Blob: stream() method - Web APIs | MDN
- ReadableStream: pipeThrough() method - Web APIs | MDN
- Compression and decompression in the browser with the Compression Streams API | Blog | Chrome for Developers
- Compression Streams are now supported on all browsers | Blog | web.dev
Discussion