Mapas de origen de JavaScript, ¿Podemos hacerlo mejor?

Rate this content
Bookmark

La revisión actual de la especificación de Mapas de origen de JavaScript tiene más de 12 años. A lo largo de este tiempo, todo el ecosistema ha evolucionado enormemente, pero por alguna razón, no hemos hecho nada para mejorar la experiencia de depuración y todavía estamos atascados en la versión 3 de la especificación. ¿Podemos hacerlo mejor?

27 min
05 Jun, 2023

Video Summary and Transcription

Los mapas de origen permiten comprender el código transpilado, empaquetado o minificado. La depuración con identificadores post hoc y de depuración ayuda a identificar archivos. Los problemas con los mapas de origen incluyen colisiones de hash y nombres de funciones faltantes. Se pueden utilizar diversas técnicas para determinar la función que causó un error. Los mapas de origen pueden almacenar información adicional y se pueden realizar mejoras en la resolución de rutas y posiciones de columnas. Los puntos de código y las posiciones de tokens pueden diferir entre navegadores. Detectar mapas de origen puede ser desafiante sin un esquema JSON estandarizado.

Available in English

1. Introducción a los mapas de origen

Short description:

Los mapas de origen te permiten transpilar, empaquetar o minimizar el código fuente, o más bien, comprender cómo se produjo el código fuente transpilado, empaquetado o minimizado. Una vez que tenemos los mapas de origen, necesitamos combinarlos con el archivo minimizado. Esto se puede hacer a través de un comentario al final del archivo o un encabezado de solicitud. La depuración ad hoc te permite ver el error a medida que ocurre y utilizar el código exacto que desencadenó el error.

Hola a todos. Mi nombre es Kamil Ugurek y soy un ingeniero de software senior en Sentry, donde actualmente trabajo en el equipo de procesamiento, donde una de las cosas en las que estamos trabajando es procesar mapas de origen. También soy miembro del equipo principal de TRPC y, como probablemente puedas notar, realmente, realmente me encantan los mapas de origen, lo que me lleva al título opcional de esta charla, que es por qué los mapas de origen son tan difíciles de hacer correctamente.

No entraremos en muchos detalles sobre cómo funcionan los mapas de origen. Hay muchas otras fuentes que puedes utilizar para esto. Sin embargo, necesitamos entender algunas ideas muy básicas. Los mapas de origen te permiten transpilar, empaquetar o minimizar el código fuente, o más bien, comprender cómo se produjo el código fuente transpilado, empaquetado o minimizado. Lo que hace es mapear los tokens del código minimizado de vuelta al código original, lo cual te permite ver errores más utilizables, en lugar de algo como undefined X no es la función funcional, o algo por el estilo. Si quieres entender más a fondo cómo se codifica en realidad, hay una excelente publicación de blog de un amigo mío, Arpad, en su blog. Realmente te animo a que lo leas detenidamente.

Una vez que tenemos los mapas de origen, necesitamos combinarlos de alguna manera con el archivo original, o más bien, lo siento, el archivo minimizado. Una de las formas de hacer esto es a través del comentario al final del archivo con un pragma especial, que es source mapping URL, o el encabezado de solicitud, que adjuntas a la solicitud HTTP saliente. Ahora que tienes ambas cosas, en lugar de ver este mensaje de error muy críptico puedes ver algo mucho más utilizable, como fetch user data en lugar de ver una función X. Puedes ver esto directamente en tus DevTools, lo cual se llama depuración ad hoc, lo que significa que ves el error a medida que ocurre y puedes utilizar el código exacto, que se carga dentro del motor de JavaScript, y puedes estar seguro de que es el mismo código que desencadenó el error.

2. Depuración con Post Hoc y Identificadores de Depuración

Short description:

Existe otra forma de depuración llamada depuración post hoc. El principal problema es la falta de identidad, ya que no podemos determinar qué archivo se utilizó. El uso de una versión como identificador único ayuda, pero no es suficiente. Podemos utilizar identificadores de depuración, que son hashes únicos basados en los mapas de origen, para asegurarnos de que los archivos sean los mismos.

Sin embargo, existe otra forma de depuración, que es la depuración post hoc, que es lo que Sentry está haciendo en realidad, lo que significa que cuando ocurre un error, se nos envía y ahora necesitamos averiguar qué código se utilizó realmente cuando se produjo el error, que acaba de suceder después del hecho.

Esto me lleva a los problemas que existen en este momento. El primero y el más grande es la falta de identidad, lo que significa que no podemos saber qué archivo se utilizó realmente. Incluso si lo subes a nosotros, lo cual describiré muy brevemente cómo funciona. Produces algunos archivos, tienes archivos minimizados, tienes mapas correspondientes. Los pasas a través de una de las herramientas que proporcionamos, que es el binario de la CLI o los complementos para tus empaquetadores. Si quieres, puedes usar solo una llamada a la API y almacenarlos en Sentry. Necesitas usar la versión, que es un identificador único para tu compilación. Y necesitamos esto porque es la única forma en que realmente podemos tener algún tipo de identidad del archivo. Porque aparte del nombre de archivo, no hay nada más que lo haga realmente especial.

Con el tiempo, puedes tener 10 archivos MinJS empaquetados cargados para la misma versión, y no podemos saber cuál es cuál, básicamente. Es por eso que tenemos algo que también se llama un disco, que puedes pensar como directorios o el contenedor de archivos. Entonces podemos tener los mismos nombres de archivo para múltiples entornos, como producción o desarrollo o preparación. Sin embargo, aún no es suficiente, porque básicamente puedes tener el mismo nombre de archivo, algo como MinJS empaquetado, que es muy, muy común, pero producido en momentos completamente diferentes, como hoy y un mes de antelación, seis meses después, y así sucesivamente, y esos nombres pueden seguir siendo los mismos. Puedes usar nombres de hash, pero esto no siempre es posible porque a algunas personas les gusta encargarse de la memoria caché utilizando encabezados HTTP, y a veces es molesto lidiar con eso.

Entonces digamos que tenemos todos los archivos. Ahora ocurre el error. Aquí está el error. El primer marco apunta a HTTPS DRPC.IO. Assets MinJS empaquetado, que es esta línea, y realmente no nos importa el nombre del host. Podemos omitirlo para la parte de procesamiento, lo que nos deja con MinJS empaquetado. Sin embargo, la parte problemática es que se ha servido desde algún lugar. El MinJS empaquetado se encuentra dentro de Assets. Sin embargo, ¿qué sucede si la estructura de tu proyecto, cuando lo cargaste, era algo como esto, lo que significa que si solo incluiste el directorio dist para cargarlo, significa que tu archivo se encontrará en dist front-end MinJS empaquetado. Este no es el mismo camino y no coincidirán, lo que significa que no podemos decir que este archivo que acabas de servir, que en realidad causó el error, es el mismo archivo exacto que se cargó. Sería solo una suposición.

Entonces, ¿cuál es la solución a esto? ¿Cómo podemos asegurarnos de que esos archivos sean los mismos archivos, verdad? En realidad, podemos usar algo que se llama identificadores de depuración, que en el mundo nativo, es muy, muy común. Tienes algo que se llama archivos de depuración y en nuestro caso lo llamamos ID de depuración porque es muy fácil de recordar. Cómo funciona es de manera muy similar a la URL de asignación de origen, sin embargo, en lugar de usar rutas, hasheas todo el mapa de origen producido y utilizas este hash o más bien el identificador único basado en el hash, que es UUID en este caso, y lo insertas dentro del archivo minimizado y dentro del propio mapa de origen. Debes hashear el mapa de origen en lugar de solo el origen en sí porque hay una forma en que el código fuente original puede producir los mismos hashes para diferentes contenidos.

3. Problemas con los Mapas de Origen y la Depuración

Short description:

Si tu empaquetador elimina comentarios, inlinea funciones o colapsa llamadas de funciones, el archivo minificado resultante puede tener el mismo hash para diferentes códigos fuente originales, lo que hace que los mapas de origen sean inútiles. Para solucionar esto, hasheamos el contenido del mapa de origen y lo asociamos con un ID de depuración. Mantenemos una lista de archivos en el paquete y sus ID de depuración correspondientes. Una solución mejor sería tener una lista de marcos con sus ID de depuración, lo que permitiría una depuración más precisa. Se pueden utilizar servidores de símbolos para almacenar archivos de depuración con sus ID correspondientes, eliminando la necesidad de adivinar nombres de archivos o rutas. Sin embargo, surge un problema con los nombres y alcances en los mapas de origen, ya que los nombres de las funciones pueden no estar incluidos. Esto puede hacer que los mensajes de error y las trazas de pila no sean útiles.

Por ejemplo, si tu bundler decide eliminar comentarios, inlinear algunas funciones o simplemente colapsar esas llamadas de funciones, algo como esto, si agregas una sola línea de nuevos comentarios a tu código fuente y luego lo compilas y luego eliminas todos los comentarios y lo compilas nuevamente, puede terminar siendo el mismo archivo minificado, lo que significa que tenías el mismo hash para diferentes códigos fuente originales, lo que significa que los mapas de origen no pueden usar sus mapeos porque las líneas y columnas estarán completamente desfasadas.

Por eso decidimos hashear el contenido del mapa de origen en sí. Sin embargo, eso no es todo porque aún necesitamos saber de alguna manera que el archivo minificado que causó el error, en realidad tiene algún ID de depuración, como recordar esta cosa, ¿verdad? Tenemos una ruta aquí, no hay ID de depuración en ninguna parte aquí. Lo que necesitamos en su lugar es alguna forma de preguntarle a la API, o más bien al motor de JavaScript, cuál es el ID de depuración para esta URL, para este archivo que se está cargando ahora mismo en el motor?

Esta API que ves aquí es completamente inventada. No hay nada como esto, pero este es uno de los requisitos que necesitamos. En este momento, lo que hacemos es simplemente mantener una lista de todos los archivos que producimos dentro del paquete, dentro del espacio de nombres global. Entonces, como el ID de depuración de la ventana, y tenemos una lista de mapeos de URL a ID de depuración, que definitivamente no es genial, no es perfecto, pero funciona con lo que tenemos en este momento, lo que nos permite validar nuestras ideas. Pero la solución perfecta sería algo como esto, donde el error no es solo una cadena de pila, sino una lista de marcos, lo que nos permitiría ir marco por marco y preguntar por su ID de depuración correspondiente, y luego enviarlo junto con el evento mismo.

Esto nos brinda otra ventaja muy, muy buena, que son los llamados servidores de símbolos. Los servidores de símbolos también se utilizan en el mundo nativo. Básicamente, lo que hacen es permitirte tener un servidor completamente separado de primera parte donde puedes almacenar todos tus archivos de depuración con sus ID de depuración correspondientes. En nuestro caso, podrían ser solo mapas de origen, por ejemplo, en un bucket de S3, y simplemente haces que tu herramienta sepa que allí está la URL, por favor, cada vez que necesites algunos mapas de origen, o cualquier otro archivo de depuración, simplemente ve allí. Simplemente ve allí, pregúntale si tiene el ID de depuración correspondiente, tiene el archivo, te dará toda la información que necesitas. Básicamente, configuras una URL en la configuración y listo, nada más. No necesitas adivinar los nombres de los archivos. No tienes que adivinar las rutas ni nada por el estilo.

Algo mucho más visible para el usuario final es un problema con los nombres y alcances. Porque los nombres y los nombres de las funciones originales dentro de los mapas de origen no son obligatorios. Puedes tener un mapa de origen completamente sin ellos, puedes omitir un array de nombres originales. Lo que puede suceder es que puedes tener una función que arroja un error y ver el error así. Tienes una función indefinida, y el único marco que ves está en x, en y, en z. Es completamente inútil. Ves que todo sucede en la línea número uno y la columna 21000, lo que sea. No es genial. Toma este código, por ejemplo. Hay una función tal vez que llama a la función llamame, que luego arroja un error. Y luego llamamos a la función. En esta forma minificada, es algo como esto. Todo se colapsa en una sola línea y algunas funciones. Lo siento, algunos nombres de funciones con solo una o dos letras.

4. Detectando la Función que Causó el Error

Short description:

Para determinar qué función causó un error, podemos utilizar el escaneo hacia atrás mediante la tokenización del código minificado y buscar el nombre minificado de la función. Otro truco es el nombramiento del llamador, donde subimos un paso en la pila de llamadas y obtenemos la columna y la línea del marco. Sin embargo, el mejor enfoque es la reconstrucción del AST, que proporciona toda la información necesaria pero puede ser ineficiente en memoria y costoso computacionalmente para archivos grandes.

¿Cómo podemos saber realmente que la función que lanzó el error fue llamada? El problema aquí es que el motor de JavaScript te dirá lo que realmente sucedió es que el primer marco fue un nuevo error. Porque, técnicamente, esto es lo que produjo el error. Pero esto no es útil. De lo contrario, solo veríamos en la mayoría de los casos simplemente nuevo error, nuevo error, nuevo error. Lo que queremos saber es cuál es la función que realmente lo causó.

Entonces, en este caso, sería llamada. Sin embargo, ¿cómo podemos saber que es realmente esto? Tenemos algunos trucos bajo la manga. El primero se llama escaneo hacia atrás, donde tomas el código fuente minificado, lo tokenizas y vas un token a la vez hacia atrás. Entonces, lo que haces es tener error, ir a nuevo, volver a throw, y lo haces mientras veas el nombre minificado de la función. O más bien, veas el token function precedido del nombre minificado. En nuestro caso aquí, era XY, ¿verdad? Una vez que tenemos esta función y los tokens XY, podemos preguntar cuál es la posición del token XY, en este caso, y luego preguntar al mapa de origen, oye, bien, ahora sé la nueva ubicación. Esto no es nuevo error. Sé la ubicación de XY. ¿Tienes un nombre correspondiente para esto? Y si es así, tenemos suerte, ahora podemos decir que fue realmente llamada y no nuevo error lo que causó el error en sí. Sin embargo, no siempre es posible. Si tienes una función anónima o una función flecha de ES6, simplemente no funcionará.

El segundo truco que podemos usar se llama nombramiento del llamador, que hace la suposición de que la función que nos llamó no modificó el nombre original. Por ejemplo, no lo reasignó en ningún lugar o no lo modificó de alguna manera extraña o no lo llamó dinámicamente, aquí está la pila de llamadas, la original, que es la función maybe, que llama a la función llamada, que produce el error, y la minificada, llamada VM llamando a XY, llamando a nuevo error. Lo que podemos hacer en lugar de preguntar cuál es la ubicación de nuevo error, podemos subir un paso hacia arriba, que es XY en este caso, y preguntarle a XY cuál es la columna y la línea correspondiente de este marco. Lo que requiere es que necesitas conocer toda la pila de antemano. Por ejemplo, si solo obtienes el primer marco, volvamos al ejemplo aquí, si solo conoces X asset bundle min JS, el primero, estás fuera de suerte, no puedes hacer esto porque lo que necesitas hacer es consultar el marco debajo de este, que es como una columna 2430, ¿verdad? Esto generalmente da algunas ideas, como podemos recurrir a esto, pero tampoco es genial. No siempre funciona, sigue siendo solo una suposición.

La mejor idea que se nos ocurrió y que usamos con éxito en este momento, y esto es lo que muchos DevTools están haciendo en este momento, es la reconstrucción del AST. Lo que hace es tomar el código fuente minificado y hacer el mismo trabajo que los empaquetadores y transpiladores ya hicieron, pero, nuevamente, es muy ineficiente en memoria, es pesado, básicamente requiere mucho trabajo. Sin embargo, la ventaja de esto es que obtenemos toda la información que podamos necesitar. Por ejemplo, podemos decir que aquí se lanzó un nuevo error dentro del método estático en la clase método bar de foo, ¿verdad? O en este caso, podemos decir exactamente que era solo un literal de objeto, asignado a la variable A mayúscula, y era un método, en realidad la propiedad, lo siento, el otro método, u otro getter personalizado llamado foo. Y aquí podemos decir que era el constructor de la clase B. Entonces podemos saber exactamente dónde estamos en el momento en que ocurrió el error, porque podríamos reconstruir todo. Sin embargo, el problema es que nuevamente, necesitas procesar todo el AST, lo que puede ser muy, muy costoso para archivos muy grandes. Y los empaquetadores y transpiladores ya tenían estos data.

5. Almacenando Información en Mapas de Origen

Short description:

Los mapas de origen pueden almacenar información en su interior, como el formato de pasta utilizado por los ingenieros de Bloomberg. Se pueden agregar ámbitos al archivo JSON del mapa de origen para codificar desplazamientos y nombres. La naturaleza anidada de los ámbitos permite una fácil reconstrucción y búsqueda binaria. También hay problemas más pequeños que podrían abordarse en la próxima revisión de la especificación, como pruebas de conformidad.

Básicamente, pueden almacenar esto de alguna manera dentro de un mapa de origen, que es otra idea que ya fue iniciada por los ingenieros de Bloomberg con su llamado formato de pasta, del cual puedes leer más aquí. Y también hay un RFC, del cual puedes leer en el propio repositorio de los nuevos RFC de mapas de origen.

En lugar de hacer este trabajo una y otra vez, lo que sucedería es que agregaríamos un nuevo atributo llamado ámbitos, o nombres de ámbito, algo así, dentro del archivo JSON del mapa de origen, y codificaría todos los desplazamientos, todos los desplazamientos en bytes y el nombre del ámbito en sí. Y debido a que los ámbitos están anidados, por ejemplo, tienes este ámbito externo, que puede contener un ámbito interno, que puede contener un ámbito interno y así sucesivamente. Es muy fácil reconstruir esto porque se superponen, ¿verdad? Como 15 está dentro de los límites de 10 y 30, 16 a 20 está dentro de los límites de 15 y 25, y así sucesivamente. Una vez que tienes esto, como una pirámide, puedes hacer una búsqueda binaria y encontrar la mejor coincidencia para tu caso.

Esos son dos problemas importantes, sin embargo, hay algunos más pequeños que aún no son críticos, pero sería bueno solucionar en la próxima revisión de la especificación. El primero son las pruebas de conformidad. Si nunca has oído hablar de ellas, son un conjunto de pruebas que confirman que tu herramienta, tu motor, tu implementación sigue la especificación al pie de la letra. Si pasa todas las pruebas de las pruebas de conformidad, significa que se ha implementado correctamente. Esto es lo que prueba 262, en realidad es lo que los navegadores y otros motores de JavaScript están ejecutando para asegurarse de que la especificación de ECMAScript se implemente correctamente.

6. Resolución de Rutas y Posiciones de Columna

Short description:

La resolución de rutas puede ser frustrante ya que es difícil determinar la ruta. Las fuentes originales suelen estar codificadas dentro del propio mapa de origen, pero esto es opcional. Algunas herramientas solo proporcionan la matriz de archivos y una ruta de origen, que puede tener varios formatos. Adivinar la ubicación real del archivo puede ser un desafío. Además, las posiciones de columna pueden diferir entre navegadores debido a la codificación y la falta de especificación.

El segundo, que es mucho más molesto, es la resolución de rutas, porque nunca puedes asegurar cuál es la ruta. Una de las características que tenemos en Sentry se llama líneas de contexto, lo que significa que para la ubicación donde ocurrió el error, queremos mostrarte algo así como un pequeño fragmento del editor. Así que si tus líneas anteriores, tus pocas líneas siguientes. Pero para hacer esto, necesitamos las fuentes originales de alguna manera.

Las fuentes originales suelen estar codificadas dentro de los contenidos de las fuentes dentro del propio mapa de origen, es solo un área de códigos fuente, básicamente. Sin embargo, también es opcional. Así que a veces tienes mala suerte y no tienes acceso a esto, lo que nos dificulta. Así que cuando uses Sentry CLI, probablemente lo incluiremos en línea. Lo arreglaremos por ti. Sin embargo, todavía hay algunas herramientas que no producen esto. Solo producen la matriz de archivos y una ruta de origen opcional mencionada, lo que significa que esas son las rutas que la herramienta utilizó para producir este paquete en caso de que quieras volver atrás y, ya sabes, ver dónde se encontraban esos archivos y la ruta de origen es como un prefijo común para todos esos archivos. Sin embargo, el problema es que pueden tener cualquier formato. Pueden ser absolutas, pueden ser relativas. Pueden tener un host personalizado, como por ejemplo, webpack está haciendo ahora mismo. Pueden tener espacios de nombres personalizados, lo que quieras. Es el salvaje Oeste. Así que puedes terminar con algo como esto. Tienes un error donde el marco apunta a example.com este bundle.js. Su correspondiente mapa de origen apunta a dos directorios, up slash assets slash bundle.js map porque sí, puedes tener viajes de ruta aquí. Y tus archivos apuntan a algo como webpack hosts slash, y luego el espacio de nombres que webpack produjo, que en este caso sería como alguna biblioteca de espacio de nombres y hay problemas con la API de origen. Y de alguna manera necesitas adivinar u entender dónde estaba realmente el archivo ubicado en caso de que alguien te haya enviado el archivo.

Un dato curioso, en este momento, nuestra función de unión de URL simple tiene más de 50 líneas de código y sigue creciendo. Es muy divertido. La posición de columna es algo que si lo piensas, no debería suceder, ya estamos en el año 2023, pero por alguna razón todavía sucede porque las codificaciones son complicadas y, ya sabes, no hay una especificación. Considerando este código muy trivial, es solo una función que lanza un error, sin embargo, puedes ver que hay un comentario que tiene algunos emojis en su interior. Y ¿qué sucede si ejecutas este código en todos los navegadores modernos en este momento, si lo llamas en Firefox, tendrás un informe de que el error fue lanzado en la columna 13, que es el inicio de la función en Chrome es la columna 16 y en Safari es la columna 19. ¿Qué sucede? Quiero decir, ¿qué sucede es que Firefox está contando. Unidades de código. Lo siento. O puntos de código, puntos de código.

7. Puntos de Código y Posiciones de Tokens

Short description:

Los puntos de código difieren en el recuento entre Chromium, que cuenta unidades de código, y Safari, que trata el paréntesis de apertura del token como la llamada a la función. Algunas herramientas producen dos tokens para una función, mientras que otras producen uno sin espacios en blanco. Para asegurar una ubicación de minificación precisa y un comportamiento de depuración adecuado, utiliza valores de posición iguales o mayores y considera la posibilidad de errores de uno en uno.

Sí. Puntos de código. Um, que en este caso es gratis porque es UTF 32. Entonces es como un solo punto de código para cada emoji de fuego, Chromium está contando unidades de código donde, um, es UTF 16, lo que significa que cada emoji de fuego está compuesto por dos unidades de código. Um, y Safari por alguna razón decidió que, uh, es mejor hacer, uh, tratar el paréntesis de apertura del token como el token que realmente llama a la función, no la función en sí, ¿verdad? Divertido. Um, aún es mejor que, uh, que este, que tiene un error de uno en uno, uh, que, por supuesto, también debemos tener en el mapa de origen. Si tienes esta función, que es una función que algunas herramientas producirán dos tokens donde el primer token es función espacio en blanco y el segundo es qué, que es el nombre de la función. Sin embargo, algunas herramientas producirán esto, que es funcional sin espacio en blanco. Y el segundo es espacio qué? A quién le importa ahora mismo, si quieres, uh, asegurarte de que tu ubicación de minificación apunte a un lugar muy específico en la ubicación original, simplemente puedes usar igual, necesitas usar igual o más por si acaso hay este error de uno en uno, error de uno en uno aquí, uh, producido. Y también se aplica al depurador porque si haces clic en debug, um, debug, la marca debug dentro de las herramientas de desarrollo en el token o el nombre de la función, necesita conocer la posición exacta del token.

8. Detectando Mapas de Origen

Short description:

Para detectar si un archivo es un mapa de origen, actualmente nos basamos en la extensión del archivo y atributos específicos como 'versión' y 'mapeo'. Sin embargo, dado que los mapas de origen son solo archivos JSON, no hay bytes mágicos ni indicadores. Sería beneficioso crear un esquema JSON estandarizado para los mapas de origen para garantizar su identificación.

Y el último es, ¿estás seguro de que es un mapa de origen? Porque bueno, el mapa de origen es solo un archivo Jason, ¿verdad? Entonces, ¿cómo detectamos que realmente es un mapa de origen? Bueno, actualmente lo hacemos de dos formas. La primera es utilizando la extensión del archivo. Sin embargo, ya sabes, puedes llamar a cualquier archivo, uh, con la extensión .map. Entonces, lo que la mayoría de las herramientas hacen es buscar atributos de versión con la cadena literal `free`. Y si tienes este atributo, y tal vez también buscan atributos de mapeo, si tienes todas esas cosas, significa que es muy probable que sea un mapa de origen, pero. Solo es muy probable porque es solo un archivo Jason y porque es solo Jason, no podemos tener ningún byte mágico ni nada por el estilo predefinido o adjunto al archivo. Um, así que estamos sin suerte. Sería genial si pudiéramos hacer algo. Es crear un esquema Jason que luego se estandarizaría y todos podríamos usarlo en todas partes. Y esto aseguraría que el archivo que estamos mirando sea el mapa de origen. Entonces, ¿cuál es el futuro? Desafortunadamente, para este formato que se ha utilizado, ya sabes, durante casi todos, bueno, no casi en todos los navegadores y motores. Se ha hablado muy, muy, uh, bueno, no hubo mucha discusión, diría que esta es una buena manera de decirlo. Um, porque la revisión inicial, que fue la revisión uno, fue alrededor de 2009. Aunque no puedo confirmarlo, um, porque el documento original está bloqueado ahora mismo. Um, sin embargo, la revisión dos y la revisión tres fueron en algún momento entre 2010 y 2013, lo que significa que, uh, han pasado más de 10 años ahora desde que se realizaron cambios significativos. Y simplemente hemos lidiado con el hecho de que funciona como funciona. Un dato curioso durante los últimos 10 años, um, o diría que ahora son 12. Uh, esta fue toda la especificación. Si alguna vez has usado mapas de origen o has tenido que hacer algo con ellos, esto es lo que probablemente encontraste. Y esta fue realmente la especificación oficial del mapa de origen, uh, mapa de origen, uh, especificación, este documento de Google muy agradable. Afortunadamente, un amigo mío y yo lo hemos traducido al formato oficial o a otra forma estandarizada de escribir especificaciones, que puedes encontrar ahora mismo en esta URL y podemos evolucionar esto de alguna manera. Um, entonces, el siguiente paso aquí es que, a principios de este año, uh, algunos colegas míos y yo de Century participamos en este grupo de divulgación 39, que se centra en tooling y mapas de origen. Y lo que queremos hacer ahora es intentar impulsar este trabajo y básicamente hacer nuestras vidas más fáciles. Afortunadamente, hay muchas más personas interesadas en esto de las que pensábamos, cada persona está haciendo algún RFC, alguna investigación, algunos están proporcionando comentarios. Y tengo muchas esperanzas de que podamos hacer este trabajo más pronto que tarde. Si quieres unirte y contribuir también, hay un canal de métricas para esto. Puedes unirte a las reuniones directamente. Nos reunimos cada, um, cada mes en este momento, que es cada último miércoles del mes, creo. Y si tienes algún comentario directamente, puedes ir al repositorio de GitHub, allí hay RFC abiertos, hay discusiones abiertas. Um, ya sabes, y todos los comentarios son bienvenidos. Definitivamente deberías unirte. Gracias por tu tiempo. Y si tienes alguna pregunta, contáctame en Twitter. Gracias. Adiós.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

JSNation 2023JSNation 2023
29 min
Modern Web Debugging
Few developers enjoy debugging, and debugging can be complex for modern web apps because of the multiple frameworks, languages, and libraries used. But, developer tools have come a long way in making the process easier. In this talk, Jecelyn will dig into the modern state of debugging, improvements in DevTools, and how you can use them to reliably debug your apps.
JSNation 2022JSNation 2022
21 min
The Future of Performance Tooling
Top Content
Our understanding of performance & user-experience has heavily evolved over the years. Web Developer Tooling needs to similarly evolve to make sure it is user-centric, actionable and contextual where modern experiences are concerned. In this talk, Addy will walk you through Chrome and others have been thinking about this problem and what updates they've been making to performance tools to lower the friction for building great experiences on the web.
React Summit 2023React Summit 2023
24 min
Debugging JS
As developers, we spend much of our time debugging apps - often code we didn't even write. Sadly, few developers have ever been taught how to approach debugging - it's something most of us learn through painful experience.  The good news is you _can_ learn how to debug effectively, and there's several key techniques and tools you can use for debugging JS and React apps.
JSNation 2023JSNation 2023
31 min
Rome, a Modern Toolchain!
Modern JavaScript projects come in many shapes: websites, web applications, desktop apps, mobile apps, and more. For most of them, the common denominator is the technical debt that comes from settings up tools: bundlers, testing suite, code analysis, documentation, etc. I want to present you Rome, a toolchain that aims to be a all-in-one toolchain for the web, with one single tool you can maintain the health of all your projects!
React Summit 2023React Summit 2023
29 min
Improving Developer Happiness with AI
GitHub Copilot is an AI pair programmer that can help you write code faster and spend less time writing repetitive code.This session will cover some interesting use cases for Copilot that could shine a light on its possibilities. This ranges from prompting Copilot to suggest a function based on a comment, learning how to use a new framework, tackling a security or accessibility bug, better documenting your code, translating  code from one language to another, etc.Agenda:
Introduction to CoPilot
- What is Copilot
- How can you use it
- How it can help you write code faster
- Copilot Labs experimental features I will pick examples from the React ecosystem and show how we can fix Security Vulnerabilities and Accessibility issues in some components.

Workshops on related topic

React Summit 2023React Summit 2023
170 min
React Performance Debugging Masterclass
Featured WorkshopFree
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
React Advanced Conference 2023React Advanced Conference 2023
148 min
React Performance Debugging
Workshop
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
JSNation 2022JSNation 2022
71 min
The Clinic.js Workshop
Workshop
Learn the ways of the clinic suite of tools, which help you detect performance issues in your Node.js applications. This workshop walks you through a number of examples, and the knowledge required to do benchmarking and debug I/O and Event Loop issues.
JSNation 2023JSNation 2023
44 min
Solve 100% Of Your Errors: How to Root Cause Issues Faster With Session Replay
WorkshopFree
You know that annoying bug? The one that doesn’t show up locally? And no matter how many times you try to recreate the environment you can’t reproduce it? You’ve gone through the breadcrumbs, read through the stack trace, and are now playing detective to piece together support tickets to make sure it’s real.
Join Sentry developer Ryan Albrecht in this talk to learn how developers can use Session Replay - a tool that provides video-like reproductions of user interactions - to identify, reproduce, and resolve errors and performance issues faster (without rolling your head on your keyboard).
TestJS Summit 2021TestJS Summit 2021
146 min
Live e2e test debugging for a distributed serverless application
WorkshopFree
In this workshop, we will be building a testing environment for a pre-built application, then we will write and automate end-to-end tests for our serverless application. And in the final step, we will demonstrate how easy it is to understand the root cause of an erroneous test using distributed testing and how to debug it in our CI/CD pipeline with Thundra Foresight.

Table of contents:
- How to set up and test your cloud infrastructure
- How to write and automate end-to-end tests for your serverless workloads
- How to debug, trace, and troubleshot test failures with Thundra Foresight in your CI/CD pipelines