by Karan Thakkar
How to use Babel macros with React Native
A practical use case for solving an i18n problem using codegen.macro
If you follow Kent C. Dodds or Sunil Pai on Twitter, you may have read tweets every once in a while about babel macros. So did I. But it was only yesterday that I finally understood what the hype is all about. And it is glorious!
So, coming to the problem: I wanted to add some utility to do locale-based number formatting in React Native. Since there is no consistent support for the Internationalization API in React Native, I used a polyfill for it: https://github.com/andyearnshaw/Intl.js. Now, along with the polyfill, I also needed to import all the supporting locale files. There are two options here:
- Load all the locales: This is straightforward, as I can just import one file. This should usually be avoided, since it can unnecessarily bloat your bundle size if you just need to support some locales.
2. Load only necessary locales: With this, I only load the locales that my app supports.
For example, if the app supports 40 locales, I have to manually end up writing 40 imports for each locale. It becomes much harder and more tedious to do this as the list of locales you support increases.
I wanted to automate this in a way that required no manual changes. This is especially useful for us as we have background jobs running on the CI that automatically update our locales file whenever we add support for a new language.
What are these…babel things?
It’s a “new” approach to code transformation. It enables you to have zero-config, importable code transformations.
codegen.macro is one such transformation that you can use to “generate code” at build time.
How do you set it up?
React Native allows you to configure your own babel settings. You can create our own “.babelrc” file at the root of your project. To make sure that you use the default babel configuration that comes with React Native, install babel-preset-react-native.
What does codegen.macro do?
It takes a piece of code, executes it, and replaces itself with the
export-ed string. It will make a lot of sense once you see the example below. Given a list of locales and a codegen macro, it generates a list of imports at build time!
But, what if I need syntax highlighting?
Since we’re writing all our code in a template string, it is really hard to get proper syntax highlighting. You might end up spending a lot of time trying to figure out why your macro gives an error while transpiling.
Thankfully, babel macros support a few different ways to use them. My favorite is using a codegen.require. With this, you can move the body of your macro into a separate file and require it wherever you want, as shown below:
Advantages of using this syntax:
- well, syntax highlighting 💁🏻
- no need to escape any escape sequences you need to use like \n 🙄
- use template literals inside your codegen 👯
NOTE: upgrading React Native
If you choose to override the babel config, whenever you upgrade react-native, you must also bump the version of babel-preset-react-native to match the one being used inside that react-native version.
That’s it folks! You’ve setup babel macros with React Native 🎈🎉 Check out these other available macros if you wanna try out something different.
Hi! 👋 I’m Karan Thakkar. I work on React Native infrastructure at Skyscanner Engineering. Previously, I lead the web team at Crowdfire. I like trying out new technologies in my spare time and I’ve built Tweetify (using React Native) and Show My PR’s (using Golang).
Other articles written by me are: