Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 32 additions & 12 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,31 +44,37 @@ title: Bundling API

## Reference

All functions exposed below accept an additional `config` option. This object should be the [Metro configuration](CLI.md) exposed by your `metro.config.js` file - you can obtain it using `Metro.loadConfig`.
The `config` object accepted by the functions below is the [Metro configuration](./Configuration.md) exported by your `metro.config.js` file, which you can obtain with `Metro.loadConfig`.

### `loadConfig(<options>)`
### `loadConfig(<options>, <defaultConfigOverrides>)`

**Basic options:** `config`, `cwd`

Load the Metro configuration, either from `config` in options if specified, or by traversing the directory hierarchy from `cwd` to the root until it finds a file (by default `metro.config.js`). The returned configuration will have been normalized and merged with Metro's default values.
Load the Metro configuration, either from the path given in `config` if specified, or by traversing the directory hierarchy from `cwd` up to the user's home directory until it finds a [config file](./Configuration.md). The returned configuration will have been normalized and merged with Metro's default values, after applying `defaultConfigOverrides` to the defaults.

### `async runMetro(config)`
`loadConfig` also accepts the options of the [CLI](./CLI.md), which override the corresponding config values: `port` ([`server.port`](./Configuration.md#port)), `projectRoot`, `watchFolders`, `assetExts`, `sourceExts` and `platforms` (the `resolver` options of the same names), [`maxWorkers`](./Configuration.md#maxworkers) (which defaults to a number based on `os.availableParallelism()`), `transformer` ([`transformer.babelTransformerPath`](./Configuration.md#babeltransformerpath)), `resetCache`, and `verbose` (`false` silences Metro's terminal output).

Creates a Metro server based on the config and returns it. You can use this as a middleware in your existing server.
### `async runMetro(config, <options>)`

**Basic options:** `waitForBundler`, `watch`, `onBundleBuilt`, `hasReducedPerformance`

Creates a Metro server based on the config and returns it. Its `processRequest` method can be used as a middleware in your existing server. `hasReducedPerformance` only makes Metro's terminal output warn that Metro is operating with reduced performance.

### `async runBuild(config, <options>)`

**Required options:** `entry`, `out`
**Required options:** `entry`

**Basic options:** `out`, `bundleOut`, `sourceMapOut`, `dev`, `minify`, `platform`, `sourceMap`, `sourceMapUrl`, `assets`, `onBegin`, `onProgress`, `onComplete`, `customResolverOptions`, `customTransformOptions`, `output`

**Basic options:** `dev`, `minify`, `platform`, `sourceMap`, `sourceMapUrl`, `assets`
Bundles `entry` for the given `platform` (defaults to `'web'`). If `out` or `bundleOut` is given, saves the bundle to `bundleOut`, or to `out` with a `.js` extension. If `sourceMap` is set, also generates a source map. The source map will be inlined, unless `sourceMapUrl` is also defined, in which case `sourceMapUrl` is used as the bundle's `sourceMappingURL`. When saving to disk, the source map is also written to `sourceMapOut`, or to `out` with a `.map` extension. If `assets` is `true`, an array of `AssetData` will be generated and returned in the `assets` property of the result object.

Bundles `entry` for the given `platform`, and saves it to location `out`. If `sourceMap` is set, also generates a source map. The source map will be inlined, unless `sourceMapUrl` is also defined. In the latter case, a new file will be generated with the basename of the `sourceMapUrl` parameter. If `assets` is `true`, an array of `AssetData` will be generated and returned in the `assets` property of the result object.
`output` replaces how the bundle is built and written to disk. It is an object with two functions: `build(server, requestOptions, buildOptions)`, whose result `runBuild` resolves to and passes to `save`, and `save(bundle, outputOptions, log)`, which is only called if `out` or `bundleOut` is given. Defaults to Metro's plain bundle output, `metro/private/shared/output/bundle`. For example, `require('metro/private/shared/output/RamBundle')` writes a [RAM bundle](./Bundling.md#indexed-ram-bundle) instead.

### `async runServer(config, <options>)`

**Basic options:** `host`, `port`, `secureServerOptions`, `unstable_middleware`, `unstable_priorityMiddleware`, `unstable_onServerCreated`, `secure (DEPRECATED)`, `secureKey (DEPRECATED)`, `secureCert (DEPRECATED)`
**Basic options:** `host`, `onReady`, `onClose`, `onError`, `waitForBundler`, `watch`, `hasReducedPerformance`, `websocketEndpoints`, `secureServerOptions`, `unstable_middleware`, `unstable_priorityMiddleware`, `unstable_onServerCreated`, `secure (DEPRECATED)`, `secureKey (DEPRECATED)`, `secureCert (DEPRECATED)`

Starts a full Metro HTTP server. It will listen on the specified `host:port`, and can then be queried to retrieve bundles for various entry points. If the `secureServerOptions` family of options are present, the server will be exposed over HTTPS.
Starts a full Metro HTTP server. It will listen on the specified `host` and [`server.port`](./Configuration.md#port), and can then be queried to retrieve bundles for various entry points. If `secureServerOptions` or [`server.tls`](./Configuration.md#tls) is present, the server will be exposed over HTTPS. Resolves to `{httpServer}`.

`unstable_middleware` and `unstable_priorityMiddleware` take the same shapes as [`server.unstable_middleware`](./Configuration.md#unstable_middleware-experimental) and [`server.unstable_priorityMiddleware`](./Configuration.md#unstable_prioritymiddleware-experimental), and wrap them: `unstable_middleware` passed here runs after the config's, and `unstable_priorityMiddleware` runs before the config's.

Expand All @@ -80,6 +86,20 @@ Priority middleware handlers must call `next()` for every request they don't ful

### `createConnectMiddleware(config, <options>)`

**Basic options:** `port`, `onBundleBuilt`
**Basic options:** `onBundleBuilt`, `watch`, `waitForBundler`, `hasReducedPerformance`

Instead of creating the full server, creates a Connect middleware that answers to bundle requests. This middleware can then be plugged into your own servers. Resolves to `{middleware, attachHmrServer(httpServer), metroServer, end()}`. The `onBundleBuilt` function is optional, is passed the bundle path, and is called when the server has finished creating the bundle.

### `async buildGraph(config, <options>)`

**Required options:** `entries`

**Basic options:** `dev`, `minify`, `platform`, `type`, `customTransformOptions`

Resolves and transforms the dependency graph for the given `entries` without serializing a bundle, and returns the graph.

### `attachMetroCli(yargs, <options>)`

**Basic options:** `build`, `serve`, `dependencies`

Instead of creating the full server, creates a Connect middleware that answers to bundle requests. This middleware can then be plugged into your own servers. The `port` parameter is optional and only used for logging purposes. The `onBundleBuilt` function is optional, is passed the bundle name, and is called when the server has finished creating the bundle.
Registers Metro's [CLI commands](./CLI.md) on a `yargs` instance. Pass `null` for a command to omit it.
22 changes: 12 additions & 10 deletions docs/Bundling.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,25 @@ When bundling, each of the modules gets assigned a numeric id, meaning no dynami

## Plain bundle

This is the standard bundling format. In this format, all files are wrapped with a function call, then added to the global file. This is useful for environments that expect a JS only bundle (e.g. a browser). Just requiring the entry point with the `.bundle` extension should trigger a build of it.
This is the standard bundling format. In this format, all files are wrapped with a function call (`__d()`, which registers the module with Metro's module system), then concatenated into a single file. This is useful for environments that expect a JS only bundle (e.g. a browser). Just requiring the entry point with the `.bundle` extension should trigger a build of it.

## Indexed RAM bundle

RAM (Random Access Modules) bundles store each module separately, so the app can load a module's code only when it is first required.

This format composes the bundle as a binary file, which format has the following parts (all numbers are expressed in Little Endian):

* A magic number: a `uint32` must be located at the beginning of the file, with the value `0xFB0BD1E5`. This is used to verify the file.
* An offset table: the table is a sequence of `uint32` pairs, with a header
* For the header, two `uint32`s can be found: the length of the table, and the length of the startup code.
* For the pairs, they represent the offset in the file and the length of code module, in bytes.
* Each of the modules, finished by a null byte (`\0`).
* For the header, two `uint32`s can be found: the number of table entries (highest module id + 1), and the length of the startup code, in bytes.
* For the pairs, they represent the offset of the module code relative to the start of the startup code, and the length of the module code, in bytes.
* The startup code, followed by each of the modules, each finished by a null byte (`\0`). The startup code runs when the bundle loads: polyfills, Metro's module system, [`preloadedModules`](./Configuration.md#gettransformoptions), and the call that runs the entry point.

```
` 0 1 2 3 4 5 6
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Magic number | Header size |
| Magic number | Number of entries |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Startup code size | Module 0 offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Expand All @@ -35,9 +37,9 @@ This format composes the bundle as a binary file, which format has the following
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | Module n offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Module n length | Module 0 code | Module 0 code | ... | \0 |
| Module n length | Startup code | Startup code | ... | \0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Module 1 code | Module 1 code | ... | \0 | |
| Module 0 code | Module 0 code | ... | \0 | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
| |
+ ... +
Expand All @@ -49,12 +51,12 @@ This format composes the bundle as a binary file, which format has the following

This structure is optimal for an environment that is able to load all code in memory at once:

* By using the offset table, one can load any module in constant time, where the code for module `x` is located at `file[(x + 3) * sizeof(uint32)]`. Since there is a null character (`\0`) separating all modules, usually length does not even need to be used, and the module can be loaded directly as an ASCIIZ string.
* Startup code is always found at `file[sizeof(uint32)]`.
* By using the offset table, one can load any module in constant time, where the offset/length entry for module `x` is located at `file[(3 + 2 * x) * sizeof(uint32)]`, and its code starts at that offset from the start of the startup code. Since there is a null character (`\0`) separating all modules, usually length does not even need to be used, and the module can be loaded directly as a null-terminated (ASCIIZ) string.
* Startup code is always found right after the offset table, at `file[(3 + 2 * numEntries) * sizeof(uint32)]`.

This bundling is usually used by iOS.

## File RAM bundle

Each module is stored as a file, with the name `js-modules/${id}.js`, plus an extra file called `UNBUNDLE` is created, which its only content is the magic number, `0xFB0BD1E5`. Note that the `UNBUNDLE` file is created at the root.
Each module is stored as a file, with the name `js-modules/${id}.js`, plus an extra file called `UNBUNDLE` is created, which its only content is the magic number, `0xFB0BD1E5`, and which marks the bundle as a file RAM bundle. Note that the `UNBUNDLE` file is created inside the `js-modules` directory, and the startup code is written to the bundle output file.
This bundling is usually used by Android, since package contents are zipped, and access to a zipped file is much faster. If the indexed format was used instead, all the bundled should be unzipped at once to get the code for the corresponding module.
44 changes: 32 additions & 12 deletions docs/CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,45 @@ Generates a JavaScript bundle containing the specified entrypoint and its descen

| Option | Alias | Description | Value |
|----------|----------|----------|----------|
| `out` | `O` | File name where to store the output | String |
| `platform` | `p` | Which platform to bundle for | `web`, `android`, `ios` |
| `out` | `O` | File name where to store the output (required) | String |
| `platform` | `p` | Which platform to bundle for (e.g. `web`, `android`, `ios`) | String |
| `minify` | `z` | Whether Metro should minify the bundle | Boolean |
| `dev` | `g` | Create a development version of the build (`process.env.NODE_ENV = 'development'`) | Boolean |
| `dev` | `g` | Create a development build, in which `__DEV__` is `true` | Boolean |
| `config` | `c` | Location of the `metro.config.js` to use | String |
| `max-workers` | `j` | The number of workers Metro should parallelize the transformer on | Number |
| `project-roots` | `P` | The root folder of your project | Array |
| `max-workers` | `j` | The number of workers Metro should parallelize the transformer on. Overrides [`maxWorkers`](./Configuration.md#maxworkers) which defaults to a number based on `os.availableParallelism()` | Number |
| `project-roots` | `P` | Accepted, but has no effect | Array |
| `source-map` | | Whether Metro should generate source maps | Boolean |
| `source-map-url` | | URL where the source map can be found | String |
| `legacy-bundler` | | Whether Metro should use the legacy bundler | Boolean |
| `legacy-bundler` | | Accepted, but has no effect | Boolean |
| `resolver-option` | | [Custom resolver options](./Resolution.md#customresolveroptions-string-mixed) of the form `key=value` | Array |
| `transform-option` | | Custom transform options of the form `key=value` | Array |
| `transform-option` | `transformer-option` | Custom transform options of the form `key=value` | Array |
| `reset-cache` | | **Deprecated.** Clears Metro's caches before building, like [`resetCache`](./Configuration.md#resetcache) | Boolean |
| `output-type` | `t` | Accepted, but has no effect | String |


## `serve`

Starts Metro on the given port, building bundles on the fly.
Alias: `start`

## `get-dependencies <entryFile>`
Starts Metro on the given port, building bundles on the fly. Restarts the server when the config file changes.

### Options

| Option | Alias | Description | Value |
|----------|----------|----------|----------|
| `host` | `h` | Host to listen on. Defaults to `localhost` | String |
| `port` | `p` | Port to listen on. Defaults to `8081`, overriding [`server.port`](./Configuration.md#port) | Number |
| `config` | `c` | Location of the `metro.config.js` to use | String |
| `max-workers` | `j` | The number of workers Metro should parallelize the transformer on. Overrides [`maxWorkers`](./Configuration.md#maxworkers) which defaults to a number based on `os.availableParallelism()` | Number |
| `secure-server-options` | `s` | Options for the HTTPS server, using dot notation (e.g. `-s.cert="$(cat path/to/cert)" -s.key="$(cat path/to/key)"`) | Object |
| `secure` | | **Deprecated.** Serve over HTTPS. Use `secure-server-options` instead | Boolean |
| `secure-key` | | **Deprecated.** Path to the key file for HTTPS when `secure` is set | String |
| `secure-cert` | | **Deprecated.** Path to the cert file for HTTPS when `secure` is set | String |
| `reset-cache` | | **Deprecated.** Clears Metro's caches on startup, like [`resetCache`](./Configuration.md#resetcache) | Boolean |
| `project-roots` | `P` | Accepted, but has no effect | Array |
| `hmr-enabled` | `hmr` | Accepted, but has no effect | Boolean |

## `get-dependencies [entryFile]`

List all dependencies that will be bundled for a given entry point.

Expand All @@ -44,6 +64,6 @@ List all dependencies that will be bundled for a given entry point.
| `output` | File name where to store the output, ex. /tmp/dependencies.txt |
| `platform` | The platform extension used for selecting modules |
| `transformer` | Specify a custom transformer to be used |
| `max-workers` | Specifies the maximum number of workers the worker-pool will spawn for transforming files. This defaults to the number of the cores available on your machine. |
| `dev` | If false, skip all dev-only code path |
| `verbose` | Enables logging |
| `max-workers` | Specifies the maximum number of workers the worker-pool will spawn for transforming files. Overrides [`maxWorkers`](./Configuration.md#maxworkers) which defaults to a number based on `os.availableParallelism()`. |
| `dev` | If false, skip all dev-only code path. Defaults to `true` |
| `verbose` | Enables logging. Defaults to `false` |
Loading
Loading