[Code Pills] Añadir nodos <script> en el <body> en Vue/Nuxt con Postscribe

Un truco para que Nuxt no borre scripts embebidos.

Cuando estaba revisando mi primera publicación, me plantee añadir pequeñas porciones de código con tal de hacer diferente las referencias a los repos que mencionaba, por lo que use Embed Like Gist.

El código generado es un nodo script que llama a un javascript que ejecuta la instrucción document.write en el cual añade en el árbol DOM todo lo necesario para que el resultado se vea algo así:

El problema de ello que ese código se ejecuta inmediatamente cuando el navegador renderiza el HTML, pero Vue sigue cargando recursos, y luego vuelve a cargar el DOM, borrando toda inconsistencia para mantener la reactividad, quitando en el proceso los nodos añadidos por emgithub.

¿Cómo solucionarlo? Como pruebas iniciales, intenté añadir el nodo posterior a la carga (con nextTick), o cargar el contenido del JS y añadirlo en el árbol DOM, y varias vueltas más sin éxito.

El punto clave es la función document.write que no se ejecuta una vez que el DOM ya fue cargado. Esto lo soluciona la librería PostScribe, que se encarga de ejecutar dicha función de forma asíncrona, permitiendo añadir porciones de código posterior a la carga inicial de la página.

Para este caso, mostraré como abordé esta solución en Nuxt, para usarlo de forma global.

Primero, instalar la dependencia. En este caso añadí directamente el paquete a la lista respectiva e instalé con npm.

Luego añadí PostScribe como plugin al archivo de configuración a través del archivo en la carpeta plugins. En ese archivo añadí la instrucción para que la función a llamar de PostScribe quedara disponible para todo el proyecto a través de la variable this.

Finalmente, llamé a la librería dentro del componente que mostrará el contenido embebido. En mi caso, la porción del código proviene de la query a la API de Prismic, que contiene la porción correspondiente al contenido embebido dentro de la entrada del blog.

Usando $nextTickse asegura que el componente no sobreescribirá el contenido generado debido a acciones del render.

¡Y listo! El código ya debería estar generado el contenido externo que buscábamos añadir. Esta solución se puede extender a otros frameworks, o cargarlo localmente dentro del componente requerido, según se requiera.