O que são os mapas de origem?

Os mapas de origem são uma ferramenta crucial no desenvolvimento moderno da Web que facilita muito 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 implantavam arquivos HTML, CSS e JavaScript diretamente na Web.

Apps da Web mais modernos e complexos podem precisar de várias ferramentas no fluxo de trabalho de desenvolvimento. Exemplo:

Uma breve visão geral de várias ferramentas.
Algumas das ferramentas comuns de desenvolvimento de apps da Web.

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 em .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 em 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.

Uma visualização de mapa de origem.
Uma visualização do exemplo de código anterior, gerada por um visualizador.

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 código correspondente na coluna gerada.

A seção mapeamentos 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.
Entrada de mapeamento.
A visualização de mapeamento, com foco na entrada 65 -> 2:2.

Isso permite que os desenvolvedores identifiquem rapidamente a relação entre o código minimizado e o 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.

Ferramentas para desenvolvedores aplicando um mapa de origem.
Exemplo de como as ferramentas de desenvolvedor do navegador aplicam mapas de origem e mostram os mapeamentos entre arquivos.

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.

O cumprimento variável não está mapeado.
A variável greet no código original não está no mapeamento.

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.

A variável greet está indefinida.
A ferramenta para desenvolvedores não consegue encontrar um valor para greet.

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.