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

问题描述 投票:0回答:4

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

react-native browserify
4个回答
2
投票

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

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
投票

我想出的最好的解决方案是切换到 webpack。正如评论之一所提到的,该库需要由 browserify 或 web pack 之类的东西进行处理,因为它在像“domain”这样的节点内置程序上有礼貌。问题是 browserify 声明了一个 require() 方法,该方法在 React Native 中表现不佳,因为 React Native 也有一个 require() 方法。切换到 webpack 解决了这个问题,因为它们将 require() 命名为 __webpack_require(),这使得处理后的版本可以在 React Native 中正常工作。


0
投票

恕我直言,比浏览器化 Node 库更好的方法是

  • 使用 Node 内置的 browserify polyfills,如
    crypto
    stream
    等,
  • 一个小的 Babel 变换,重写从
    require()
    crypto
    等的
    crypto-browserify
    调用,
  • React Native 打包器本身将其全部打包。

ReactNativify 存储库演示了如何做到这一切。


0
投票
这来得很晚,但我找到了一个更简单的解决方案,至少对我来说到目前为止它是有效的。 Browserify 创建了自己的“require”,但 React Native 以一种特殊的方式处理 require 来解释错误。因此,我在 vscode 中打开浏览器化模块,并将“require”的所有实例替换为不属于代码一部分的其他内容,例如“reqqquire”。这使得模块能够正常工作。并且不要忘记通过创建导出模块的全局变量并将导出语句移出浏览器化函数来使 module.exports 成为全局变量。

© www.soinside.com 2019 - 2024. All rights reserved.