¿Qué son los mapas de origen?

Los mapas de origen son una herramienta fundamental en el desarrollo web moderno que facilitan mucho la depuración. En esta página, se exploran los conceptos básicos de los mapas de fuentes, cómo se generan y cómo mejoran la experiencia de depuración.

La necesidad de mapas de origen

Las primeras aplicaciones web se compilaban con una complejidad baja. Los desarrolladores implementaban archivos HTML, CSS y JavaScript directamente en la Web.

Las apps web más modernas y complejas pueden necesitar una variedad de herramientas en su flujo de trabajo de desarrollo. Por ejemplo:

Una breve descripción general de varias herramientas.
Algunas de las herramientas comunes de desarrollo de apps web.

Estas herramientas requieren un proceso de compilación para transpilar tu código a HTML, JavaScript y CSS estándar que los navegadores pueden comprender. También es una práctica común optimizar el rendimiento mediante la reducción y combinación de estos archivos con una herramienta como Terser.

Por ejemplo, con las herramientas de compilación, podemos transpilar y comprimir el siguiente archivo de TypeScript en una sola línea de JavaScript. Puedes probarlo en esta demostración en 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:

/* 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, comprimir el código puede dificultar la depuración. Los mapas de origen pueden quitar este problema: ya que asignan tu código compilado al código original, pueden ayudarte a encontrar rápidamente la fuente de un error.

Genera mapas de origen

Los mapas de fuentes son archivos cuyos nombres terminan con .map (por ejemplo, example.min.js.map y styles.css.map). Pueden generarse con la mayoría de las herramientas de compilación, incluidas Vite, webpack, Rollup, Parcel y esbuild.

Algunas herramientas incluyen mapas de orígenes de forma predeterminada. Otros pueden necesitar una 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

Para ayudar con la depuración, estos archivos de mapa de origen contienen información esencial sobre cómo el código compilado se asigna al código original. Este es un ejemplo de un mapa de origen:

{
  "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 origen o La anatomía de un mapa de origen.

La parte más importante de un mapa de origen es el campo mappings. Usa una cadena codificada en VLQ base 64 para asignar líneas y ubicaciones en el archivo compilado al archivo original correspondiente. Puedes ver esta asignación con un visualizador de mapas de origen, como source-map-visualization o Visualización de mapas de origen.

Visualización de un mapa de fuentes.
Una visualización del ejemplo de código anterior, generada por un visualizador.

La columna generado de la izquierda muestra el contenido comprimido, y la columna original muestra la fuente original.

El visualizador codifica por color cada línea de la columna original con su código correspondiente 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.
Entrada de asignación.
La visualización de asignación, que se enfoca en la entrada 65 -> 2:2.

Esto permite a los desarrolladores identificar rápidamente la relación entre el código reducido y el original, lo que simplifica la depuración.

Las herramientas para desarrolladores de navegadores aplican estos mapas de origen para ayudarte a identificar tus problemas de depuración rápidamente en el navegador.

Herramientas para desarrolladores que aplican un mapa de origen.
Un ejemplo de cómo las herramientas para desarrolladores de navegadores aplican los mapas de origen y muestran las asignaciones entre archivos.

Extensiones de mapas de fuentes

Los mapas de origen admiten campos de extensión personalizados que comienzan con un prefijo x_. Un ejemplo es el campo de extensión x_google_ignoreList que propone DevTools 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.

Desventajas del mapa de fuentes

Desafortunadamente, las asignaciones de fuentes no siempre son tan completas como necesitas que lo sean. En nuestro primer ejemplo, la variable greet se optimizó durante el proceso de compilación, a pesar de que su valor está incorporado directamente en el resultado de la cadena final.

No se asignó el saludo de la variable.
Falta la variable greet en el código original de la asignación.

En este caso, cuando depuras el código, es posible que las herramientas para desarrolladores no puedan inferir ni mostrar el valor real. Este tipo de error puede dificultar la supervisión y análisis del código.

La variable de saludo no está definida.
La herramienta para desarrolladores no puede encontrar un valor para greet.

Este es un problema que se debe resolver dentro del diseño de los mapas de origen. Una posible solución es incluir información de alcance en los mapas de origen de la misma manera 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 del mapa de origen. Para seguir el trabajo en curso para mejorar la depurabilidad con los mapas de origen, consulta la propuesta de Source Maps v4 en GitHub.