返回博客首页
← 所有文章

如何在 NativeScript 中使用任何 npm 模块

2017年3月14日 — 作者:Eddy Verbruggen

npm-transparent
为什么要使用 npm 模块?

你想重新发明汽车的轮子,还是直接开车?就是这样。

庞大的npm 注册表托管着数十万个现成的模块,你可以直接将其添加到你的应用程序中。从左填充完善的日期处理,从电子邮件地址验证亚马逊的 AWS SDK。所有这些都可以在 npm 上找到,等待你使用 "npm install" 安装它们。

这也是所有 NativeScript 插件,甚至NativeScript 本身的分发位置。

听起来不错,我要安装所有这些模块!

等等!慢点,士兵。虽然 NativeScript 使用 JavaScript(从 TypeScript 转换而来或直接使用)并且 npm 模块也用 JavaScript 编写,但你不能简单地安装任何模块并期望它能够工作。

最初,npm 模块被设计为在一个专用的运行时环境中工作:Node。这意味着模块有时期望在 Node 运行时环境中运行,并使用内置的 Node 模块来例如访问文件系统或执行加密函数。

浏览器呢?它们也使用 npm 模块,对吧?

好问题。确实如此。这就是 polyfill(或 shim)的作用所在。你可能听说过 Browserify——它(除其他外)会在 npm 模块的package.json中查找浏览器声明,并将maindependencies中任何也在browser中的内容进行替换。让我给你举个例子。这是aws-sdkpackage.json的相关部分

AWS SDK package.json 的 browserify 部分

模块作者使用插件提供了浏览器友好的 JavaScript 代码版本,Browserify 在为浏览器构建时会简单地将默认实现替换为浏览器实现。

此外,许多与 Node 一起提供的内置模块也已经使用浏览器版本进行了 polyfill,因此 Browserify 能够“修复”绝大多数 npm 模块,并允许它们在浏览器中运行。

所以……让我们应用我们在这里学到的知识!

一个(部分)解决方案

Browserify 对浏览器所做的,我们也可以对 NativeScript 运行时环境做。但是,我们不想强迫你和你项目使用像 Browserify 或 Webpack 这样的工具(我们也需要更多灵活性),因此nativescript-nodeify 插件被创建为一个特殊用途的工具,用于将依赖项树中的任何内置 Node 模块替换为 NativeScript 兼容的实现。

限制

虽然 NativeScript 不是 Node 运行时环境,但它也不是浏览器。因此,并非所有浏览器 polyfill 都可以在 NativeScript 运行时环境中工作。这就是为什么我们需要比盲目替换浏览器兼容模块更进一步的原因。例如,stream-http,Node 原生 http 模块的一个流行 polyfill,使用global.location.protocol.search,这在 NativeScript 中并不存在。

这就是需要 NativeScript 特定 polyfill 的地方。比如这个用于randombytes这个用于xml2js,或者这个用于fs

nativescript-nodeify 插件知道哪些 polyfill 最适合 NativeScript,但像上面stream-http的例子一样,总会有需要额外工作才能解决的特殊情况。

如何使用该插件?

你可以像往常一样安装依赖项,以及这个插件,然后在构建时,该插件安装的钩子会扫描并修改你的模块,使其适合 {N} 兼容。

例如,看看当你安装node-uuid(运行npm install node-uuid --save)时会发生什么。此模块在这一行中使用了 Node 的内置crypto库,这在浏览器和 NativeScript 中都不起作用。所以让我们在我们的应用程序中require该模块,看看运行时会发生什么

node-uuid-without-nodeify.js

崩溃了!太糟糕了!

让我们通过运行tns plugin add nativescript-nodeify来安装插件,并再次运行完全相同的代码

node-uuid-with-nodeify.js

没有崩溃!更好的是,你得到了你梦寐以求的随机 UUID!

结论

如果你遇到一个不立即与 NativeScript 兼容的 npm 模块,请添加nativescript-nodeify 插件并重新构建你的应用程序。

如果运行时仍然存在问题,请在 GitHub 上提交一个 issue,看看我们是否可以一起解决它,并进一步增强 NativeScript 的 npm 支持!