インスタント マルチプレイヤー Web アプリを構築、サーバーは不要
デモを試してみませんか?
trysteroアプリケーションのユーザーが暗号化され、サーバー仲介者なしで直接通信できるようにする秘密の宅配ネットワークを管理します。
ネットには、トレント トラッカー、IoT デバイス ブローカー、専門的なファイル プロトコル、ニッチなソーシャル ネットワークなど、オープンで分散型の通信チャネルが溢れています。
trysteroこれらのネットワークに便乗して、ユーザー側での努力を必要とせずに、アプリのユーザー間に安全でプライベートな p2p 接続を自動的に確立します。
ピアは ? 経由で接続できます。ビットトレント、?ノストル、? MQTT、⚡️ Supabase、Firebase、それとも ? IPFS – すべて同じ API を使用します。
trysteroピア マッチングを自動化するだけでなく、WebRTC 上にいくつかの優れた抽象化を提供します。
ここで、人々がtrystero使って何を構築しているのかを見ることができます。
trystero試してみたいだけの場合は、この説明をスキップして、すぐに使用できます。
WebRTC との直接ピアツーピア接続を確立するには、ピア情報 (SDP) を交換するためのシグナリング チャネルが必要です。通常、これには独自のマッチメイキング サーバーを実行する必要がありますが、 trysteroこれを抽象化し、ピアを接続するための複数の「サーバーレス」戦略を提供します (現在は BitTorrent、Nostr、MQTT、Supabase、Firebase、および IPFS)。
覚えておくべき重要な点は次のとおりです。
ピア検出を超えて、アプリのデータは戦略媒体に触れることはなく、ユーザー間で直接ピアツーピアおよびエンドツーエンドで暗号化されて送信されます。
?
ここで戦略を比較できます。
npm ( npm i trystero
) でインストールし、次のようにインポートできます。
import { joinRoom } from ' trystero '
それとも単純な script タグの方が良いでしょうか?最新リリースから事前に構築された JS ファイルをダウンロードし、ローカルにインポートします。
< script type =" module " >
import { joinRoom } from './ trystero -torrent.min.js'
</ script >
デフォルトでは、Nostr 戦略が使用されます。別のものを使用するには、次のようにディープインポートするだけです (バンドラーは、関連するコードのみを含めることを処理する必要があります)。
import { joinRoom } from ' trystero /mqtt' // ( trystero -mqtt.min.js with a local file)
// or
import { joinRoom } from ' trystero /torrent' // ( trystero -torrent.min.js)
// or
import { joinRoom } from ' trystero /supabase' // ( trystero -supabase.min.js)
// or
import { joinRoom } from ' trystero /firebase' // ( trystero -firebase.min.js)
// or
import { joinRoom } from ' trystero /ipfs' // ( trystero -ipfs.min.js)
次に、ID を使用してユーザーをルームに参加させます。
const config = { appId : 'san_narciso_3d' }
const room = joinRoom ( config , 'yoyodyne' )
最初の引数は、 appId
必要とする構成オブジェクトです。これはアプリにとって完全に一意の識別子である必要があります¹。 2 番目の引数はルーム ID です。
なぜ部屋なのか?ブラウザーが一度に処理できる WebRTC 接続の量は限られているため、ユーザーがグループ (またはルーム、名前空間、チャネルなど、任意の呼び方) に分割されるようにアプリを設計することをお勧めします。
¹ Firebase を使用する場合、 appId
databaseURL
である必要があり、Supabase を使用する場合、それはプロジェクト URL である必要があります。
ルームに参加しているピアをリッスンします。
room . onPeerJoin ( peerId => console . log ( ` ${ peerId } joined` ) )
部屋から退室するピアをリッスンします。
room . onPeerLeave ( peerId => console . log ( ` ${ peerId } left` ) )
オーディオ/ビデオ ストリームを送信しているピアをリッスンします。
room . onPeerStream (
( stream , peerId ) => ( peerElements [ peerId ] . video . srcObject = stream )
)
イベントの登録を解除するには、ルームから退出してください。
room . leave ( )
次のようにselfId
インポートすることで、ローカル ユーザーのピア ID にアクセスできます。
import { selfId } from ' trystero '
console . log ( `my peer ID is ${ selfId } ` )
ビデオ ストリームをピアに送信します。
room . addStream (
await navigator . mediaDevices . getUserMedia ( { audio : true , video : true } )
)
カスタム P2P アクションを送信してサブスクライブします。
const [ sendDrink , getDrink ] = room . makeAction ( 'drink' )
// buy drink for a friend
sendDrink ( { drink : 'negroni' , withIce : true } , friendId )
// buy round for the house (second argument omitted)
sendDrink ( { drink : 'mezcal' , withIce : false } )
// listen for drinks sent to you
getDrink ( ( data , peerId ) =>
console . log (
`got a ${ data . drink } with ${ data . withIce ? '' : 'out' } ice from ${ peerId } `
)
)
アクションを使用して画像などのバイナリ データを送信することもできます。
const [ sendPic , getPic ] = room . makeAction ( 'pic' )
// blobs are automatically handled, as are any form of TypedArray
canvas . toBlob ( blob => sendPic ( blob ) )
// binary data is received as raw ArrayBuffers so your handling code should
// interpret it in a way that makes sense
getPic (
( data , peerId ) => ( imgs [ peerId ] . src = URL . createObjectURL ( new Blob ( [ data ] ) ) )
)
ユーザーが自分自身に名前を付けられるようにしたいとします。
const idsToNames = { }
const [ sendName , getName ] = room . makeAction ( 'name' )
// tell other peers currently in the room our name
sendName ( 'Oedipa' )
// tell newcomers
room . onPeerJoin ( peerId => sendName ( 'Oedipa' , peerId ) )
// listen for peers naming themselves
getName ( ( name , peerId ) => ( idsToNames [ peerId ] = name ) )
room . onPeerLeave ( peerId =>
console . log ( ` ${ idsToNames [ peerId ] || 'a weird stranger' } left` )
)
アクションはスマートで、シリアル化とチャンク化をバックグラウンドで処理します。これは、非常に大きなファイルを送信でき、送信したデータはすべて同じタイプ (数値は数値として、文字列は文字列として、オブジェクトはオブジェクトとして、バイナリはバイナリとしてなど) として相手側で受信されることを意味します。 。
音声チャットルームを作成する方法の簡単な例を次に示します。
// this object can store audio instances for later
const peerAudios = { }
// get a local audio stream from the microphone
const selfStream = await navigator . mediaDevices . getUserMedia ( {
audio : true ,
video : false
} )
// send stream to peers currently in the room
room . addStream ( selfStream )
// send stream to peers who join later
room . onPeerJoin ( peerId => room . addStream ( selfStream , peerId ) )
// handle streams from other peers
room . onPeerStream ( ( stream , peerId ) => {
// create an audio instance and set the incoming stream
const audio = new Audio ( )
audio . srcObject = stream
audio . autoplay = true
// add the audio to peerAudio object if you want to address it for something
// later (volume, etc.)
peerAudios [ peerId ] = audio
} )
ビデオでも同じことを行うのは似ていますが、DOM 内のビデオ要素に受信ストリームを必ず追加してください。
const peerVideos = { }
const videoContainer = document . getElementById ( 'videos' )
room . onPeerStream ( ( stream , peerId ) => {
let video = peerVideos [ peerId ]
// if this peer hasn't sent a stream before, create a video element
if ( ! video ) {
video = document . createElement ( 'video' )
video . autoplay = true
// add video element to the DOM
videoContainer . appendChild ( video )
}
video . srcObject = stream
peerVideos [ peerId ] = video
} )
アプリがさまざまな種類のファイルの送信をサポートしており、送信される生のバイトに、どのように解釈されるべきかについてのメタデータで注釈を付けたいとします。バッファにメタデータ バイトを手動で追加する代わりに、バイナリ ペイロードの送信側アクションにメタデータ引数を渡すだけで済みます。
const [ sendFile , getFile ] = makeAction ( 'file' )
getFile ( ( data , peerId , metadata ) =>
console . log (
`got a file ( ${ metadata . name } ) from ${ peerId } with type ${ metadata . type } ` ,
data
)
)
// to send metadata, pass a third argument
// to broadcast to the whole room, set the second peer ID argument to null
sendFile ( buffer , null , { name : 'The Courierʼs Tragedy' , type : 'application/pdf' } )
アクション センダー関数は、送信完了時に解決される Promise を返します。オプションでこれを使用して、大規模な転送がいつ完了したかをユーザーに示すことができます。
await sendFile ( amplePayload )
console . log ( 'done sending to all peers' )
アクション送信側関数は、送信の進行に応じて継続的に呼び出されるオプションのコールバック関数も受け取ります。これは、大規模な転送の送信者に進行状況バーを表示するために使用できます。コールバックは、0 ~ 1 のパーセンテージ値と受信ピアの ID を使用して呼び出されます。
sendFile (
payload ,
// notice the peer target argument for any action sender can be a single peer
// ID, an array of IDs, or null (meaning send to all peers in the room)
[ peerIdA , peerIdB , peerIdC ] ,
// metadata, which can also be null if you're only interested in the
// progress handler
{ filename : 'paranoids.flac' } ,
// assuming each peer has a loading bar added to the DOM, its value is
// updated here
( percent , peerId ) => ( loadingBars [ peerId ] . value = percent )
)
同様に、次のように受信側として進行状況イベントをリッスンできます。
const [ sendFile , getFile , onFileProgress ] = room . makeAction ( 'file' )
onFileProgress ( ( percent , peerId , metadata ) =>
console . log (
` ${ percent * 100 } % done receiving ${ metadata . filename } from ${ peerId } `
)
)
すべてのメタデータは進行状況イベントとともに送信されるため、受信側ユーザーに転送が進行中であることを受信ファイルの名前とともに示すことができることに注意してください。
ピアは複数の送信を並行して送信できるため、一意の ID を送信するなど、メタデータを使用してそれらを区別することもできます。
ピアが相互に接続されると、すべての通信がエンドツーエンドで暗号化されます。最初の接続/検出プロセス中に、ピアの SDP は、選択されたピアリング戦略媒体を介して送信されます。デフォルトでは、SDP はアプリ ID とルーム ID から派生したキーを使用して暗号化され、平文のセッション データがログに表示されるのを防ぎます。これはほとんどのユースケースでは問題ありませんが、リレー戦略オペレーターはルーム ID とアプリ ID を使用してキーをリバース エンジニアリングできます。より安全なオプションは、暗号化キーの導出に使用されるアプリ構成オブジェクトでpassword
パラメーターを渡すことです。
joinRoom ( { appId : 'kinneret' , password : 'MuchoMaa$' } , 'w_a_s_t_e__v_i_p' )
これは共有秘密であり、事前に知っておく必要があり、接続するにはルーム内のすべてのピアのパスワードが一致する必要があります。ユースケースの例としては、ユーザーが外部手段を介してパスワードを知るプライベート チャット ルームが挙げられます。
trystero関数はべき等であるため、すぐに React フックとして機能します。
以下は、各ピアが自分の好きな色を他のピアと同期する簡単なコンポーネントの例です。
import { joinRoom } from ' trystero '
import { useState } from 'react'
const trystero Config = { appId : 'thurn-und-taxis' }
export default function App ( { roomId } ) {
const room = joinRoom ( trystero Config , roomId )
const [ sendColor , getColor ] = room . makeAction ( 'color' )
const [ myColor , setMyColor ] = useState ( '#c0ffee' )
const [ peerColors , setPeerColors ] = useState ( { } )
// whenever new peers join the room, send my color to them:
room . onPeerJoin ( peer => sendColor ( myColor , peer ) )
// listen for peers sending their colors and update the state accordingly:
getColor ( ( color , peer ) =>
setPeerColors ( peerColors => ( { ... peerColors , [ peer ] : color } ) )
)
const updateColor = e => {
const { value } = e . target
// when updating my own color, broadcast it to all peers:
sendColor ( value )
setMyColor ( value )
}
return (
< >
< h1 > trystero + React </ h1 >
< h2 > My color: </ h2 >
< input type = "color" value = { myColor } onChange = { updateColor } />
< h2 > Peer colors: </ h2 >
< ul >
{ Object . entries ( peerColors ) . map ( ( [ peerId , color ] ) => (
< li key = { peerId } style = { { backgroundColor : color } } >
{ peerId } : { color }
</ li >
) ) }
</ ul >
</ >
)
}
賢明な読者は、上記の例が単純で、コンポーネントのルーム ID を変更するかアンマウントするかを考慮していないことに気づくかもしれません。これらのシナリオでは、ルーム イベントのサブスクライブを適宜解除するこの単純なuseRoom()
フックを使用できます。
import { joinRoom } from ' trystero '
import { useEffect , useRef } from 'react'
export const useRoom = ( roomConfig , roomId ) => {
const roomRef = useRef ( joinRoom ( roomConfig , roomId ) )
const lastRoomIdRef = useRef ( roomId )
useEffect ( ( ) => {
if ( roomId !== lastRoomIdRef . current ) {
roomRef . current . leave ( )
roomRef . current = joinRoom ( roomConfig , roomId )
lastRoomIdRef . current = roomId
}
return ( ) => roomRef . current . leave ( )
} , [ roomConfig , roomId ] )
return roomRef . current
}
Supabase 戦略を使用するには:
appId
として設定し、 anon public
API キーをコピーして、 trystero構成のsupabaseKey
として設定します。Firebase 戦略を使用したいが、既存のプロジェクトがない場合:
databaseURL
をコピーし、 trystero設定のappId
として使用します。{
"rules" : {
".read" : false ,
".write" : false ,
"__ trystero __" : {
".read" : false ,
".write" : false ,
"$room_id" : {
".read" : true ,
".write" : true
}
}
}
}
これらのルールにより、ルームの名前空間が事前にわかっている場合にのみ、ルーム ピアのプレゼンスを読み取ることができるようになります。
joinRoom(config, roomId, [onError])
ローカル ユーザーをルームに追加すると、同じ名前空間内の他のピアが通信チャネルを開いてイベントを送信できるようになります。同じ名前空間でjoinRoom()
複数回呼び出すと、同じルーム インスタンスが返されます。
config
- 次のキーを含む構成オブジェクト:
appId
- (必須)アプリを識別する一意の文字列。 Supabase を使用する場合、これをプロジェクト URL に設定する必要があります (Supabase のセットアップ手順を参照)。 Firebase を使用している場合、これは Firebase 構成のdatabaseURL
である必要があります (Firebase 戦略を構成する別の方法については、以下のfirebaseApp
も参照してください)。
password
- (オプション)ピアリング メディアを通過する際に、AES-GCM 経由でセッションの説明を暗号化する文字列。設定されていない場合、セッションの説明はアプリ ID とルーム名から派生したキーで暗号化されます。接続するには、ルーム内のピア間でカスタム パスワードが一致する必要があります。詳細については、暗号化を参照してください。
rtcConfig
- (オプション)すべてのピア接続のカスタムRTCConfiguration
を指定します。
relayUrls
- (オプション、? BitTorrent、? Nostr、? MQTT のみ) P2P 接続のブートストラップに使用する戦略の URL のカスタム リスト。これらはそれぞれ、BitTorrent トラッカー、Nostr リレー、MQTT ブローカーになります。安全な WebSocket 接続をサポートする必要があります。
relayRedundancy
- (オプション、? BitTorrent、? Nostr、? MQTT のみ)いくつかのトレント トラッカーが失敗した場合に同時に接続するトレント トラッカーの数を指定する整数。 relayUrls
オプションを渡すと、リスト全体が使用されるため、このオプションは無視されます。
supabaseKey
- (必須、⚡️ Supabase のみ) Supabase プロジェクトのanon public
API キー。
firebaseApp
- (オプション、Firebase のみ) appId
の代わりに、すでに初期化された Firebase アプリ インスタンスを渡すことができます。通常、 trystero appId
に基づいて Firebase アプリを初期化しますが、他の場所で使用するためにすでに初期化している場合、これは失敗します。
rootPath
- (オプション、Firebase のみ) trysteroデータベースにマッチメイキング データを書き込むパスを指定する文字列 (デフォルトでは'__ trystero __'
)。これを変更すると、同じデータベースを使用して複数のアプリを実行し、名前空間の衝突を心配したくない場合に便利です。
libp2pConfig
- (オプション、? IPFS のみ)ブートストラップ用の静的ピアのリストを指定できるLibp2pOptions
。
roomId
- ルーム内の名前空間ピアおよびイベントへの文字列。
onError(details)
- (オプション)パスワードが間違っているためにルームに参加できない場合に呼び出されるコールバック関数。 details
、 appId
、 roomId
、 peerId
、およびerror
を説明する error を含むオブジェクトです。
次のメソッドを使用してオブジェクトを返します。
leave()
ルームからローカル ユーザーを削除し、ルーム イベントの登録を解除します。
getPeers()
ルーム内に存在するピアのRTCPeerConnection
のマップを返します (ローカル ユーザーは含まれません)。このオブジェクトのキーは、それぞれのピアの ID です。
addStream(stream, [targetPeers], [metadata])
メディア ストリームを他のピアにブロードキャストします。
stream
- ルーム内のピアに送信するオーディオやビデオを含むMediaStream
。
targetPeers
- (オプション)指定した場合、ストリームはターゲット ピア ID (文字列) またはピア ID のリスト (配列) にのみ送信されます。
metadata
- (オプション)ストリームとともに送信される追加のメタデータ (シリアル化可能なタイプ)。これは、複数のストリームを送信する場合に便利で、受信者がどれがどれであるかを認識します (例: Web カメラとスクリーン キャプチャ)。メタデータ引数を使用してルーム内のすべてのピアにストリームをブロードキャストする場合は、2 番目の引数としてnull
を渡します。
removeStream(stream, [targetPeers])
以前に送信したメディア ストリームの他のピアへの送信を停止します。
stream
- 送信を停止する、以前に送信されたMediaStream
。
targetPeers
- (オプション)指定した場合、ストリームはターゲット ピア ID (文字列) またはピア ID のリスト (配列) からのみ削除されます。
addTrack(track, stream, [targetPeers], [metadata])
新しいメディア トラックをストリームに追加します。
track
- 既存のストリームに追加するMediaStreamTrack
。
stream
- 新しいトラックをアタッチするターゲットMediaStream
。
targetPeers
- (オプション)指定すると、トラックはターゲット ピア ID (文字列) またはピア ID のリスト (配列) にのみ送信されます。
metadata
- (オプション)トラックとともに送信される追加のメタデータ (シリアル化可能なタイプ)。詳細については、上記のaddStream()
のmetadata
ノートを参照してください。
removeTrack(track, stream, [targetPeers])
ストリームからメディア トラックを削除します。
track
- 削除するMediaStreamTrack
。
stream
- トラックが接続されているMediaStream
。
targetPeers
- (オプション)指定した場合、トラックはターゲット ピア ID (文字列) またはピア ID のリスト (配列) からのみ削除されます。
replaceTrack(oldTrack, newTrack, stream, [targetPeers])
メディア トラックを新しいものに置き換えます。
oldTrack
- 削除するMediaStreamTrack
。
newTrack
- 添付するMediaStreamTrack
。
stream
- oldTrack
が接続されているMediaStream
。
targetPeers
- (オプション)指定すると、ターゲット ピア ID (文字列) またはピア ID のリスト (配列) のトラックのみが置き換えられます。
onPeerJoin(callback)
ピアがルームに参加したときに呼び出されるコールバック関数を登録します。複数回呼び出された場合、最後に登録されたコールバックのみが呼び出されます。
callback(peerId)
- ピアが参加するたびに実行される関数。ピアの ID で呼び出されます。例:
onPeerJoin ( peerId => console . log ( ` ${ peerId } joined` ) )
onPeerLeave(callback)
ピアがルームから退出したときに呼び出されるコールバック関数を登録します。複数回呼び出された場合、最後に登録されたコールバックのみが呼び出されます。
callback(peerId)
- ピアが離れるたびに実行される関数。ピアの ID で呼び出されます。例:
onPeerLeave ( peerId => console . log ( ` ${ peerId } left` ) )
onPeerStream(callback)
ピアがメディア ストリームを送信するときに呼び出されるコールバック関数を登録します。複数回呼び出された場合、最後に登録されたコールバックのみが呼び出されます。
callback(stream, peerId, metadata)
- ピアがメディア ストリームを送信するたびに実行される関数。ピアのストリーム、ID、およびオプションのメタデータを使用して呼び出されます (詳細については、上記のaddStream()
参照してください)。例:
onPeerStream ( ( stream , peerId ) =>
console . log ( `got stream from ${ peerId } ` , stream )
)
onPeerTrack(callback)
ピアがメディア トラックを送信するときに呼び出されるコールバック関数を登録します。複数回呼び出された場合、最後に登録されたコールバックのみが呼び出されます。
callback(track, stream, peerId, metadata)
- ピアがメディア トラックを送信するたびに実行される関数。ピアのトラック、添付されたストリーム、ID、およびオプションのメタデータを使用して呼び出されます (詳細については、上記のaddTrack()
参照してください)。例:
onPeerTrack ( ( track , stream , peerId ) =>
console . log ( `got track from ${ peerId } ` , track )
)
makeAction(actionId)
カスタム データ アクションをリッスンして送信します。
actionId
- すべてのピア間でこのアクションを一貫して登録するための文字列。3 つの関数の配列を返します。
データをピアに送信し、すべてのターゲット ピアがデータの受信を完了したときに解決される Promise を返します。
(data, [targetPeers], [metadata], [onProgress])
data
- 送信する任意の値 (プリミティブ、オブジェクト、バイナリ)。シリアル化とチャンク化は自動的に処理されます。バイナリ データ ( Blob
、 TypedArray
など) は、他のピアによって不可知論的なArrayBuffer
として受信されます。
targetPeers
- (オプション)ピア ID (文字列)、ピア ID の配列、またはnull
(ルーム内のすべてのピアに送信することを示す) のいずれか。
metadata
- (オプション)データがバイナリの場合、それを説明するオプションのメタデータ オブジェクトを送信できます (バイナリ メタデータを参照)。
onProgress
- (オプション)すべてのピアのすべてのチャンクが送信されるときに呼び出されるコールバック関数。この関数は、0 ~ 1 の値とピア ID を指定して呼び出されます。例については、「進捗状況の更新」を参照してください。
このアクションのデータを他のピアから受信したときに実行されるコールバック関数を登録します。
(data, peerId, metadata)
data
- 送信ピアによって送信された値。逆シリアル化は自動的に処理されます。つまり、数値は数値として、オブジェクトはオブジェクトとして受信されます。
peerId
- 送信ピアの ID 文字列。
metadata
- (オプション) data
がバイナリ (ファイル名など) の場合に送信者によって提供されるオプションのメタデータ オブジェクト。
ピアから部分的なデータを受信したときに実行されるコールバック関数を登録します。これを使用して、大規模なバイナリ転送を追跡できます。例については、「進捗状況の更新」を参照してください。
(percent, peerId, metadata)
percent
- 転送が完了した割合を示す 0 ~ 1 の数値。
peerId
- 送信ピアの ID 文字列。
metadata
- (オプション)送信者によって提供されるオプションのメタデータ オブジェクト。
例:
const [ sendCursor , getCursor ] = room . makeAction ( 'cursormove' )
window . addEventListener ( 'mousemove' , e => sendCursor ( [ e . clientX , e . clientY ] ) )
getCursor ( ( [ x , y ] , peerId ) => {
const peerCursor = cursorMap [ peerId ]
peerCursor . style . left = x + 'px'
peerCursor . style . top = y + 'px'
} )
ping(peerId)
ピア ID を取得し、そのピアへの往復にかかった時間をミリ秒単位で解決する Promise を返します。レイテンシーの測定に使用します。
peerId
- ターゲットピアのピア ID 文字列。例:
// log round-trip time every 2 seconds
room . onPeerJoin ( peerId =>
setInterval (
async ( ) => console . log ( `took ${ await room . ping ( peerId ) } ms` ) ,
2000
)
)
selfId
他のピアがローカル ユーザーをルーム全体でグローバルに認識できる一意の ID 文字列。
getRelaySockets()
(? BitTorrent、? Nostr、? MQTT のみ) WebSocket 接続にマップされたリレー URL キーのオブジェクトを返します。これは、リレーへのユーザーの接続状態を判断し、接続障害を処理するのに役立ちます。
例:
console . log ( trystero . getRelaySockets ( ) )
// => Object {
// "wss://tracker.webtorrent.dev": WebSocket,
// "wss://tracker.openwebtorrent.com": WebSocket
// }
getOccupants(config, roomId)
( Firebase のみ)指定された名前空間に存在するユーザー ID のリストに解決される Promise を返します。これは、ルームに参加せずにルームにいるユーザーの数を確認するのに役立ちます。
config
- 構成オブジェクトroomId
- joinRoom()
に渡す名前空間文字列。例:
console . log ( ( await trystero . getOccupants ( config , 'the_scope' ) ) . length )
// => 3
ワンタイムセットアップ¹ | バンドルサイズ² | 接続するまでの時間¶ | |
---|---|---|---|
?ノストル | なし ? | 54K | ⏱️⏱️ |
? MQTT | なし ? | 332K | ⏱️⏱️ |
?ビットトレント | なし ? | 25K ? | ⏱️⏱️ |
⚡️スーパーベース | ~5分 | 150K | ⏱️? |
ファイアベース | ~5分 | 177K | ⏱️? |
? IPFS | なし ? | 945K | ⏱️⏱️ |
¹ Firebase を除くすべての戦略では、セットアップは必要ありません。 Firebase はアカウントの設定が必要な管理された戦略です。
²ロールアップ バンドル + ターサー圧縮によって計算されます。
³ルームに参加する際のピアの相互接続の相対速度。 Firebase はほぼ瞬時に処理されますが、他の戦略はピアリング情報の交換に少し時間がかかります。
trysteroの独自の利点は、バックエンドのセットアップが不要で、ほとんどの場合に分散型インフラストラクチャを使用することです。これにより、摩擦のない実験が可能になり、単一障害点がなくなりました。潜在的な欠点の 1 つは、 trystero使用する冗長技術を使用したとしても、使用する公共インフラストラクチャが常に高可用性であることを保証するのが難しいことです。他の戦略は分散型ですが、Supabase および Firebase 戦略は、より優れた制御と SLA を備えたより管理されたアプローチであり、「運用」アプリにより適している可能性があります。
trystero使用すると、戦略間の切り替えが簡単になります。インポート行を 1 つ変更するだけで、すぐに実験できます。
import { joinRoom } from ' trystero /[torrent|nostr|mqtt|supabase|firebase|ipfs]'
trystero by Dan Motzenbecker