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 origen, cómo se generan y cómo mejoran la experiencia de depuración.
La necesidad de mapas de origen
Las primeras apps web se compilaban con baja complejidad. 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:
- Lenguajes de plantillas y preprocesadores de HTML: Pug, Nunjucks y Markdown
- Preprocesadores de CSS: SCSS, LESS y PostCSS.
- Frameworks de JavaScript: Angular, React, Vue, Svelte
- Frameworks de meta JavaScript: Next.js, Nuxt y Astro.
- Lenguajes de programación de alto nivel: TypeScript, Dart y CoffeeScript.
Estas herramientas requieren un proceso de compilación para transpilar tu código en HTML, JavaScript y CSS estándar que los navegadores puedan entender. 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 demo 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 origen son archivos cuyos nombres terminan con .map
(por ejemplo,
example.min.js.map
y styles.css.map
). La mayoría de las herramientas de compilación, como Vite, webpack,
Rollup, Parcel y
esbuild, pueden generarlos.
Algunas herramientas incluyen mapas de origen 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.
La columna generado de la izquierda muestra el contenido comprimido, y la columna original muestra la fuente original.
El visualizador asigna un código de color a cada línea de la columna original con su código correspondiente en la columna generada.
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.
Esto permite a los desarrolladores identificar rápidamente la relación entre el código reducido y el código original, lo que hace que la depuración sea un proceso más sencillo.
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.
Extensiones de mapas de origen
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
Lamentablemente, las asignaciones de origen no siempre son tan completas como necesitas.
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.
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 el análisis de tu código.
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.