Source Maps

Una de las prácticas recomendadas para mejorar el rendimiento de nuestros desarrollos es la combinación y compresión de los recursos JavaScript y CSS. Sin embargo, hemos vivido más de una situación donde ocurren errores en producción y resulta realmente complicado depurar si hemos llevado a cabo dicha práctica.

Source Map se trata de un archivo relacionado con nuestro código ya tratado, el cual nos proporciona una forma de acceder al código original, ya que mantiene información de los archivos a los que hace referencia, permitiéndonos reconstruir los mismos aunque estemos en producción. Este proceso es posible con los archivos JavaScript y CSS, aunque en este post vamos a probarlo sólo con el primero de ellos.

Creando source maps

En la mayoría de los artículos donde se habla de ello, las soluciones que nos ofrecen son Closure Compiler, UglifyJS, a través de CoffeeScript, etcétera. Para aquellos que trabajemos con Visual Studio podemos ayudarnos con Web Essentials para conseguir la generación de estos archivos.

Imaginemos que tenemos el siguiente código JavaScript:

window.onload = function () {

    function id(elem) {
        return document.getElementById(elem);
    }

    //Some comments here
    id("btnFirst").addEventListener("click", function () {
        alert("btnFirst button click!");
    });

    //Some comments there
    id("btnSecond").addEventListener("click", function () {
        alert("btnSecond button click!");
    });
};

Seleccionamos el archivo en Solution Explorer con el botón derecho y en el apartado Web Essentials seleccionamos Minify JavaScript file(s):

Web Essentials Minify JavaScript file with source map

Si abrimos el archivo .min veremos que al final del mismo aparece la siguiente referencia:

/*
//# sourceMappingURL=script.min.js.map
*/

Por otro lado, el archivo al que hace alusión sourceMappingURL, contiene la siguiente información:

{
"version":3,
"file":"script.min.js",
"lineCount":1,
"mappings":"AAAAA,MAAMC,OAAQ,CAAEC,QAAS,CAAA,CAAG,CAExBC,SAASA,CAAE,CAACC,CAAD,CAAO,CACd,OAAOC,QAAQC,eAAe,CAACF,CAAD,CADhB,CAKlBD,CAAE,CAAC,UAAD,CAAYI,iBAAiB,CAAC,OAAO,CAAE,QAAS,CAAA,CAAG,CACjDC,KAAK,CAAC,wBAAD,CAD4C,CAAtB,CAE7B,CAGFL,CAAE,CAAC,WAAD,CAAaI,iBAAiB,CAAC,OAAO,CAAE,QAAS,CAAA,CAAG,CAClDC,KAAK,CAAC,yBAAD,CAD6C,CAAtB,CAZR,CAe3B",
"sources":["script.js"],
"names":["window","onload","window.onload","id","elem","document","getElementById","addEventListener","alert"]
}
version
Se trata de la versión de la especificación de source map. En este caso Source Map Revision 3 Proposal
file
El nombre del archivo relacionado.
lineCount
En la última revisión se indica que este campo fue eliminado el 20 de Julio del 2011, pero no aparece exactamente cuál era su utilidad.
mappings
Se trata de un string en Base64 VLQ, el cual contiene realmente el “mapeo” del código.
sources
Array con el nombre de los archivos originales. En este ejemplo se trata de un único archivo, pero podemos combinar varios.
names
Array que contiene todos los nombres de variables y funciones utilizados en los archivos fuente.

Para que podamos ver su efecto, basta con modificar la referencia en el código HTML por el archivo .min que acabamos de generar:

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <input type="button" id="btnFirst" value="First button" />
    <input type="button" id="btnSecond" value="Second button" />
    <script src="Scripts/script.min.js"></script>
</body>
</html>

A día de hoy los navegadores que soportan source maps son Chrome y Firefox. En el primero de ellos es necesario que los valores Enable JS source maps y Enable CSS source maps estén habilitados en las herramientas para desarrolladores:

Settings Chrome Source Maps

Si accedemos al sitio web con las Dev Tools habilitadas, veremos que aparecen tanto el archivo script.min.js como script.js en el apartado Sources, aunque únicamente tengamos el primero de ellos asociado a nuestro código HTML:

source maps activated Chrome

Podemos utilizar breakpoints y depurar nuestro código, como si fuera esa versión la que tenemos asociada en producción.

Espero que haya sido de utilidad.

¡Saludos!