The WebTransport Polyfill is a library that allows you to use the WebTransport API in browsers that do not support it natively by fallback to WebSocket.
WebTransport is a web API that uses the HTTP/3 protocol as a bi-directional transport. It's intended for two-way communication between a web client and an HTTP/3 server. It supports sending data both unreliably via its datagram APIs, and reliably via its streams APIs.
WebTransport enables low-latency, high-throughput communication between clients and servers, which is useful for applications such as SaaS with real-time collaboration feature, gaming, live streaming, video conferencing, and more.
Try it out The best way to experiment with WebTransport is to start up a compatible HTTP/3 server. You can then use this page with a basic JavaScript client to try out client/server communications.
Additionally, a community-maintained echo server is available at webtransport.day.
Link: https://web.dev/webtransport#try-it-out
However, WebTransport is not widely supported by browsers yet:
Link: https://caniuse.com/?search=webtransport
Frontend developers have to spend time and effort between high performance networking and browser compatibility. This polyfill project allows developers to use the WebTransport API in browsers that do not support it natively by providing a fallback transport mechanism and implementing the WebTransport protocol on top of it.
You can install the WebTransport polyfill using npm:
npm install @yomo/webtransport-polyfill
for browser:
<script src="https://unpkg.com/@yomo/webtransport-polyfill@latest/dist/index.global.js" async></script>
To use the WebTransport polyfill, you need to import it into your JavaScript code:
import { WebTransportPolyfill } from "@yomo/webtransport-polyfill";
Create a connection:
const url = `https://wsss.deno.dev/`;
const transport = new WebTransport(url);
// Optionally, set up functions to respond to the connection closing:
transport.closed
.then(() => {
console.log(`The HTTP/3 connection to ${url} closed gracefully.`);
})
.catch((error) => {
console.error(`The HTTP/3 connection to ${url} closed due to `, error);
});
// Once .ready fulfilled, the connection can be used
await transport.ready;
// Sending datagrams to the server
const writer = transport.datagrams.writable.getWriter();
const data1 = new Uint8Array([65, 66, 67]);
const data2 = new Uint8Array([68, 69, 70, 71]);
writer.write(data1);
setTimeout(() => {
writer.write(data2);
}, 1e3);
setTimeout(() => {
// close the connection
transport.close({
closeCode: 3000,
reason: "close connection by setTimeout",
});
}, 3e3);
// Read datagrams from the server.
const reader = transport.datagrams.readable.getReader();
while (true) {
const { value, done } = await reader.read();
if (done) {
break;
}
console.log(value);
}
more examples can be found here: test/write.html
pnpm run test
The WebTransport polyfill is not a full implementation of the WebTransport API, and APIs may change as this project is following W3C Working Draft
The polyfill consists of two parts: a client-side JavaScript library that exposes the WebTransport API to your web app, and a server-side backend that handles WebSocket and WebTransport connections simultaneously, the source code can be found here: https://github.com/yomorun/presencejs.
To use this polyfill, you need to install and run the server component on your own machine or cloud service. You will also need to include the client-side library in your web app and create a WebTransport object with your server's URL. The polyfill will automatically detect wether the browser supports WebTransport natively or not, and use the appropriate transport layer accordingly. You can then use the WebTransport object as you would normally do with the native API.
WebTransport and WebSocket are both technologies that enable real-time communication between clients and servers over the web. However, there are some key differences between them.
WebSocket uses a single underlying protocol (WebSocket protocol) for both transport and application layer, while WebTransport uses a separate transport protocol (QUIC) and application protocols (e.g., HTTP, WebSocket, and HTTP/3).
WebTransport allows for multiplexing of multiple streams over a single connection, which enables better resource utilization and lower latency. WebSocket does not support multiplexing by default, but it can be achieved using various techniques such as sub-protocols.
WebTransport provides built-in security features such as encrypted transport and origin authentication. WebSocket does not provide built-in security features, but it can be secured using SSL/TLS.
WebTransport is designed to be more flexible than WebSocket, as it can support different application protocols, including WebSocket, HTTP/3, and others. WebSocket is limited to the WebSocket protocol only.
WebTransport is designed to be faster and more efficient than WebSocket, especially in high-latency and low-bandwidth environments. This is due to the use of the QUIC transport protocol, which is optimized for performance in these types of environments.
WebTransport and WebSocket are two web APIs that offer different trade-offs between performance, flexibility, reliability, and compatibility. WebTransport may be a better choice for applications that require low-latency, event-driven communication . While WebSocket is a well-established technology that has been widely adopted for real-time communication over the web, WebTransport is a newer technology that offers several advantages in terms of flexibility, security, and performance through multiple streams per connection and unreliable datagrams. However, WebTransport is not yet widely supported by browsers and servers, hopefully this project helped.
If you would like to contribute to the WebTransport polyfill, please fork the repository and submit a pull request. You can also submit issues or feature requests on the GitHub page.
Build:
bun run build
Test:
bun run test
e2e:
bunx serve out
Verify Publish:
npm pack dry-run
Publish:
npm publish
We deploy a public WebSocket server on Deno for
testing the WebTransport polyfill: https://wsss.deno.dev
.
source code:
import { serve } from "https://deno.land/[email protected]/http/server.ts";
var a = 0;
serve((_req) => {
console.log("> got a _req!");
const upgrade = _req.headers.get("upgrade") || "";
if (upgrade.toLowerCase() != "websocket") {
return new Response("request isn't trying to upgrade to websocket.");
}
const { socket, response } = Deno.upgradeWebSocket(_req);
socket.onopen = () => console.log("socket opened", (new Date()).valueOf());
socket.onmessage = (e) => {
console.log(">[" + ++a + "] socket message:", Deno.inspect(e.data));
socket.send(
"received length=" + e.data.byteLength + " timestamp:" + new Date(),
);
};
socket.onerror = (e) => console.log("socket errored:", e.message);
socket.onclose = () => console.log("socket closed");
return response;
}, { port: 6000 });
console.log("working");
we set domain lo.yomo.dev
to 127.0.0.1
for development purpose, frontend
developers can use this domain to test WebTransport polyfill on their local dev.
$ dig +all @8.8.8.8 lo.yomo.dev
; <<>> DiG 9.10.6 <<>> +all @8.8.8.8 lo.yomo.dev
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19969
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;lo.yomo.dev. IN A
;; ANSWER SECTION:
lo.yomo.dev. 600 IN A 127.0.0.1
;; Query time: 65 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sun Mar 19 12:34:09 CST 2023
;; MSG SIZE rcvd: 56
The WebTransport Polyfill is licensed under the MIT License. See the LICENSE file for more information.