在 Node-Browser(Isomorphic) 库中使用流或任何 Node.js 库

Using stream or any Node.js library in a Node-Browser(Isomorphic) library

我正在开发一个 Node-Browser(同构)库,其中的源代码是用 TypeScript 编写的,并转换为 CJS 和 ES 模块。 转译后的代码按原样发送,在发布前未使用模块捆绑器捆绑。

我需要使用 node core 中的流模块,我打算在浏览器部分使用 stream-browserify 包。

  1. 在库中包括使用 Node.js 流或任何节点特定库的最佳方法是什么?
  2. 如何在无需重写相同代码或尽可能减少重复的情况下包含 stream-browserify?
  3. 我遇到了一些示例,其中 package.json 中的浏览器字段使用如下 -
   "browser" : {
       "stream":"stream-browserify";
   } 

这是如何工作的?

您将需要配置用于转换代码以理解已安装模块的任何工具。

如果你没有捆绑你的代码,这意味着你在导入每个单独的文件时加载它(我不确定你是怎么做的或打算用 CJS 做到这一点,因为没有 require() API 在浏览器中)。但是,如果我import foo from "some-library";some-library是第三方包,需要加载的JavaScript文件需要以某种方式导入。

这意味着三件事:

  1. 您需要模块的代码,这意味着您需要实际安装它(您将使用 package.json 中的 dependencies 散列来执行此操作)。
  2. 您需要能够导入代码。这意味着您的 import 语句需要由您的 transpiler/bundler/etc 重写。指向可访问的路径。 import foo from 'some-library'; 需要将 'some-library' 翻译成类似 node_modules/some-library/src/index.js 的内容。否则浏览器如何知道要加载什么以及从哪里加载?
  3. 您需要对要导入的库的内部结构执行相同的操作,因为它们也需要重写导入。

您提到的 browser 散列将代码中导入的模块名称映射到该模块的浏览器友好版本。您列出的示例意味着 require('stream') 在为浏览器编译时变为 require('stream-browserify'),在为 Node 编译时变为 require('stream')

对于上面的 #2 和 #3,TypeScript(或者更确切地说,tsc)不会为你做那件事。它 听起来 就像您想要 Snowpack 这样的工具。但是,有一些事情需要注意。

首先,你不能 运行 任何 浏览器中的 Node 模块,或者至少在没有更高级的工具如 Webpack 的情况下不能 mock/rewrite/replace在浏览器中需要 Node 和 cannot 运行 的依赖项。如果您导入的模块需要另一个不是浏览器安全的模块,您将不知道它不是浏览器安全的,直到它在 运行 时间抛出错误(无论是 JS 错误还是来自您的服务器的 404 ).

其次,您可能确实需要一个捆绑器。如果您使用的是 Node 模块,则依赖树会变得非常深。如果你的 node_modules/ 目录中有 5,000 个 JS 文件,那就是 5,000 个网络请求——其中许多需要串行加载、解析和执行(即,在导入它们的模块加载和解析之后)。像 tree shaking 这样的优化离不开打包器:即使是用于生产目的的 Snowpack recommends creating an optimized build

就是说,如果您要发布一个包(也就是说,您要将其上传到 NPM 而不是将其部署到您自己的服务器),这主要是没有实际意义的。只需按照通常的方式编写代码,在 dependencies 中列出依赖项,在 browser 中列出浏览器安全的等效项,然后发布转译后的源代码。实际使用您的库的人会担心如何加载它。如果您不发布到 NPM(也就是说,您自己将此代码放在 Web 上),请考虑使用捆绑器。打包器并不妨碍您拥有同构库:您可以在浏览器和 Node 中拥有一个 运行s 的单个 JS 文件,或者您可以拥有两个输出文件(一个浏览器,一个 Node),它们是从同一个来源。如何实现这一目标取决于您的目标。