Streaming Cara Anda untuk Mendapatkan Respons Langsung

Siapa pun yang menggunakan pekerja layanan dapat mengetahui bahwa mereka berjalan secara asinkron. Library klien ini hanya mengandalkan antarmuka berbasis peristiwa, seperti FetchEvent, dan menggunakan promise untuk memberikan sinyal saat operasi asinkron selesai.

Asinkronisasi juga sama pentingnya, meskipun kurang terlihat oleh developer, dalam hal respons yang diberikan oleh pengendali peristiwa pengambilan pekerja layanan. Respons streaming adalah standar terbaik di sini: memungkinkan halaman yang membuat permintaan asli mulai menangani respons segera setelah bagian data pertama tersedia, dan berpotensi menggunakan parser yang dioptimalkan untuk streaming agar secara bertahap menampilkan konten.

Saat menulis pengendali peristiwa fetch Anda sendiri, biasanya Anda cukup meneruskan metode respondWith() Response (atau promise untuk Response) yang Anda dapatkan melalui fetch() atau caches.match(), dan menghentikannya sehari. Kabar baiknya adalah Response yang dibuat oleh kedua metode tersebut sudah dapat di-streaming. Kabar buruknya adalah Response yang "secara manual" dibuat tidak dapat di-streaming, setidaknya sampai sekarang. Di sinilah Streams API akan masuk.

Streaming?

Aliran data adalah sumber data yang dapat dibuat dan dimanipulasi secara bertahap, dan menyediakan antarmuka untuk membaca atau menulis potongan data asinkron, hanya subset yang mungkin tersedia dalam memori pada waktu tertentu. Untuk saat ini, kita akan tertarik pada ReadableStream, yang dapat digunakan untuk membuat objek Response yang diteruskan ke fetchEvent.respondWith():

self.addEventListener('fetch', event => {
    var stream = new ReadableStream({
    start(controller) {
        if (/* there's more data */) {
        controller.enqueue(/* your data here */);
        } else {
        controller.close();
        }
    });
    });

    var response = new Response(stream, {
    headers: {'content-type': /* your content-type here */}
    });

    event.respondWith(response);
});

Halaman yang permintaannya memicu peristiwa fetch akan segera mendapatkan respons streaming segera setelah event.respondWith() dipanggil, dan akan terus membaca dari aliran tersebut selama pekerja layanan terus melakukan enqueue() data tambahan. Respons yang mengalir dari pekerja layanan ke halaman benar-benar asinkron, dan kita memiliki kontrol penuh untuk mengisi aliran data.

Penggunaan di dunia nyata

Anda mungkin telah memperhatikan bahwa contoh sebelumnya memiliki beberapa komentar /* your data here */ placeholder, dan ringan pada detail penerapan yang sebenarnya. Jadi akan seperti apa contoh dunia nyata terlihat?

Jake Archibald (tidak mengherankan!) memiliki contoh bagus tentang penggunaan streaming untuk merangkai respons HTML dari beberapa cuplikan HTML yang di-cache, bersama dengan data "live" yang distreaming melalui fetch()—dalam hal ini, konten untuk blog-nya

Keuntungan menggunakan respons streaming, seperti yang dijelaskan Jake, adalah bahwa browser dapat mengurai dan merender HTML saat mengalir, termasuk bit awal yang dimuat dengan cepat dari cache, tanpa harus menunggu seluruh pengambilan konten blog selesai. Cara ini akan memanfaatkan sepenuhnya kemampuan rendering HTML progresif browser. Resource lain yang juga dapat dirender secara bertahap, seperti beberapa format gambar dan video, juga dapat memperoleh manfaat dari pendekatan ini.

Streaming? Atau app shell?

Praktik terbaik yang ada terkait penggunaan pekerja layanan untuk mendukung aplikasi web Anda berfokus pada model Shell Aplikasi + konten dinamis. Pendekatan tersebut bergantung pada penyimpanan cache "shell" aplikasi web Anda secara agresif—HTML, JavaScript, dan CSS minimal yang diperlukan untuk menampilkan struktur dan tata letak Anda—lalu memuat konten dinamis yang diperlukan untuk setiap halaman tertentu melalui permintaan sisi klien.

Aliran data membawa alternatif untuk model Shell Aplikasi, yaitu ada respons HTML yang lebih lengkap yang di-streaming ke browser saat pengguna membuka halaman baru. Respons yang di-streaming dapat memanfaatkan resource yang di-cache sehingga tetap dapat menyediakan potongan awal HTML dengan cepat, bahkan saat offline!—tetapi pada akhirnya terlihat lebih seperti isi respons tradisional yang dirender server. Misalnya, jika aplikasi web Anda didukung oleh sistem pengelolaan konten yang merender HTML oleh server dengan menggabungkan template parsial, model tersebut akan langsung diterjemahkan menjadi menggunakan respons streaming, dengan logika template yang direplikasi dalam pekerja layanan, bukan server Anda. Seperti yang ditunjukkan dalam video berikut, untuk kasus penggunaan tersebut, keunggulan kecepatan yang ditawarkan respons streaming dapat sangat mengejutkan:

Salah satu keuntungan penting streaming seluruh respons HTML, yang menjelaskan alasan ini menjadi alternatif tercepat dalam video, adalah HTML yang dirender selama permintaan navigasi awal dapat memanfaatkan sepenuhnya parser HTML streaming browser. Potongan HTML yang disisipkan ke dalam dokumen setelah halaman dimuat (seperti yang umum dalam model Shell Aplikasi) tidak dapat memanfaatkan pengoptimalan ini.

Jadi, jika Anda sedang dalam tahap perencanaan implementasi pekerja layanan, model mana yang harus Anda adopsi: respons yang di-streaming yang dirender secara bertahap, atau shell ringan yang digabungkan dengan permintaan sisi klien untuk konten dinamis? Jawabannya, tidak mengherankan, semuanya bergantung: pada apakah Anda sudah memiliki implementasi yang mengandalkan CMS dan template sebagian (kelebihan: stream); pada apakah Anda mengharapkan payload HTML tunggal berukuran besar yang akan mendapat manfaat dari rendering progresif (unggul: stream); pada apakah aplikasi web Anda paling baik dimodelkan sebagai aplikasi web satu halaman (keunggulan: App Shell saat ini); dan apakah Anda memerlukan model yang didukung di beberapa browser saat ini (keunggulan: App Shell).

Kami masih dalam tahap awal respons streaming yang didukung pekerja layanan, dan kami tidak sabar untuk melihat berbagai model matang, terutama untuk melihat lebih banyak alat yang dikembangkan untuk mengotomatiskan kasus penggunaan umum.

Mempelajari feed lebih dalam

Jika Anda membuat streaming yang dapat dibaca sendiri, memanggil controller.enqueue() secara acak mungkin tidak akan cukup atau efisien. Jake menjelaskan beberapa detail tentang cara metode start(), pull(), dan cancel() dapat digunakan bersama untuk membuat aliran data yang disesuaikan dengan kasus penggunaan Anda.

Jika Anda ingin mengetahui detail lebih lanjut, baca spesifikasi Streaming.

Kompatibilitas

Dukungan untuk membuat objek Response di dalam pekerja layanan menggunakan ReadableStream seperti sumbernya ditambahkan di Chrome 52.

Implementasi pekerja layanan Firefox belum mendukung respons yang didukung oleh ReadableStream, tetapi ada bug pelacakan yang relevan untuk dukungan Streams API yang dapat Anda ikuti.

Progres untuk dukungan Streams API tanpa awalan di Edge, beserta dukungan pekerja layanan secara keseluruhan, dapat dilacak di Halaman status platform Microsoft.