Pembaruan parsial deklaratif

Dipublikasikan: 19 Mei 2026

Web sudah lama beralih dari media statis berbasis dokumen seperti yang digunakan pada awalnya. Aplikasi web modern dan lengkap digunakan oleh semua orang karena berbagai alasan, mulai dari berkomunikasi, membeli, menggunakan konten lengkap, hingga mengelola kehidupan kita yang kompleks.

HTML, meskipun telah mengalami banyak kemajuan, masih dikirim secara berurutan dari atas ke bawah dengan sedikit memperhatikan kapan konten siap atau kapan pengguna menggunakannya. CSS memungkinkan Anda mengubah urutan konten, tetapi sering kali dengan efek samping aksesibilitas yang signifikan. JavaScript memungkinkan Anda memanipulasi DOM melalui berbagai API untuk sedikit keluar dari hal ini, tetapi sering kali memerlukan sintaksis yang panjang atau pembuatan pohon DOM untuk terhubung ke HTML.

Performa sangat penting untuk web, mengingat sifat klien-server media, tetapi pilihan yang kurang optimal sering kali dibuat untuk menghindari sifat HTML yang berurutan ini, yang memperlambat performa. Hal ini mencakup menunggu hingga seluruh halaman siap atau menggunakan framework yang berat untuk mengirimkan komponen secara asinkron. Popularitas framework JavaScript menunjukkan bahwa developer web lebih memilih model berbasis komponen daripada model mental dokumen yang kaku dari asal-usul web.

Tim Chrome telah mempertimbangkan masalah ini dan telah mengembangkan tambahan baru ke platform web dengan nama Pembaruan Parsial Deklaratif.

Dua kumpulan API baru memudahkan pengiriman HTML dengan cara yang kurang linear, baik di luar urutan dalam dokumen HTML itu sendiri maupun melalui cara yang lebih mudah untuk menyisipkan HTML secara dinamis ke dalam dokumen yang ada menggunakan JavaScript API baru. API ini siap untuk pengujian developer dari Chrome 148 menggunakan flag chrome://flags/#enable-experimental-web-platform-features. Polyfill juga tersedia untuk memungkinkan Anda menggunakan API baru ini secara langsung, bahkan di browser yang belum mendukungnya.

Tambahan ini ke platform web sedang distandardisasi dengan masukan positif dari vendor browser dan jalur standardisasi lainnya. Standar yang relevan sedang dalam proses diperbarui untuk menyertakan API baru ini.

Streaming di luar urutan

Kumpulan perubahan pertama adalah API streaming di luar urutan baru yang menggunakan elemen HTML <template> dan placeholder petunjuk pemrosesan. Contoh:

<div>
  <?marker name="placeholder">
</div>

...

<template for="placeholder">
  Here is some <em>HTML content</em>!
</template>

Petunjuk pemrosesan telah ada di XML sejak lama, tetapi telah diperlakukan sebagai komentar di HTML dan diabaikan. API baru ini mengubah hal tersebut dan menghadirkan petunjuk pemrosesan ke HTML. Saat browser melihat petunjuk pemrosesan <?marker name="placeholder">, browser tidak langsung melakukan apa pun—seperti sebelumnya—tetapi petunjuk tersebut dapat direferensikan nanti.

Elemen <template> mencari petunjuk pemrosesan yang sesuai dengan atribut name dan mengganti konten. Dalam hal ini, setelah diuraikan, DOM akan menjadi:

<div>
  Here is some <em>HTML content</em>!
</div>

Selain atribut <?marker> untuk penggantian, ada juga penanda rentang <?start> dan <?end> yang memungkinkan konten placeholder sementara ditampilkan sebelum template diproses:

<div>
  <?start name="another-placeholder">
  Loading…
  <?end>
</div>

...

<template for="another-placeholder">
  Here is some <em>HTML content</em>!
</template>

Dalam hal ini, Loading… ditampilkan hingga <template> terlihat, lalu diganti dengan konten baru.

Anda juga dapat menyertakan petunjuk pemrosesan dalam template untuk memungkinkan beberapa pembaruan:

<ul id="results">
  <?start name="results">
  Loading…
  <?end>
</ul>

...

<template for="results">
  <li>Result One</li>
  <?marker name="results">
</template>
...

<template for="results">
  <li>Result Two</li>
  <?marker name="results">
</template>
...

Hal ini akan menghasilkan HTML berikut setelah diuraikan:

<ul id="results">
  <li>Result One</li>
  <li>Result Two</li>
  <?marker name="results">
</ul>

Dengan petunjuk pemrosesan akhir di bagian akhir jika ada <template for="results"> yang ditambahkan ke dokumen nanti.

Demo

Dalam video ini, aplikasi album foto dasar diimplementasikan dengan HTML streaming:

Demo album foto yang diimplementasikan dengan streaming di luar urutan (sumber)

Status dan foto di-streaming ke dalam HTML setelah tata letak awal.

Kasus penggunaan

Ada banyak kasus penggunaan untuk HTML patching di luar urutan ini jika digabungkan dengan HTML streaming:

  • Arsitektur pulau. Pola umum yang dipopulerkan oleh framework seperti Astro adalah arsitektur pulau tempat komponen di-hydrate secara independen di atas HTML statis. <template for> API memungkinkan konten statis ditangani dengan cara yang serupa langsung di HTML. Framework JavaScript juga dapat menggunakan hal ini untuk pulau yang lebih interaktif atau untuk menangani komponen.
  • Mengirimkan konten saat siap. Berkat arsitektur pulau ini, konten dapat di-streaming saat siap, bukan ditahan untuk konten yang memerlukan pemrosesan tambahan, misalnya, pencarian database. Meskipun banyak platform yang mengizinkan HTML streaming, sifat HTML yang berurutan berarti konten sering kali ditahan, atau dengan menggunakan manipulasi DOM JavaScript yang kompleks. Sekarang Anda dapat mengirimkan konten statis sambil menunggu, lalu menghubungkan konten yang lebih mahal di akhir streaming HTML.
  • HTML dapat dikirimkan dalam urutan optimal untuk performa pemuatan halaman. Dengan mengambil langkah lebih lanjut, Anda dapat mengubah urutan meskipun sudah siap. Misalnya, menu mega adalah fitur navigasi umum yang berisi banyak HTML yang tidak akan dilihat pengguna hingga halaman menjadi interaktif. HTML dalam jumlah besar ini dapat dikirimkan nanti dalam dokumen HTML untuk memprioritaskan HTML yang lebih penting yang diperlukan untuk pemuatan halaman awal. Urutan tidak lagi menjadi penghalang dengan HTML.

Ini hanyalah beberapa kasus penggunaan, dan sangat menarik untuk melihat penggunaan API baru ini oleh developer.

Batasan dan detail

API ini mencakup beberapa batasan dan detail yang perlu diperhatikan:

  • <template for> hanya dapat memperbarui petunjuk pemrosesan dalam elemen induk yang sama karena alasan keamanan. Menambahkan <template for> langsung ke elemen <body> akan memberikan akses ke seluruh dokumen (termasuk <head>).
  • Petunjuk pemrosesan <?end> bersifat opsional dan jika tidak ada, konten antara elemen <?start> dan akhir elemen yang berisi akan diganti.
  • Memindahkan petunjuk pemrosesan setelah <template for> mulai melakukan streaming juga dapat menimbulkan konsekuensi yang tidak terduga dengan konten baru yang terus di-streaming ke lokasi lama.
  • Perhatikan bahwa saat menyisipkan <template for> secara dinamis dengan metode seperti setHTML atau innerHTML, "induk" template saat diuraikan adalah fragmen dokumen perantara. Artinya, menyisipkan HTML menggunakan metode ini tidak dapat mengubah DOM yang ada, dan patching terjadi "di tempat" di dalam fragmen. Namun, saat melakukan streaming menggunakan metode seperti streamHTMLUnsafe (yang akan kita bahas!), tidak ada fragmen perantara sehingga template dapat mengganti konten yang ada.

Potensi penambahan di masa mendatang

Beberapa potensi penambahan di masa mendatang yang sedang dipertimbangkan mencakup:

  • Sisi klien mencakup. Misalnya, <template for="footer" patchsrc="/partials/footer.html">.
  • Pengelompokan. Sisi klien, fragmen mencakup juga dapat diperluas untuk menangani pengelompokan guna memastikan beberapa pembaruan terjadi secara bersamaan.
  • Mencegah konten yang tidak akan berubah agar tidak ditimpa. Hal ini dapat dicapai dengan nomor revisi konten atau pembuatan versi. Hal ini akan memungkinkan status dipertahankan antara perubahan rute atau pembaruan lainnya, bukan mereset konten.
  • Membersihkan saat melakukan patching. Misalnya, <template for=icon safe><svg id="from-untrusted-source">...</svg></template>

Polyfill

Tim Chrome telah merilis template-for-polyfill yang tersedia di npm untuk memungkinkan situs menggunakan fungsi baru ini secara langsung bahkan sebelum fungsi ini tersedia di browser lain.

Ada beberapa batasan karena tidak dapat langsung memperbarui parser HTML browser, tetapi kasus penggunaan yang paling umum tercakup. Situs tetap harus melakukan pengujian di browser lain.

Metode penyisipan dan streaming HTML yang diperbarui

Tidak semua konten dapat dikirimkan dalam HTML. Bagian kedua dari pekerjaan yang dilakukan Chrome di area ini adalah mempermudah pembaruan konten melalui JavaScript.

Sudah ada beberapa cara untuk menyisipkan HTML secara dinamis ke dalam dokumen yang ada menggunakan JavaScript:

  • setHTML
  • setHTMLUnsafe
  • Setter innerHTML dan outerHTML
  • createContextualFragment
  • insertAdjacentHTML

Namun, semuanya berfungsi dengan cara yang sedikit berbeda dengan detail dan perbedaan yang mungkin tidak selalu dipertimbangkan oleh developer:

  • Apakah konten baru akan menimpa atau menambahkan?
  • Apakah konten tersebut membersihkan HTML yang berpotensi berbahaya dengan meng-escape <script> tag, misalnya?
  • Jika tidak, apakah <script>'s harus dijalankan?
  • Bagaimana cara kerjanya dengan TrustedTypes?

Hanya sedikit developer yang dapat melihat API tersebut dan menjawab pertanyaan tersebut dengan yakin untuk setiap API.

Batasan besarnya adalah bahwa API tersebut hanya dapat digunakan untuk kumpulan HTML lengkap yang diketahui sebelumnya, saat ada panggilan untuk mengizinkan HTML di-streaming. Secara praktis, ini berarti Anda harus mendownload seluruh konten sebelum menyisipkannya, padahal salah satu poin penting HTML adalah kemampuan untuk langsung melakukan streaming konten. Hal ini dapat diatasi dengan cara terbatas dengan membagi payload atau menggunakan metode yang tidak praktis dan tidak digunakan lagi seperti document.write, tetapi metode tersebut menimbulkan masalahnya sendiri.

Kumpulan API Statis dan Streaming baru

Chrome telah mengusulkan rangkaian API baru dan ekstensi ke setHTML dan setHTMLUnsafe yang ada yang membersihkan hal ini, serta memperkenalkan fungsi streaming:

Ada metode untuk menetapkan atau mengganti bersama dengan metode untuk menyisipkan konten sebelum atau setelah HTML yang ada. Setiap metode memiliki streaming yang setara:

Tindakan Statis Streaming
Menetapkan konten HTML elemen setHTML(html, options); streamHTML(options);
Mengganti seluruh elemen dengan HTML ini replaceWithHTML(html, options); streamReplaceWithHTML(options);
Menambahkan HTML sebelum elemen beforeHTML(html, options); streamBeforeHTML(options);
Menambahkan HTML sebagai turunan pertama elemen prependHTML(html, options); streamPrependHTML(options);
Menambahkan HTML sebagai turunan terakhir elemen appendHTML(html, options); streamAppendHTML(options);
Menambahkan HTML setelah elemen afterHTML(html, options); streamAfterHTML(options);
Metode penyisipan dan streaming baru

Ada juga versi Unsafe yang akan kita bahas sebentar lagi. Meskipun terlihat banyak (terutama saat Anda menambahkan Unsafe yang setara), konvensi penamaan yang konsisten membuat fungsi setiap metode lebih jelas dibandingkan dengan metode yang tidak terkait yang disebutkan sebelumnya.

Versi statis menggunakan HTML baru sebagai argumen DOM String, beserta opsi opsional:

const newHTML = "<p>This is a new paragraph</p>";
const contentElement = document.querySelector('#content-to-update');

contentElement.setHTML(newHTML);

Versi streaming berfungsi dengan Streams API seperti dengan getWriter():

const contentElement = document.querySelector('#content-to-update');
const writer = contentElement.streamHTMLUnsafe().getWriter();

// Example stream of updating content
while (true) {
 await writer.write(`<p>${++i}</p>`);
 await new Promise((resolve) => setTimeout(resolve, 1000));
}

writer.close();

Atau, sebagai alternatif dari respons pengambilan, dengan rantai pipa:

const contentElement = document.querySelector('#content-to-update');

const response = await fetch('/api/content.html');

response.body
  .pipeThrough(new TextDecoderStream())
  .pipeTo(contentElement.streamHTMLUnsafe());

Kami juga berencana menambahkan metode praktis yang memungkinkan Anda melakukan streaming secara langsung tanpa memerlukan langkah TextDecoderStream() perantara.

Argumen options memungkinkan Anda menentukan sanitizer kustom yang secara default adalah default, yang berarti konfigurasi sanitizer default. Metode ini digunakan sebagai berikut:

const newHTML = "<p>This is a new paragraph</p>";
const contentElement = document.querySelector('#content-to-update');

// Only allows basic formatting
const basicFormattingSanitzer = new Sanitizer({ elements: ["em", "i", "b", "strong"] });

contentElement.setHTML(newHTML, {sanitizer: basicFormattingSanitzer});

Metode "Tidak Aman"

Ada juga versi "tidak aman" dari setiap API:

Tindakan Statis Streaming
Menetapkan konten HTML elemen setHTMLUnsafe(html,options); streamHTMLUnsafe(options);
Mengganti seluruh elemen dengan HTML ini replaceWithHTMLUnsafe(html, options); streamReplaceWithHTMLUnsafe(options);
Menambahkan HTML sebelum elemen beforeHTMLUnsafe(html, options); streamBeforeHTMLUnsafe(options);
Menambahkan HTML sebagai turunan pertama elemen prependHTMLUnsafe(html, options); streamPrependHTMLUnsafe(options);
Menambahkan HTML sebagai turunan terakhir elemen appendHTMLUnsafe(html, options); streamAppendHTMLUnsafe(options);
Menambahkan HTML setelah elemen afterHTMLUnsafe(html, options); streamAfterHTMLUnsafe(options);
Metode penyisipan dan streaming "tidak aman"

Metode "tidak aman" ini menonaktifkan sanitizer secara default (Anda dapat menentukan sanitizer kustom jika mau) dan juga memungkinkan skrip dijalankan dengan opsi runScripts opsional (yang secara default adalah false).

Seperti setHTML, setHTMLUnsafe adalah metode yang ada, tetapi parameter opsi runScripts telah ditambahkan ke metode tersebut agar dapat digunakan dengan eksekusi skrip:

const newHTML = `<p>This is a new paragraph</p>
                 <script src=script.js></script>`;
const contentElement = document.querySelector('#content-to-update');

contentElement.setHTMLUnsafe(newHTML, {runScripts: true});

Kata "tidak aman" dalam metode ini adalah untuk mengingatkan developer tentang potensi risiko dan bagaimana mereka mungkin ingin membersihkan atau membatasi skrip, bukan untuk mengatakan bahwa metode ini tidak boleh digunakan.

Seberapa "tidak aman" hal ini bergantung pada seberapa tepercaya inputnya. Metode statis Unsafe semuanya berfungsi dengan DOM String atau TrustedHTML sebagai argumen html dan juga memungkinkan penggunaan sanitizer. Meskipun dengan runScript, seluruh tujuannya adalah untuk mengizinkan skrip, sehingga secara default tidak ada sanitizer yang digunakan.

Kasus penggunaan

API baru ini memudahkan developer menambahkan HTML ke halaman yang ada, menambahkan API baru dengan nama dan opsi yang konsisten. Streaming API memberikan manfaat performa karena tidak perlu menunggu hingga semua konten baru tersedia untuk platform.

Kasus penggunaan mencakup:

  • Streaming dinamis pembaruan konten besar di Aplikasi Halaman Tunggal. Seperti yang disebutkan sebelumnya, kelemahan besar SPA saat ini adalah tidak dapat memanfaatkan sifat streaming dari pemuatan HTML awal—hingga sekarang.
  • Menyisipkan konten umum seperti footer HTML. Dengan menggunakan JavaScript API, Anda dapat menarik partial dan menyisipkannya ke halaman, sehingga mendapatkan manfaat dari caching, bukan mengulanginya di setiap halaman yang dikirim. Namun, mengingat dependensi pada JavaScript untuk dijalankan, hal ini hanya boleh digunakan untuk konten yang tidak akan terlihat pada pemuatan awal.

Sekali lagi, ini hanyalah beberapa contoh dan kami sangat ingin melihat apa yang Anda buat.

Batasan dan detail

API baru ini juga mencakup beberapa batasan dan detail yang perlu diperhatikan:

  • Integrasi streaming dengan Trusted Types API memerlukan penggunaan metode createParserOptions baru yang memungkinkan penyisipan sanitizer ke operasi setelan HTML apa pun. Lihat penjelasan untuk mengetahui detail selengkapnya tentang integrasi jenis tepercaya
  • Mirip dengan <template for> memindahkan elemen yang di-streaming ke dalam, dapat menimbulkan konsekuensi yang tidak terduga atau error streaming.
  • streamHTMLUnsafe berfungsi lebih seperti parser utama dalam banyak hal, termasuk memproses petunjuk <template for> saat ditambahkan ke dokumen utama dan menunda skrip defer hingga akhir streaming.

Polyfill

Tim Chrome telah merilis html-setters-polyfill yang tersedia di npm untuk memungkinkan situs menggunakan fungsi baru ini secara langsung bahkan sebelum fungsi ini tersedia di browser lain.

Perhatikan bahwa polyfill ini tidak melakukan streaming, melainkan melakukan buffering dan menerapkan saat selesai. Ini lebih merupakan polyfill untuk bentuk API daripada untuk fungsi.

Selain itu, setelan konten yang aman bergantung pada setHTML dan Sanitizer API yang tidak didukung di Safari.

Menggunakan keduanya bersama-sama

Meskipun keduanya adalah dua API terpisah, manfaat sebenarnya berasal dari penggabungannya. Dengan melakukan streaming elemen <template for> baru ke dalam HTML, Anda dapat memperbarui berbagai bagian konten secara dinamis tanpa harus menargetkan setiap bagian dengan referensi JavaScript terpisah ke DOM.

Pemuatan halaman gaya SPA dasar dapat diimplementasikan dengan memuat halaman kerangka dengan petunjuk pemrosesan, lalu melakukan streaming template setiap halaman baru ke bagian bawah HTML untuk dimasukkan ke dalam petunjuk pemrosesan tersebut.

Tidak diragukan lagi bahwa ada lebih banyak potensi dan kasus penggunaan untuk kedua API ini, jadi jangan biarkan imajinasi kami (yang terbatas!) menghalangi Anda. Dengan mempermudah pengelolaan pembaruan parsial, Anda dapat mengurangi beberapa kode boilerplate, mempermudah pembaruan, dan membuka potensi baru untuk web.