Los mapas de fuentes son una herramienta fundamental para el desarrollo web moderno que facilita considerablemente 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 los mapas de origen
Las primeras aplicaciones web se desarrollaron con baja complejidad. Los desarrolladores implementaron 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 y Svelte
- Metaframeworks de JavaScript: Next.js, Nuxt y Astro.
- Lenguajes de programación de alto nivel: TypeScript, Dart, CoffeeScript
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. 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 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 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, comprimirlo puede dificultar la depuración. Los mapas de fuentes pueden quitar este problema: si vuelven a asignar el código compilado al código original, pueden ayudarte a encontrar rápidamente la fuente de un error.
Genera mapas de orígenes
Los mapas de origen son archivos cuyos nombres terminan con .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 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
}
})
Comprende 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 fuentes:
{
"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 La anatomía de un mapa de fuentes.
La parte más importante de un mapa de fuentes es el campo mappings
. Usa una cadena codificada en base 64 VLQ para asignar líneas y ubicaciones del archivo compilado al archivo original correspondiente. Puedes ver esta asignación con un visualizador de mapa de fuentes, como source-map-visualization o la visualización del mapa de fuentes.
En la columna generado de 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 en 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.
Esto permite a los desarrolladores identificar rápidamente la relación entre el código reducido y el código original, lo que simplifica el proceso de la depuración.
Las herramientas para desarrolladores del navegador aplican estos mapas de origen para ayudarte a identificar rápidamente los problemas de depuración en el navegador.
Extensiones de mapas de origen
Los mapas de orígenes admiten campos de extensiones personalizadas que comienzan con un prefijo x_
. Un
ejemplo es el campo de extensión x_google_ignoreList
que propone Chrome
DevTools. Consulta x_google_ignoreList para obtener más información sobre cómo estas extensiones te ayudan a enfocarte en el código.
Desventajas del mapa de fuentes
Desafortunadamente, las asignaciones de fuentes no siempre son tan completas como necesitas.
En nuestro primer ejemplo, se optimizó la variable greet
durante el proceso de compilación, aunque su valor está incorporado directamente en el resultado final de la cadena.
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 debe resolverse dentro del diseño de los mapas de origen. Una solución posible 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 fuentes. Para seguir el proceso en curso sobre cómo mejorar la depuración con mapas de origen, consulta la propuesta de Source Maps v4 en GitHub.