Melhorar a experiência de depuração da Web com mapas de origem.
Hoje estamos falando sobre mapas de origem, uma ferramenta crucial no desenvolvimento moderno da Web que facilita muito a depuração. Neste artigo, vamos conhecer os conceitos básicos dos mapas de origem, como eles são gerados e como melhoram a experiência de depuração.
Necessidade de mapas de origem
No passado, criamos aplicativos da web com HTML puro, CSS e JavaScript e implantamos os mesmos arquivos na web.
No entanto, como estamos criando aplicativos da Web mais complexos atualmente, seu fluxo de trabalho de desenvolvimento pode envolver o uso de várias ferramentas. Exemplo:
- Criação de modelos de linguagens e pré-processadores HTML: Pug, Nunjucks, Markdown.
- Pré-processadores de CSS: SCSS, LESS, PostCSS.
- Frameworks JavaScript: Angular, React, Vue, Svelte.
- Metaframeworks de JavaScript: Next.js, Nuxt e Astro.
- Linguagens de programação de alto nível: TypeScript, Dart, CoffeeScript.
- e muito mais. A lista pode ser infinita!
Essas ferramentas exigem um processo de criação para transcompilar seu código em HTML, JavaScript e CSS padrão que os navegadores possam entender. Além disso, para otimizar o desempenho, é uma prática comum compactar (por exemplo, usando Terser para reduzir e modificar o JavaScript) e combinar esses arquivos, reduzindo seu tamanho e tornando-os mais eficientes para a Web.
Por exemplo, usando ferramentas de build, podemos transcompilar e compactar o arquivo TypeScript a seguir em uma única linha de JavaScript. Você pode testar a demonstração no meu repositório do 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);
});
Uma versão compactada seria:
/* 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)}));
No entanto, essa otimização pode tornar a depuração mais desafiadora. Um código compactado com tudo em uma única linha e nomes de variáveis mais curtos pode dificultar a identificação da origem de um problema. É aí que entram os mapas de origem: eles mapeiam seu código compilado de volta para o código original.
Gerar mapas de origem
Os mapas de origem são arquivos com nomes terminados em .map
(por exemplo, example.min.js.map
e styles.css.map
). Eles podem ser gerados pela maioria das ferramentas de build, como Vite, webpack, Rollup, Parcel, esbuild e outras.
Algumas ferramentas incluem mapas de origem por padrão, enquanto outras podem precisar de configurações adicionais para criá-las.
/* 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
}
})
Sobre o mapa de origem
Esses arquivos de mapa de origem contêm informações essenciais sobre como o código compilado é mapeado para o código original, permitindo que os desenvolvedores depurem com facilidade. Veja um exemplo de um mapa de origem.
{
"mappings": "AAAAA,SAASC,cAAc,WAAWC, ...",
"sources": ["src/script.ts"],
"sourcesContent": ["document.querySelector('button')..."],
"names": ["document","querySelector", ...],
"version": 3,
"file": "example.min.js.map"
}
Para compreender cada um desses campos, leia a especificação do mapa de origem ou este artigo clássico sobre a anatomia de um mapa de origem.
O aspecto mais importante de um mapa de origem é o campo mappings
. Ele usa uma string codificada em base 64 do VLQ para mapear linhas e localizações no arquivo compilado para o arquivo original correspondente. Para isso, use um visualizador de mapa de origem, como o source-map-visualization e a Source Map Visualization.
A coluna gerado à esquerda mostra o conteúdo compactado e a coluna original mostra a fonte original.
O visualizador codifica por cores cada linha na coluna original e o código correspondente na coluna generated.
A seção mappings mostra os mapeamentos decodificados do código. Por exemplo, a entrada 65-> 2:2
significa:
- Código gerado: a palavra
const
começa na posição 65 no conteúdo compactado. - Código original: a palavra
const
começa na linha 2 e na coluna 2 do conteúdo original.
Dessa forma, os desenvolvedores podem identificar rapidamente a relação entre o código minimizado e o código original, tornando a depuração um processo mais suave.
As Ferramentas para desenvolvedores do navegador aplicam esses mapas de origem para ajudá-lo a localizar os problemas de depuração mais rapidamente, diretamente nos navegadores.
A imagem mostra como as Ferramentas para desenvolvedores do navegador aplicam mapas de origem e mostra os mapeamentos entre os arquivos.
Extensões de mapa de origem
Os mapas de origem são compatíveis com extensões. As extensões são campos personalizados que começam com a convenção de nomenclatura x_
. Um exemplo é o campo de extensão x_google_ignoreList
proposto pelo Chrome DevTools. Consulte x_google_ignoreList para saber mais sobre como essas extensões ajudam você a se concentrar no código.
Não é perfeito
No nosso exemplo, a variável greet
foi otimizada durante o processo de build. O valor foi incorporado diretamente na saída da string final.
Nesse caso, quando você depura o código, as ferramentas para desenvolvedores podem não conseguir inferir e mostrar o valor real. Esses não são apenas os desafios das ferramentas para desenvolvedores do navegador. Ela também dificulta o monitoramento e a análise de código.
Esse, obviamente, é um problema solucionável. Uma delas é incluir as informações de escopo nos mapas de origem da mesma forma que outras linguagens de programação fazem com as informações de depuração.
No entanto, isso exige que todo o ecossistema trabalhe em conjunto para melhorar a especificação e a implementação dos mapas de origem. Há uma discussão ativa sobre como melhorar a capacidade de depuração com mapas de origem.
Queremos melhorar os mapas de origem e tornar a depuração ainda menos difícil.