如何在React Native中使用浏览器化的库

时间:2016-11-24 02:50:31

标签: react-native browserify

我有一个库,我想在已经浏览化的React Native项目中使用。当我需要库时,所有内部require()调用都被劫持,而不是解析我所包含的文件内的依赖关系,React Native尝试解析它们,从而导致它中断。我想知道在React Native项目中包含浏览化库的正确方法是什么。

3 个答案:

答案 0 :(得分:2)

如果您决定按照Philipp von Weitershausen的建议使用ReactNativify建议的方法,那么您应该了解一些注意事项和提示(最初发布here):

1)我按照我在问题列表中找到的建议,将transformer.js分成两部分:

transformers.js(在/config中并从rn-cli.config.js调用):

const babelTransformer = require('./babel-transformer');

module.exports.transform = function(src, filename, options) {

    const extension = String(filename.slice(filename.lastIndexOf('.')));
    let result;

    try {

        result = babelTransformer(src, filename);

    } catch (e) {

        throw new Error(e);
        return;
    }

    return {
        ast: result.ast,
        code: result.code,
        map: result.map,
        filename
    };
};

babel-transformer.js(也在/config中):

'use strict'

const babel = require('babel-core');

/**
 * This is your `.babelrc` equivalent.
 */
const babelRC = {
    presets: ['react-native'],
    plugins: [

    // The following plugin will rewrite imports. Reimplementations of node
    // libraries such as `assert`, `buffer`, etc. will be picked up
    // automatically by the React Native packager.  All other built-in node
    // libraries get rewritten to their browserify counterpart.

    [require('babel-plugin-rewrite-require'), {
        aliases: {
            constants: 'constants-browserify',
            crypto: 'react-native-crypto',
            dns: 'mock/dns',
            domain: 'domain-browser',
            fs: 'mock/empty',
            http: 'stream-http',
            https: 'https-browserify',
            net: 'mock/net',
            os: 'os-browserify/browser',
            path: 'path-browserify',
            pbkdf2: 'react-native-pbkdf2-shim',
            process: 'process/browser',
            querystring: 'querystring-es3',
            stream: 'stream-browserify',
            _stream_duplex: 'readable-stream/duplex',
            _stream_passthrough: 'readable-stream/passthrough',
            _stream_readable: 'readable-stream/readable',
            _stream_transform: 'readable-stream/transform',
            _stream_writable: 'readable-stream/writable',
            sys: 'util',
            timers: 'timers-browserify',
            tls: 'mock/tls',
            tty: 'tty-browserify',
            vm: 'vm-browserify',
            zlib: 'browserify-zlib'
        },
        throwForNonStringLiteral: true
    }],

    // Instead of the above you could also do the rewriting like this:

    ["module-resolver", {
      "alias": {
        "mock": "./config/mock",
        "sodium-universal": "libsodium"
      }
    }]
    ]
};

module.exports = (src, filename) => {

    const babelConfig = Object.assign({}, babelRC, {
    filename,
    sourceFileName: filename
    });

    const result = babel.transform(src, babelConfig);
    return {
    ast: result.ast,
    code: result.code,
    map: result.map,
    filename
    };
}

2)正如您在上面的代码中所看到的,我还演示了使用babel-plugin-module-resolver

注意,我将使用此插件而不是ReactNative使用的插件。它允许您引用本地文件,并使用适当的引号编写允许非JS兼容的名称,如'sodium-universal'

Note2 或者按照此评论中的说明选择.babelrc解决方案(可能最干净):https://github.com/philikon/ReactNativify/issues/4#issuecomment-312136794

3)我发现我的项目根目录中仍然需要一个.babelrc来让我的Jest测试工作。有关详细信息,请参阅此问题:https://github.com/philikon/ReactNativify/issues/8

答案 1 :(得分:0)

我提出的最佳解决方案是切换到webpack。正如其中一条评论中所提到的,图书馆需要像浏览器或网络包一样处理,因为它在节点内置像“域”上有优势。问题是browserify声明了一个require()方法,它在React Native中也没有很好用,它也有一个require()方法。切换到webpack解决了这个问题,因为他们将其require()命名为__webpack_require(),这样就可以使处理后的版本在React Native中正常工作。

答案 2 :(得分:0)

恕我直言,比浏览节点库更好的方法是

  • 将browserify polyfills用于{@ 1}},crypto等节点内置插件,
  • a small Babel transform重写从streamrequire()等的crypto来电,
  • 和React Native包装程序本身将它打包。

ReactNativify回购展示了如何做到这一切。