2021-06-15 16:07:24 +03:00
|
|
|
# @rnx-kit/metro-serializer-esbuild
|
|
|
|
|
2021-07-09 15:18:53 +03:00
|
|
|
[![Build](https://github.com/microsoft/rnx-kit/actions/workflows/build.yml/badge.svg)](https://github.com/microsoft/rnx-kit/actions/workflows/build.yml)
|
2021-07-09 17:13:39 +03:00
|
|
|
![This plugin is highly experimental](https://img.shields.io/badge/state-experimental-critical)
|
2021-07-09 15:18:53 +03:00
|
|
|
[![npm version](https://img.shields.io/npm/v/@rnx-kit/metro-serializer-esbuild)](https://www.npmjs.com/package/@rnx-kit/metro-serializer-esbuild)
|
|
|
|
|
2021-06-15 16:07:24 +03:00
|
|
|
⚠️ **THIS PLUGIN IS HIGHLY EXPERIMENTAL** ⚠️
|
|
|
|
|
|
|
|
Allow Metro to use [esbuild](https://esbuild.github.io) for bundling and
|
|
|
|
serialization.
|
|
|
|
|
2021-07-09 17:13:39 +03:00
|
|
|
## Motivation
|
|
|
|
|
|
|
|
Metro currently does not implement tree shaking, i.e. it does not attempt to
|
|
|
|
remove unused code from the JS bundle. For instance, given this code snippet:
|
|
|
|
|
|
|
|
```ts
|
|
|
|
import { partition } from "lodash";
|
|
|
|
```
|
2021-06-15 16:07:24 +03:00
|
|
|
|
2021-07-09 17:13:39 +03:00
|
|
|
Metro will bundle all of `lodash` in your bundle even though you're only using a
|
|
|
|
small part of it. In `lodash`'s case, you can add
|
|
|
|
[`babel-plugin-lodash`](https://github.com/lodash/babel-plugin-lodash#readme) to
|
|
|
|
your Babel config to help Metro strip away some modules, but not all libraries
|
|
|
|
will come with such helpers. For more details, see issues
|
|
|
|
[#227](https://github.com/facebook/metro/issues/227) and
|
|
|
|
[#632](https://github.com/facebook/metro/issues/632).
|
|
|
|
|
|
|
|
metro-serializer-esbuild addresses this by letting esbuild take over bundling.
|
|
|
|
|
|
|
|
## Requirements
|
2021-06-15 16:07:24 +03:00
|
|
|
|
2021-07-09 17:13:39 +03:00
|
|
|
This plugin currently depends on some unstable features introduced in Metro
|
|
|
|
[0.66.1](https://github.com/facebook/metro/releases/tag/v0.66.1). Breaking
|
|
|
|
changes were introduced in Metro 0.60, so this plugin will not work with React
|
|
|
|
Native below 0.64.
|
2021-06-15 16:07:24 +03:00
|
|
|
|
|
|
|
## Usage
|
|
|
|
|
|
|
|
esbuild works best when we pass it ES6 modules. The first thing we must do is to
|
|
|
|
disable import/export transformation by enabling `disableImportExportTransform`
|
|
|
|
in `babel.config.js`:
|
|
|
|
|
|
|
|
```diff
|
|
|
|
module.exports = {
|
|
|
|
presets: [
|
|
|
|
[
|
|
|
|
"module:metro-react-native-babel-preset",
|
|
|
|
+ { disableImportExportTransform: true },
|
|
|
|
],
|
|
|
|
],
|
|
|
|
};
|
|
|
|
```
|
|
|
|
|
|
|
|
Next, configure Metro to use the esbuild serializer by making the following
|
|
|
|
changes to `metro.config.js`:
|
|
|
|
|
|
|
|
```diff
|
|
|
|
const { makeMetroConfig } = require("@rnx-kit/metro-config");
|
|
|
|
+const {
|
|
|
|
+ MetroSerializer,
|
|
|
|
+ esbuildTransformerConfig,
|
|
|
|
+} = require("@rnx-kit/metro-serializer-esbuild");
|
|
|
|
|
|
|
|
module.exports = makeMetroConfig({
|
|
|
|
projectRoot: __dirname,
|
|
|
|
+ serializer: {
|
|
|
|
+ customSerializer: MetroSerializer(),
|
|
|
|
+ },
|
|
|
|
+ transformer: esbuildTransformerConfig,
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
We can now create a bundle as usual, e.g.:
|
|
|
|
|
|
|
|
```sh
|
|
|
|
react-native bundle --entry-file index.js --platform ios --dev false ...
|
|
|
|
```
|
2021-07-20 12:40:44 +03:00
|
|
|
|
|
|
|
## Known Limitations
|
|
|
|
|
|
|
|
- Dev server may not work with this serializer. To work around this limitation,
|
|
|
|
you can save the esbuild specific Metro config to a separate file and only
|
|
|
|
specify it when needed, e.g.:
|
|
|
|
```sh
|
|
|
|
react-native bundle ... --config metro+esbuild.config.js
|
|
|
|
```
|