React Native e Babel: Utilizando macros

Um guia prático para gerar código com codegen.macro

Automatização e robôs, em toda a parte!

⭐️ Créditos

Se você segue o Kent C Doods ou Sinil Pai no Twitter, você já deve ter visto alguns tweets sobre babel macros. É, eu também! Mas foi apenas ontem que eu finalmente compreendi o hype dessa ferramenta. E ela é incrível!.

Chega de papo, vamos ao problema: Eu quero adicionar alguns utilitários para formatação de números, baseado na localização, no meu projeto React Native. Como não existe uma API de internacionalização consistente em React Native, eu acabei utilizando um polyfill para isso: https://github.com/andyearnshaw/Intl.js. Agora, junto do polyfill, eu também preciso importar todos os arquivos de localização suportados.

Temos duas opções aqui:

1 — Carregar todas as localizações: Esse é bem direto, pois podemos importar apenas um arquivo. Essa solução deve ser evitada, pois adiciona um bundle desnecessário ao seu projeto, caso você precise suportar apenas algumas localizações.

Carregando todas as localizações do Intl.js

2 — Carregar apenas as localizações necessárias: Com essa abordagem, eu carrego apenas o que meu projeto suporta.

Carregando apenas o necessário

Por exemplo, se o projeto suporta 40 localizações, eu preciso, manualmente, escrever 40 imports, um para cada. Isso fica propício a erro e chato de manter, uma lista enorme de localizações que só tende a crescer.

Eu quero automatizar essa importação manual. Isso é útil, por exemplo, quando a nossa CI atualiza automaticamente nossos arquivos de localização, a qualquer momento que adicionarmos mais uma língua.

Mas como nós podemos importar, dinamicamente, múltiplos arquivos e, ao mesmo tempo, permitir que o React Native packager receba os caminhos de arquivos corretos? A resposta é babel-plugin-macros com codegen.macro 💙

Ahmm…o que é tudo isso?

No artigo nesse link, escrito por Kent C Dodds. Ele descreve perfeitamente o que são babel-plugin-macros:

É uma “nova” abordagem para transformação de código. Ele te permite importar transformações customizadas, com zero de configuração.

codegen.macro é uma dessas transformações customizadas, que você pode usar para “gerar código” em tempo de compilação.

Certo, como utilizamos isso?

React Native te permite definir a sua própria configuração para Babel. Você pode criar o seu .babelrc na raíz do seu projeto e, para ter certeza que você esteja utilizando a configuração padrão do React Native, vale a pena instalar babel-preset-react-native.

Além disso, vamos instalar outro módulo: codegen.macro. Ele utiliza o babel-plugin-macros por debaixo dos panos, deixando nossa configuração como a seguinte:

Exemplo de como seu .babelrc deve ficar

E como o codegen.macro funciona?

Ele pega pedaços de um código, executa esse trecho e substitui o mesmo trecho pela string retornada. Tudo fará mais sentido ao visualizar o exemplo abaixo. Dado uma lista de localizações e um macro, ele irá gerar uma lista de imports em tempo de compilação!

  • Esquerda: codegen.macro para criar a lista de imports.
  • Direita: lista de localizações suportada
  • Resultado final: lista gerada depois da transformação feita pelo Babel

Mas, e se eu quiser coloração de sintaxe?

Como estamos escrevendo todo nosso código em template string, é difícil ter uma coloração de sintaxe correta. Você vai acabar gastando um bom tempo tentando resolver porque o seu macro está dando um erro ao transformar seu código.

E como podemos resolver isso? Hora, com macros é claro! 🎉

Existe algumas maneira diferentes para se usar o babel macros. Minha favorita é usando codegen.require. Com ela, você pode mover o seu macro, de template string, em um arquivo separado, aonde você quiser. Por exemplo:

Algumas vanragens do codegen.require

  • Bom, coloração de sintaxe 💁
  • Não precisa escapar sequências como \n, para gerar múltiplas linhas
  • você pode usar tempalte string dentro do seu macro 𝍆

Atenção ao atualizar React Native

Ao escolher utilizar usa própria configuração do .babelrc, lembre-se de, a qualquer momento que você atualizar a versão do react-native@*, você também deve atualizar a versão do babel-preset-react-native, combinando com a versão utilizada no RN.

Finalizando

É isso aí galera 🎈🎉 Aprendemos um poucos mais sobre Babel e macros. Existe uma lista maneira de macros disponíveis, talvez você vá encontrar o que precisa por lá, ou simplesmente, testar algo novo!

Já utiliza babel-plugin-macros? Compartilhe abaixo sua experiência. Gostou do artigo? Meu muito obrigado! 🙏