Search code examples
react-nativemobxmetro-bundler

Use optimized es6 build of MobX for React Native in Metro config


I'm trying to use the optimized, es6 build of Mobx, as per the documentation:

Tip: the main entry point of the MobX 5 package ships with ES5 code for backward compatibility with all build tools. But since MobX 5 runs only on modern browsers anyway, consider using the faster and smaller ES6 build: lib/mobx.es6.js. For example by setting up a webpack alias: resolve: { alias: { mobx: __dirname + "/node_modules/mobx/lib/mobx.es6.js" }}

https://mobx.js.org/README.html#browser-support

This allows me to import mobx and get the mobx.es6.js build:

import mobx from 'mobx' // Yay, es6 build!!!

This works great for Webpack-based projects, such as Electron ones, where I already have it working.

For React Native, I can specify extraNodeModules in metro.config.js like so:

module.exports = {
    resolver: {
        extraNodeModules: {
            "mobx": path.resolve(__dirname, 'node_modules/mobx/lib/mobx.es6.js'),
        },
    },
};

...except that doesn't work, I presume, because the mobx dependency resolves fine on its own, and so this configuration option is never checked.

I can use a separate alias for mobx, such as mobx-es6 but that's not ideal, to put it nicely:

module.exports = {
    resolver: {
        extraNodeModules: {
            // Nooo I don't want to update a bazillion source files!.
            "mobx-es6": path.resolve(__dirname, 'node_modules/mobx/lib/mobx.es6.js'),
        },
    },
};

Is there some other way to configure Metro so that I can override the mobx import like I can with Webpack?

I'm using RN 0.60.0.


Solution

  • The solution is to add a browser section to package.json:

        "name": "My React Native Project",
        "version": "0.0.1",
        "browser": {
            "mobx": "mobx/lib/mobx.es6.js"
        },
    

    This is undocumented, AFAICT, but there are hints here:

    resolverMainFields

    Type: Array<string>

    Specify the fields in package.json files that will be used by the module resolver to do redirections when requiring certain packages. For example, using ['browser', 'main'] will use the browser field if it exists and will default to main if it doesn't.

    https://facebook.github.io/metro/docs/configuration#resolvermainfields

    import mobx from 'mobx' // Yay, es6 build!!!