在React Native中使用Node.js库的妙招
去发现同类优质开源项目:https://gitcode.com/
在前端开发世界里,像browserify和webpack这样的工具已经让Node.js环境中的代码可以在浏览器环境中运行变得轻而易举。即使我们只针对浏览器进行开发,Node.js的标准库也提供了强大的Buffer实现、流API以及URL解析,使得Node.js成为JavaScript开发者的一个颇具吸引力的平台。
React Native打包器
然而,在React Native的世界里情况如何呢?理论上,React Native并不局限于特定的打包器,它可以加载从文件或URL获取的JavaScript包,无论这个包是如何准备的。所以,理论上来说,使用browserify或webpack是可行的。但实际上,事情复杂多了:
- React Native内部使用Haste模块系统。我们只能期望React Native能在某个时刻像React一样,将Haste的requires转换为Node.js风格的requires,以扩大其他打包器的使用范围。
- 只要Facebook内部还在使用React Native打包器,React Native就会始终与之配合得最好。曾经我维护过一个名为react-native-webpack-server的混合解决方案,它试图使用React Native自身的打包器来处理React Native本身的部分,而其余应用部分则使用webpack打包。但事实证明,上游React Native的变化多次导致我们的代码出问题,我们必须先修复自己的打包器才能升级到最新版的React Native。
- React Native在很多地方假设你正在使用它的打包器。例如,Xcode项目会在调试模式下自动为你启动打包器,你无法选择其他的。
简而言之,目前押注于React Native打包器是一个明智的选择。
那么,如果我们被限制在这个打包器上,怎么利用Node.js的库呢?
自定义变换器
React Native打包器有一个鲜为人知的可插拔组件——变换器。这是一个函数,可以接受给定的源文件,并通常使用Babel将其转换,将所有花哨的ES2015语法替换为JavaScriptCore能解析的内容。我们可以提供自定义的变换器,结合Babel-plugin-rewrite-require插件,以及browserify对Node.js核心库的重新实现,这样就可以使原本为Node.js编写的任何代码在React Native环境中运行。
工作原理
-
在你的React Native项目顶部创建一个
rn-cli.config.js
文件。这个文件会被React Native CLI加载以加载额外的配置。你可以通过它指定一些选项,这些选项在其他情况下可能需要通过命令行参数传递。但请注意,XCode项目会自动调用打包器,不让你指定额外的参数。查看本项目中的rn-cli.config.js
文件,了解其可能指定的选项及其解释。 -
提供你自己的变换器实现。参考本项目中的
transformer.js
示例,它使用了Babel-plugin-rewrite-require来重写对核心Node.js模块的导入,转化为它们的browserify等价物。browserify的polyfill是通过node-libs-browser
包安装的。你需要npm3来安装这个项目,以便所有的依赖都在一个扁平的目录结构中。 -
确保将必要的符号注入全局命名空间。许多Node.js库期望
Buffer
和process
(以及其他)在全局命名空间中可用。查看本项目的global.js
,这里有一个例子。 -
就像你在使用Node.js那样编写代码。
crypto_example.js
文件在本项目中提供了一个示例,它使用了Node.js的stream和crypto模块。你可以用node node.js
单独执行它,验证其在Node.js中的工作情况。多亏上述步骤实现的机制,它在React Native中也能正常工作(尽管速度慢一些)。记住,这只是个示例...
注意事项
React Native打包器非常敏感于以下场景:
-
缺少文件。虽然webpack在这种情况下会继续运行,但React Native打包器在依赖解析期间会因缺少文件而中断。我在Babel-plugin-rewrite-require中尝试解决这个问题,但效果因情况而异。
-
符号链接。React Native打包器在服务器开发模式和发布模式的捆绑过程中解析符号链接的方式不同。建议不要依赖符号链接,而是通过
rn-cli.config.js
中的getProjectRoots
添加额外的搜索路径。 -
重复模块。不要让React Native打包器发现React Native的多个安装副本。尽量确保模块都位于同一个大目录树下,且该目录树的根应该是打包器的项目根。
-
package.json
别名。React Native打包器仅在其自身包内解析browser
或react-native
别名,而其他工具如webpack则不管上下文如何都会尊重这些别名。
反馈
我不能保证能够回应所有提交的问题,但它们肯定是受欢迎的。当然,更欢迎Pull Request。
这个开源项目提供了一种创新的方法,使React Native开发者能够在他们的应用中充分利用Node.js的强大功能,而不受打包器的限制。通过自定义变换器和巧妙地处理全局符号,开发者现在可以在React Native中无缝使用Node.js库,扩展其应用的可能性。如果你的项目中需要处理复杂的逻辑或者需要使用Node.js特有的API,这个项目无疑是值得尝试的。
去发现同类优质开源项目:https://gitcode.com/