如何在 React Native 中使用浏览器化库
How to use browserified libraries in React Native
我有一个库,我想在已浏览器化的 React Native 项目中使用。当我需要库时,所有内部 require() 调用都会被劫持,而不是解析我包含的文件内部的依赖项,React Native 会尝试解析它们,从而导致它中断。我想知道在 React Native 项目中包含浏览器化库的正确方法是什么。
我想到的最好的解决方案是切换到 webpack。正如其中一条评论中提到的,该库需要通过 browserify 或 web pack 之类的东西来处理,因为它在节点内置函数上有一些优点,比如 'domain'。问题是 browserify 声明了一个 require() 方法,它在 React Native 中表现不佳,它也有一个 require() 方法。切换到 webpack 解决了这个问题,因为他们以不同的方式命名 require(),__webpack_require() 并且这允许处理后的版本在 React Native 中正常工作。
恕我直言,比浏览器化 Node 库更好的方法是
- 为节点 built-ins 使用 browserify polyfill,例如
crypto
、stream
等,
- a small Babel transform 将
require()
调用从 crypto
重写为 crypto-browserify
等,
- 和 React Native 打包器本身将其全部打包。
ReactNativify 存储库演示了如何执行所有这些操作。
如果您决定使用 ReactNativify 建议的方法,如 Philipp von Weitershausen, then you should be aware of some considerations and tips (originally posted 所建议的那样):
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
我有一个库,我想在已浏览器化的 React Native 项目中使用。当我需要库时,所有内部 require() 调用都会被劫持,而不是解析我包含的文件内部的依赖项,React Native 会尝试解析它们,从而导致它中断。我想知道在 React Native 项目中包含浏览器化库的正确方法是什么。
我想到的最好的解决方案是切换到 webpack。正如其中一条评论中提到的,该库需要通过 browserify 或 web pack 之类的东西来处理,因为它在节点内置函数上有一些优点,比如 'domain'。问题是 browserify 声明了一个 require() 方法,它在 React Native 中表现不佳,它也有一个 require() 方法。切换到 webpack 解决了这个问题,因为他们以不同的方式命名 require(),__webpack_require() 并且这允许处理后的版本在 React Native 中正常工作。
恕我直言,比浏览器化 Node 库更好的方法是
- 为节点 built-ins 使用 browserify polyfill,例如
crypto
、stream
等, - a small Babel transform 将
require()
调用从crypto
重写为crypto-browserify
等, - 和 React Native 打包器本身将其全部打包。
ReactNativify 存储库演示了如何执行所有这些操作。
如果您决定使用 ReactNativify 建议的方法,如 Philipp von Weitershausen, then you should be aware of some considerations and tips (originally posted
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