🚇 The JavaScript bundler for React Native. https://facebook.github.io/metro
Go to file
Adam Liechty f347e4ff47 Expose createModuleIdFactory as bundler option
Summary:
**Summary**

`createModuleIdFactory` is already used in `metro` internally, but is currently always a fixed function.
This enables `metro.runBuild()` to be run with a custom module ID factory.

One use case: building a base bundle, on top of which other application-specific bundles could reference modules in the base.  The application-specific IDs need to not conflict with those in the base bundle, and all references to modules in the base must resolve to the correct ID in the base bundle.  A custom ID factory can make all this possible.

**Test plan**

<!-- Demonstrate the code is solid. Example: The exact commands you ran and their output, screenshots / videos if the pull request changes UI. -->

Using `metro.runBuild(...)` with these changes, I was able to substitute in a custom ID factory

```javascript
const fs = require('fs')
const metro = require('metro')

const baseManifestFileContents = JSON.parse(fs.readFileSync('./baseManifest.json'))
// baseManifest looks like:
// { "modules": { ...
//    "react/index.js": { "id": 12 },
//    "react/cjs/react.production.min.js": { "id": 13 }, ...  } }

const opts = {
  dev: false,
  entry: 'index.js',
  out: './out.bundle',
  platform: 'ios',
  projectRoots: ['.', 'node_modules'],
  config: {
    createModuleIdFactory: createModuleIdFactory(baseManifestFileContents)
  }
}

metro.runBuild(opts)

// Creates a sample custom ID factory
function createModuleIdFactory(manifestFileContents) {
  return function createModuleIdFactory() {
    const fileToIdMap = new Map()
    let nextId = manifestFileContents ? getNextIdAfterBaseManifest(manifestFileContents) : 0

    return path => {
      const sourcePath = path
        .replace(process.cwd() + '/node_modules/', '')
        .replace(process.cwd(), '.')

      // If module is in the base manifest, return its ID
      if (manifestFileContents && manifestFileContents.modules[sourcePath]) {
        return manifestFileContents.modules[sourcePath].id
      }

      // Otherwise, get it from the map or create a new ID
      if (!fileToIdMap.has(path)) {
        fileToIdMap.set(path, nextId)
        nextId += 1
      }
      return fileToIdMap.get(path)
    }
  }

  function getNextIdAfterBaseManifest(manifestFileContents) {
    return Object.keys(manifestFileContents.modules).reduce((id, key) => {
      if (manifestFileContents.modules[key].id > id) {
        return manifestFileContents.modules[key].id
      }
      return id
    }, 0) + 1
  }
}
```

With the sample module ID factory above, the output looks like the following, where defined module IDs start at a higher number to avoid the base module IDs, but may depend on modules in the base bundle (lower numbers).

```javascript
...
__d(function(r,o,t,i,n){t.exports=r.ErrorUtils},551,[]);
__d(function(n,t,o,r,u){'use strict';var e,c=t(u[0]);e=c.now?function(){return c.now()}:function(){return Date.now()},o.exports=e},552,[553]);
...
__d(function(e,t,r,s,l){'use strict'; ...},564,[18,565,27]);
...
```
Closes https://github.com/facebook/metro/pull/100

Reviewed By: mjesun

Differential Revision: D6508351

Pulled By: rafeca

fbshipit-source-id: f2cfe5c373a6c83c8ae6c526435538633a7c9c2a
2017-12-08 06:29:23 -08:00
.github Rename metro-bundler to metro 2017-11-30 11:56:25 +00:00
docs Capitalized ‘Express’ 2017-12-05 11:29:42 -08:00
flow-typed Upgrade to 1.9.1 2017-12-06 17:31:38 -08:00
packages Expose createModuleIdFactory as bundler option 2017-12-08 06:29:23 -08:00
scripts Rename metro-bundler to metro 2017-11-30 11:56:25 +00:00
website Fix 404 on front page 'Learn more' link 2017-12-07 13:01:55 -08:00
.babelrc fix support for node v4 2017-06-26 05:08:50 -07:00
.eslintignore Initial repository structure. 2017-01-26 12:56:40 +00:00
.eslintrc Add prettier to metro-bundler, fixing code styling issues 2017-06-12 01:20:50 -07:00
.flowconfig @allow-large-files [flow] deploy flow 0.60 2017-12-04 13:30:30 -08:00
.gitignore Rename metro-bundler to metro 2017-11-30 11:56:25 +00:00
.npmignore Initial repository structure. 2017-01-26 12:56:40 +00:00
.travis.yml Initial repository structure. 2017-01-26 12:56:40 +00:00
CHANGELOG.md Rename metro-bundler to metro 2017-11-30 11:56:25 +00:00
CODE_OF_CONDUCT.md Add CODE_OF_CONDUCT.md 2017-11-22 02:58:16 -08:00
CONTRIBUTING.md Rename metro-bundler to metro 2017-11-30 11:56:25 +00:00
LICENSE Rename metro-bundler to metro 2017-11-30 11:56:25 +00:00
PATENTS Rename metro-bundler to metro 2017-11-30 11:56:25 +00:00
README.md Rename metro-bundler to metro 2017-11-30 11:56:25 +00:00
appveyor.yml Initial repository structure. 2017-01-26 12:56:40 +00:00
circle.yml Add script to automatically deploy the website 2017-11-30 04:03:29 -08:00
lerna.json Bump metro@0.23.0 2017-12-05 09:28:57 -08:00
package.json Update flow-bin version 2017-12-08 05:28:57 -08:00
yarn.lock Upgrade to 1.9.1 2017-12-06 17:31:38 -08:00

README.md

Metro Bundler

CircleCI Build Status npm version

🚇 The JavaScript bundler for React Native.

  • 🚅 Fast: We aim for sub-second reload cycles, fast startup and quick bundling speeds.
  • ⚖️ Scalable: Works with thousands of modules in a single application.
  • ⚛️ Integrated: Supports every React Native project out of the box.

This project was previously part of the react-native repository. In this smaller repository it is easier for the team working on Metro Bundler to respond to both issues and pull requests. See react-native#13976 for the initial announcement.

Installation & Documentation

See the Metro website for documentation.