¿Qué son los mapas de origen?

Mejora la experiencia de depuración web con mapas de origen.

Hoy hablaremos sobre los mapas de origen, una herramienta crucial en el desarrollo web moderno que facilita considerablemente la depuración. En este artículo, exploraremos los conceptos básicos de los mapas de origen, cómo se generan y cómo estos mejoran la experiencia de depuración.

La necesidad de los mapas de origen

En los viejos tiempos, creamos aplicaciones web con HTML, CSS y JavaScript puros, y luego implementamos los mismos archivos en la Web.

Sin embargo, dado que actualmente compilamos aplicaciones web más complejas, es posible que el flujo de trabajo de desarrollo incluya el uso de varias herramientas. Por ejemplo:

Una breve descripción general de varias herramientas.

Estas herramientas requieren un proceso de compilación para transpilar tu código a HTML, JavaScript y CSS estándar que los navegadores puedan comprender. Además, para optimizar el rendimiento, es una práctica común comprimir (por ejemplo, usar Terser para reducir y modificar JavaScript) y combinar estos archivos, reducir su tamaño y hacerlos más eficientes para la Web.

Por ejemplo, con las herramientas de compilación, podemos transpilar y comprimir el siguiente archivo TypeScript en una sola línea de JavaScript. Puedes jugar con la demostración en mi repositorio de GitHub.

/* A TypeScript demo: example.ts */

document.querySelector('button')?.addEventListener('click', () => {
  const num: number = Math.floor(Math.random() * 101);
  const greet: string = 'Hello';
  (document.querySelector('p') as HTMLParagraphElement).innerText = `${greet}, you are no. ${num}!`;
  console.log(num);
});

Una versión comprimida sería la siguiente:

/* A compressed JavaScript version of the TypeScript demo: example.min.js  */

document.querySelector("button")?.addEventListener("click",(()=>{const e=Math.floor(101*Math.random());document.querySelector("p").innerText=`Hello, you are no. ${e}!`,console.log(e)}));

Sin embargo, esta optimización puede hacer que la depuración sea más difícil. El código comprimido con todo en una sola línea y nombres de variables más cortos puede dificultar la identificación del origen de un problema. Ahí es donde entran en juego los mapas de origen: asignan tu código compilado de vuelta al código original.

Cómo generar mapas de orígenes

Los mapas de origen son archivos con nombres que terminan en .map (por ejemplo, example.min.js.map y styles.css.map). Se pueden generar con la mayoría de las herramientas de compilación, como Vite, webpack, Rollup, Parcel, esbuild y muchas más.

Algunas herramientas incluyen mapas de origen de forma predeterminada, mientras que otras pueden necesitar configuración adicional para producirlos.

/* Example configuration: vite.config.js */
/* https://vitejs.dev/config/ */

export default defineConfig({
  build: {
    sourcemap: true, // enable production source maps
  },
  css: {
    devSourcemap: true // enable CSS source maps during development
  }
})

Información sobre el mapa de fuentes

Estos archivos de mapa de origen contienen información esencial sobre la forma en que el código compilado se asigna al código original, lo que permite a los desarrolladores realizar depuraciones con facilidad. Este es un ejemplo de un mapa de orígenes.

{
  "mappings": "AAAAA,SAASC,cAAc,WAAWC, ...",
  "sources": ["src/script.ts"],
  "sourcesContent": ["document.querySelector('button')..."],
  "names": ["document","querySelector", ...],
  "version": 3,
  "file": "example.min.js.map"
}

Para comprender cada uno de estos campos, puedes leer la especificación del mapa de fuentes o este artículo clásico sobre la anatomía de un mapa de fuentes.

El aspecto más crítico de un mapa de fuentes es el campo mappings. Utiliza una cadena codificada en base 64 VLQ para asignar líneas y ubicaciones del archivo compilado al archivo original correspondiente. Esa asignación se puede visualizar con un visualizador de mapa de origen, como source-map-visualization y source-map-visualization.

Visualización de un mapa de origen.
En la imagen, se muestra nuestro ejemplo de código anterior, generado por un visualizador.

En la columna generado que se encuentra a la izquierda, se muestra el contenido comprimido, mientras que en la columna original, se muestra la fuente original.

El visualizador codifica por color cada línea de la columna original y su correspondiente código en la columna generated.

En la sección mappings, se muestran las asignaciones decodificadas del código. Por ejemplo, la entrada 65-> 2:2 significa lo siguiente:

  • Código generado: La palabra const comienza en la posición 65 en el contenido comprimido.
  • Código original: La palabra const comienza en la línea 2 y la columna 2 del contenido original.

Asignando entrada.

De esta manera, los desarrolladores pueden identificar rápidamente la relación entre el código reducido y el código original, lo que hace que la depuración sea más fluida.

Las Herramientas para desarrolladores del navegador aplican estos mapas de origen para ayudarte a identificar los problemas de depuración más rápido, directamente en el navegador.

Las Herramientas para desarrolladores aplican un mapa de fuentes.

En la imagen, se muestra cómo las Herramientas para desarrolladores del navegador aplican mapas de origen y muestran las asignaciones entre archivos.

Extensiones de mapas de origen

Los mapas de fuentes admiten extensiones. Las extensiones son campos personalizados que comienzan con la convención de nombres x_. Un ejemplo es el campo de extensión x_google_ignoreList propuesto por las Herramientas para desarrolladores de Chrome. Consulta x_google_ignoreList para obtener más información sobre cómo estas extensiones te ayudan a enfocarte en tu código.

No es perfecto

En nuestro ejemplo, se optimizó la variable greet durante el proceso de compilación. El valor se integró directamente en la salida final de la cadena.

El saludo variable no es un mapa.

En este caso, cuando depuras el código, es posible que las herramientas para desarrolladores no puedan inferir ni mostrar el valor real. Esto no solo presenta los desafíos de las herramientas para desarrolladores de los navegadores. También dificulta la supervisión y el análisis de código.

La variable greet no está definida.

Esto, por supuesto, es un problema que se puede resolver. Una de las formas es incluir la información de alcance en los mapas de origen, al igual que otros lenguajes de programación, lo hacen con su información de depuración.

Sin embargo, esto requiere que todo el ecosistema trabaje en conjunto para mejorar la especificación y la implementación de los mapas de origen. Hay un debate activo sobre cómo mejorar la depuración con mapas de orígenes.

Esperamos mejorar los mapas de origen y hacer que la depuración sea aún menos abrumadora.