metro-minify-esbuild
Use ESBuild to make your React Native code bundle faster.
Metro Bundler (used for React Native, Instagram, Internal Facebook) allows for any minifier you'd like. ESBuild is a very powerful transpiler / bundler -- but if you use it for transpilation then you can't use any babel plugins (like reanimated, decorators, strip flow types (required for React Native)). So a decent compromise is to use ESBuild for smaller tasks like minifying the output JavaScript bundle.
You write JavaScript -> Babel turns it into older JavaScript -> Minifier makes it small.
By default, Metro uses uglify-es, which currently produces the smallest bundles out of all popular minifiers, but it's ~46x slower than ESBuild.
View minifier benchmarks.
Usage
yarn add -D metro-minify-esbuild esbuild
Now set ESBuild with transformer.minifierPath
, and pass in ESBuild
options via transformer.minifierConfig
.
metro.config.js
const { getDefaultConfig } = require("expo/metro-config");
const config = getDefaultConfig(__dirname);
config.transformer.minifierPath = require.resolve("metro-minify-esbuild");
config.transformer.minifierConfig = {
// ESBuild options...
};
module.exports = config;
Remove Console Logs
You can automatically remove console.log
statements using the following configuration:
config.transformer.minifierConfig = {
// ESBuild options...
drop: ["console"],
};
Performance
Hello World
The following is a base project generated with expo init my-app
, then bundled for production with Metro:
Before
(uglify)
Roughly ~12 seconds, and 833kb.
iOS Bundling complete 11937ms
Bundle Size
┌ index.ios.js 833 kB
└ index.ios.js.map 3.3 MB
After
(esbuild)
Roughly ~9.8 seconds, and 840kb.
About 2 seconds faster, and 7kb larger -- this can improve overtime with newer versions of esbuild, which is why the minifier isn't dictating a specific version of esbuild to use.
iOS Bundling complete 9751ms
Bundle Size
┌ index.ios.js 840 kB
└ index.ios.js.map 2.46 MB
Kitchen Sink
Bundling the Expo Native Component List (everything).
Before
(uglify)
~151 seconds.
iOS Bundling complete 151312ms
Copying 112 ios assets
Bundle Size
┌ index.ios.js 8.99 MB
└ index.ios.js.map 26.2 MB
After
(esbuild)
~53 seconds (about 3x faster), 4kb bigger. This one can change a lot in time, sometimes when the computer is running very slow it's closer to 100s, still substantially faster than uglify.
iOS Bundling complete 52952ms
Copying 112 ios assets
Bundle Size
┌ index.ios.js 9.03 MB
└ index.ios.js.map 17.8 MB
Troubleshooting
error: Invalid option in transform() call: "mangle"
Metro passes default options to the minifier because it expects uglify to be used, simply reset them in your metro.config.js
config.transformer.minifierConfig = {
// ESBuild options...
};