Mapas de origen: rápidos y claros





El mecanismo de Mapas de origen se utiliza para asignar el código fuente del programa a los scripts generados en función de ellos. A pesar de que el tema no es nuevo y ya se han escrito varios artículos sobre él (por ejemplo, este , este y este ), algunos aspectos aún necesitan aclaración. El artículo presentado es un intento de organizar y sistematizar todo lo que se conoce sobre este tema de forma concisa y accesible.



El artículo Mapas de origen se considera en relación con el desarrollo del cliente en el entorno de navegadores populares (por ejemplo, DevTools Google Chrome), aunque su alcance no está vinculado a ningún idioma o entorno en particular. La fuente principal de Source Maps es, por supuesto, el estándar , aunque aún no se ha adoptado (estado - propuesta), pero, sin embargo, es ampliamente compatible con los navegadores.



El trabajo en Source Maps comenzó a fines de la década de 2000, con la primera versión creada para el complemento Firebug Closure Inspector. La segunda versión se lanzó en 2010 y contenía cambios en términos de reducción del tamaño del archivo de mapa. La tercera versión se desarrolló como parte de una colaboración entre Google y Mozilla y se propuso en 2011 (última revisión en 2013).



Actualmente, en el entorno de desarrollo del cliente, existe una situación en la que el código fuente casi nunca se integra directamente en la página web, sino que pasa por varias etapas de procesamiento antes de eso: minificación, optimización, concatenación, además, el código fuente en sí se puede escribir en idiomas que requieren transpilación ... En este caso, para fines de depuración, se necesita un mecanismo que le permita observar el código original, legible por humanos en el depurador.



Source Maps requiere los siguientes archivos para funcionar:



  • el archivo JavaScript generado real
  • un conjunto de archivos con código fuente utilizado para crearlo
  • archivo de mapa que los mapea entre sí


Archivo de mapa



Todo el trabajo de Source Maps se basa en un archivo de mapa, que puede verse así:



{
    "version":3,
    "file":"index.js",
    "sourceRoot":"",
    "sources":["../src/index.ts"],
    "names":[],
    "mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,SAAS,SAAS;IACd,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;",
    "sourcesContent": []
}


Por lo general, el nombre del archivo de mapa es la suma del nombre del script al que pertenece, con la adición de la extensión ".map", bundle.js - bundle.js.map. Este es un archivo JSON normal con los siguientes campos:



  • "Versión" - Versión de mapas de origen;
  • "Archivo" - (opcional) el nombre del archivo generado al que pertenece el archivo de mapa actual;
  • "SourceRoot": prefijo (opcional) para rutas a archivos fuente;
  • "Fuentes": una lista de rutas a los archivos de origen (resuelto de la misma manera que las direcciones src de la etiqueta del script, puede usar file: //.);
  • "Nombres": una lista de nombres de variables y funciones que se han cambiado en el archivo generado;
  • "Mapeos": coordenadas de las variables y funciones de mapeo de los archivos fuente a un archivo generado en formato Base64 VLQ;
  • "FuentesContenido" - (opcional) en el caso de un archivo de mapa autocontenido, una lista de líneas, cada una de las cuales contiene el texto fuente del archivo de las fuentes;


Descargar mapas de origen



Para que el navegador cargue el archivo de mapa, se puede usar uno de los siguientes métodos:



  • El archivo JavaScript viene con un encabezado HTTP: SourceMap: <url> (anteriormente se usaba ahora el X-SourceMap ahora obsoleto: <url>)
  • el archivo JavaScript generado tiene un comentario especial como:


//# sourceMappingURL=<url> ( CSS /*# sourceMappingURL=<url> */)


Por lo tanto, una vez cargado el archivo de mapa, el navegador extraerá las fuentes del campo "fuentes" y, utilizando los datos en el campo "asignaciones", las mostrará en el script generado. En la pestaña Fuentes DevTools, puede encontrar ambas opciones.



El archivo: // pseudoprotocol se puede usar para especificar la ruta. Además, <url> puede incluir todo el contenido del archivo de mapa en la codificación Base64. En la terminología de Webpack, los mapas de origen como estos se denominan mapas de origen en línea.



//# sourceMappingURL=data:application/json;charset=utf-8;base64,<source maps Base64 code>


Errores de carga de mapas de origen
, map- -, Network DevTools. , map-, Console DevTools : «DevTools failed to load SourceMap: ...». , : «Could not load content for ...».



Archivos de mapa independientes



El código del archivo fuente se puede incluir directamente en el archivo del mapa en el campo "contenido de fuentes", si este campo está disponible, no hay necesidad de descargarlos por separado. En este caso, los nombres de archivo en "fuentes" no reflejan su dirección real y pueden ser completamente arbitrarios. Es por eso que puede ver esos "protocolos" extraños en la pestaña Fuentes DevTools: webpack: //, ng: //, etc.



Mapeos



La esencia del mecanismo de mapeo es que las coordenadas (fila / columna) de los nombres de variables y funciones en el archivo generado se asignan a las coordenadas en el archivo de código fuente correspondiente. Para que funcione el mecanismo de visualización, se requiere la siguiente información:



(# 1) número de línea en el archivo generado;

(# 2) número de columna en el archivo generado;

(# 3) índice de la fuente en "fuentes";

(# 4) número de línea de origen;

(# 5) número de columna fuente;



Todos estos datos se encuentran en el campo "asignaciones", cuyo valor es una cadena larga con una estructura especial y valores codificados en Base64 VLQ.



La línea está dividida por punto y coma (;) en secciones correspondientes a las líneas en el archivo generado (# 1).



Cada sección está separada por comas (,) en segmentos, cada uno de los cuales puede contener 1,4 o 5 valores:



  • el número de columna en el archivo generado (# 2);
  • índice fuente en "fuentes" (# 3);
  • número de línea fuente (# 4);
  • número de columna fuente (# 5);
  • índice del nombre de la variable / función de la lista de nombres;


Los valores de los números de fila y columna son relativos, indican el desplazamiento relativo a las coordenadas anteriores y solo el primero desde el comienzo del archivo o sección.



Cada valor es un número Base64 VLQ. VLQ (cantidad de longitud variable) es el principio de codificar un número arbitrariamente grande utilizando un número arbitrario de bloques binarios de longitud fija.



Source Maps utiliza bloques de seis bits, que se ordenan de menor a mayor. El sexto bit más alto de cada bloque (bit de continuación) está reservado, si se establece, el bloque actual es seguido por el siguiente bloque del mismo número; si se restablece, la secuencia se completa.



Dado que el valor debe tener un signo en Source Maps, el 1 bit menos significativo (bit de signo) también está reservado para él, pero solo en el primer bloque de la secuencia. Como se esperaba, el bit de signo establecido significa un número negativo.



Por lo tanto, si un número puede codificarse con un solo bloque, no puede ser el módulo 15 (1111 2 ), ya que en el primer bloque de seis bits de la secuencia se reservan dos bits: el bit de continuación siempre se borrará, el bit de signo se establecerá en función del signo del número.



Los bloques VLQ de seis bits se asignan a Base64, donde cada secuencia de seis bits corresponde a un carácter ASCII específico.







Decodifica el número mE. Invierta el orden, la parte menos significativa de la última: Em. Decodificamos los números de Base64: E - 000100, m - 100110. En el primero, descartamos el bit de continuación más alto y los dos ceros iniciales - 100. En el segundo, descartamos los bits de continuación más bajos y de signo más bajo (el bit de signo se borra - el número es positivo) - 0011. Como resultado, obtenemos 100 0011 2 , que corresponde al decimal 67.



También puede en la dirección opuesta, codificar 41. Su código binario es 101001 2, nos dividimos en dos bloques: la parte alta - 10, la parte baja (siempre de 4 bits) - 1001. A la parte alta agregamos el bit de continuación de alto orden (borrado) y tres ceros iniciales - 000010. A la parte baja agregamos el bit de continuación de alto orden (conjunto) y el bit de signo menos significativo (borrado - el número es positivo) - 110010. Codificamos números en Base64: 000010 - C, 110010 - y. Invertimos el orden y, como resultado, obtenemos yC.



La biblioteca del mismo nombre es muy útil para trabajar con VLQ .



All Articles