Una fuente externa proporciona el contenido de las etiquetas de script escritas como HTML en una cadena. Necesito agregar estas etiquetas de script en la cabeza. Si lo hago así, todas las etiquetas de script se agregan al DOM en la etiqueta principal, sin embargo, ninguna de las fuentes se carga realmente (pestaña de red de devtools).
<html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> </head> <body> <script> let sLoadThis = '<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/underscore@latest/underscore-umd-min.js">' sLoadThis = sLoadThis + "<" + "/script>" let oScript = $(sLoadThis).get(0); document.head.appendChild(oScript); </script> </body> </html>Si utilizo jQuery como intérprete para luego insertar la etiqueta del script con Vanilla JS, funciona:
<html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> </head> <body> <script> let sLoadThis = '<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/underscore@latest/underscore-umd-min.js">' sLoadThis = sLoadThis + "<" + "/script>" let oScript = $(sLoadThis).get(0); var vanillaScript = document.createElement('script') vanillaScript .type = 'text/javascript' vanillaScript .src = oScript.src document.head.appendChild(vanillaScript ) </script> </body> </html>Me gustaría entender por qué no funciona en mi primer ejemplo.
El segundo ejemplo se ejecuta porque está utilizando un nodo dom. Así es como funciona appendChild() . El método jQuery get() funciona con elementos dom existentes. Lo único que tienes es una cadena, que aún no existe en tu dominio. Pruebe lo siguiente.
let script = $.parseHtml(sLoadThis); console.log(script.get(0)); // should be a script dom node element document.head.appendChild(script.get(0));En Vanilla JavaScript es aún más fácil y mucho más rápido que jQuery porque no tienes que usar una dependencia.
const fragment = document.createRange().createContextualFragment(htmlStr); document.head.appendChild(fragment);Hasta donde sé, hay 4 formas de crear un elemento DOM a partir de una cadena:
HTML5 especifica que una etiqueta <script> insertada con una de las 3 primeras opciones no debe ejecutarse porque podría convertirse en un riesgo para la seguridad. ver esto
Entonces, en el ejemplo, aunque todas las etiquetas de script se agregan al DOM en la sección <head> , solo se ejecutará la opción número 4.
const str1 = "<script>alert('option 1 executed')" + "<" + "/script>" const str2 = "<script>alert('option 2 executed')" + "<" + "/script>" const str3 = "<script>alert('option 3 executed')" + "<" + "/script>" const str4 = "<script>alert('option 4 executed')" + "<" + "/script>" // OPTION 1 const placeholder1 = document.createElement('div') placeholder1.innerHTML = str1 const node1 = placeholder1.firstChild document.head.appendChild(node1) // OPTION 2 const placeholder2 = document.createElement('div') placeholder2.insertAdjacentHTML('afterbegin', str2) const node2 = placeholder2.firstChild document.head.appendChild(node2) // OPTION 3 const node3 = new DOMParser().parseFromString(str3, 'text/html').head.firstElementChild document.head.appendChild(node3) // OPTION 4 const node4 = document.createRange().createContextualFragment(str4) document.head.appendChild(node4)