Os mapas de origem são uma ferramenta essencial no desenvolvimento moderno da Web que facilitam bastante a depuração. Esta página aborda os conceitos básicos dos mapas de origem, como eles são gerados e como eles melhoram a experiência de depuração.
A necessidade de mapas de origem
Os primeiros apps da Web eram criados com baixa complexidade. Os desenvolvedores implantaram arquivos HTML, CSS e JavaScript diretamente na Web.
Apps da Web mais modernos e complexos podem precisar de várias ferramentas no fluxo de desenvolvimento. Exemplo:
- Linguagens de templates e processadores HTML: Pug, Nunjucks e Markdown.
- Pré-processadores de CSS: SCSS, LESS, PostCSS.
- Frameworks do JavaScript: Angular, React, Vue, Svelte.
- Metaframeworks do JavaScript: Next.js, Nuxt, Astro.
- Linguagens de programação de alto nível: TypeScript, Dart, CoffeeScript.
Essas ferramentas exigem um processo de build para transpilar seu código em HTML, JavaScript e CSS padrão que os navegadores possam entender. Também é prática comum otimizar o desempenho minimizando e combinando esses arquivos, usando uma ferramenta como o Terser.
Por exemplo, usando ferramentas de build, podemos transpilar e compactar o seguinte arquivo TypeScript em uma única linha de JavaScript. Teste essa funcionalidade na demonstração no 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, a compactação do código pode dificultar a depuração. Os mapas de origem podem remover esse problema: ao mapear o código compilado de volta ao código original, eles podem ajudar a encontrar rapidamente a origem de um erro.
Gerar mapas de origem
Os mapas de origem são arquivos com nomes que terminam com .map
(por exemplo,
example.min.js.map
e styles.css.map
). Eles podem ser gerados pela maioria das ferramentas
de build, incluindo Vite, webpack,
Rollup, Parcel e
esbuild.
Algumas ferramentas incluem mapas de origem por padrão. Outros podem precisar de mais configuração para serem produzidos:
/* 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
}
})
Entender o mapa de origem
Para ajudar na depuração, esses arquivos de mapa de origem contêm informações essenciais sobre como o código compilado é mapeado para o código original. Confira um exemplo de 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 entender cada um desses campos, leia a especificação do mapa de origem ou A anatomia de um mapa de origem.
A parte mais importante de um mapa de origem é o campo mappings
. Ele usa uma string codificada com base 64 VLQ para mapear linhas e locais no arquivo compilado para o arquivo original correspondente. É possível conferir esse mapeamento usando um visualizador de mapas de origem, como
source-map-visualization ou
Source Map Visualization.
A coluna generated à esquerda mostra o conteúdo compactado, e a coluna original mostra a origem original.
O visualizador codifica cada linha na coluna original com o respectivo código por cor 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.
Isso permite que os desenvolvedores identifiquem rapidamente a relação entre o código reduzido e o código original, tornando a depuração um processo mais suave.
As ferramentas para desenvolvedores de navegadores aplicam esses mapas de origem para ajudar a identificar problemas de depuração rapidamente no navegador.
Extensões de mapa de origem
Os mapas de origem oferecem suporte a campos de extensão personalizados que começam com um prefixo x_
. Um
exemplo é o campo de extensão x_google_ignoreList
proposto pelo Chrome
DevTools. Consulte x_google_ignoreList
para saber como essas extensões ajudam você a se concentrar no código.
Desvantagens do mapa de origem
Infelizmente, os mapeamentos de origem nem sempre são tão completos quanto você precisa.
No nosso primeiro exemplo, a variável greet
foi otimizada durante o processo
de build, mesmo que o valor dela seja incorporado diretamente à saída da string final.
Nesse caso, ao depurar o código, as ferramentas para desenvolvedores podem não conseguir inferir e mostrar o valor real. Esse tipo de erro pode dificultar o monitoramento e a análise do código.
Esse é um problema que precisa ser resolvido no design dos mapas de origem. Uma solução possível é incluir 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 do mapa de origem. Para acompanhar a melhoria contínua na capacidade de depuração com mapas de origem, consulte a proposta de Mapas de origem v4 no GitHub.