Secara default, elemen <script> yang dimasukkan ke dalam DOM melalui properti innerHTML tidak akan dieksekusi oleh browser demi alasan keamanan. Untuk menjalankan script tersebut, Anda harus melakukan parsing manual menggunakan MutationObserver, mengeksekusi ulang fungsi terkait secara langsung, atau menyisipkan elemen script baru menggunakan document.createElement().
Ketika Anda mengubah innerHTML dari sebuah elemen, string HTML yang berisi tag <script> memang masuk ke dalam DOM, namun spesifikasi HTML5 dengan sengaja mengabaikan eksekusi script tersebut. Artikel ini membahas metode teknis paling andal untuk mengatasi batasan tersebut secara aman dan efisien.
Metode 1: Membuat Ulang Elemen Script (Metode Paling Aman)
Cara paling bersih dan direkomendasikan adalah dengan mengambil semua tag <script> dari konten HTML yang ingin dimasukkan, lalu membuat elemen script baru secara dinamis dan menambahkannya ke dalam dokumen agar browser mau mengeksekusinya.
function setHTMLWithScripts(container, htmlString) {
container.innerHTML = htmlString;
// Ambil semua tag script di dalam container
const scripts = container.querySelectorAll('script');
scripts.forEach(oldScript => {
const newScript = document.createElement('script');
// Salin semua atribut (src, type, dll)
Array.from(oldScript.attributes).forEach(attr => {
newScript.setAttribute(attr.name, attr.value);
});
// Salin isi kode script inline
newScript.appendChild(document.createTextNode(oldScript.innerHTML));
// Ganti script lama dengan script baru yang bisa dieksekusi
oldScript.parentNode.replaceChild(newScript, oldScript);
});
}
// Contoh Penggunaan:
const targetDiv = document.getElementById('content');
setHTMLWithScripts(targetDiv, '<p>Konten baru</p><script>console.log("Script berhasil dieksekusi!");</script>');
Metode 2: Menggunakan MutationObserver
Jika Anda menggunakan pustaka pihak ketiga atau framework yang secara otomatis mengubah innerHTML tanpa akses langsung ke fungsi penyisipan, Anda dapat memantau perubahan DOM menggunakan MutationObserver.
const targetNode = document.getElementById('observed-container');
const observer = new MutationObserver((mutationsList) => {
for (let mutation of mutationsList) {
if (mutation.type === 'childList') {
mutation.addedNodes.forEach(node => {
if (node.nodeName === 'SCRIPT') {
const freshScript = document.createElement('script');
freshScript.text = node.innerHTML;
document.head.appendChild(freshScript).parentNode.removeChild(freshScript);
}
});
}
}
});
observer.observe(targetNode, { childList: true, subtree: true });
Perbandingan Metode Eksekusi Script
| Metode | Tingkat Keamanan | Kelebihan | Kekurangan |
|---|---|---|---|
| createElement() | Tinggi | Kontrol penuh, mendukung script eksternal (src) maupun inline. | Membutuhkan fungsi pembantu (helper function) tambahan. |
| MutationObserver | Sedang | Otomatis mendeteksi perubahan DOM tanpa mengubah fungsi render utama. | Sedikit boros performa jika DOM terlalu sering berubah (overhead). |
| eval() / Function() | Sangat Rendah | Kode sangat singkat. | Rentan terhadap celah keamanan XSS (Cross-Site Scripting). |
Tips Troubleshooting & Keamanan
Hindari penggunaan fungsi eval() untuk menjalankan string script mentah dari sumber yang tidak tepercaya. Jika konten HTML berasal dari input pengguna (user-generated content), pastikan untuk melakukan sanitasi terlebih dahulu menggunakan pustaka seperti DOMPurify guna mencegah serangan XSS sebelum script dieksekusi.