为节点和浏览器环境构建包

时间:2013-05-06 15:10:10

标签: javascript node.js npm

我开发了一个节点NPM包,它主要是一个特定JSON API的包装器(使用节点的httphttpsquerystring模块)。它是在Coffeescript中构建的,并使Node.js服务器能够与此API通信。 Api主要是REST。

现在我希望这个库也可用于浏览器。这意味着对http模块的调用需要替换为XMLHttpRequest(异步)。在我看来,我会为适配器做一个包装器。对于Node环境,此适配器会将所有调用传递给http模块,将浏览器环境传递给XMLHttpRequest对象。

有没有一个很好的方法来构建一个构建系统,以便npm包包含两个版本,我也可以在Github上发布简单的“浏览器版本”?然后,节点包可以通过require('package-name')获得,并且应该将JS文件(用于浏览器)放在目录中。

我查看了Component,这对于客户端软件包管理非常好,但问题仍然是如何创建不同的构建环境。

4 个答案:

答案 0 :(得分:5)

使用browserify对node.js和浏览器进行交叉开发的示例解决方案:https://github.com/amitayd/grunt-browserify-jasmine-node-exampleand discussion at my blog post)。

特别是对于Browser / Node.js的不同实现,请检查PersistentReaderWriter.js

一旦你有一些模板开始使用browserify,并且你意识到一些陷阱,你可能会发现你也想将它用于小型库。

编辑:请注意,如果浏览模块,则不应通过检查是否定义了module和module.exports来检查isBrowser(),因为Browserify的包装器将在模块上下文中定义它们。相反,在我的例子中,我检查要定义的窗口。

答案 1 :(得分:1)

在模块的末尾添加它。并像这样导出你的模块。

if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
  module.exports = YourModule;
}
else {
  if (typeof define === 'function' && define.amd) {
    define([], function() {
      return YourModule;
    });
  }
  else {
    window['YourModule'] = YourModule;
  }
}

答案 2 :(得分:0)

我找到了一个解决方案,虽然它不是第一个想到的,具有不同的构建环境。

在我的情况下,我有一个非常小的库,它使用Node的httphttpsquerystringurl包。我不想使用Browserify这样的东西,因为将所有这些包捆绑在一个小的api库中似乎不合适。相反,我将httphttps功能替换为XMLHttpRequest包。 querystringurl提供的小功能很容易被重写。

在我的库中,如果window.XMLHttpRequest对象可用,我会检查运行时。如果是这样,请使用该(本机)对象。否则,它使用包提供的那个。就这样:

_getRequestObject: () ->
  if window? and window.XMLHttpRequest?
    return new window.XMLHttpRequest()

  if window? and window.ActiveXObject?
    try
      request = new ActiveXObject('Msxml2.XMLHTTP')
    catch e
      try
        request = new ActiveXObject('Microsoft.XMLHTTP')
      catch e

  XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest
  return new XMLHttpRequest()

另一个问题是浏览器中未定义exports。有一些软件包可以模拟这种行为,但同样,它不想让文件库膨胀。所以我再次检查运行时是否设置了module变量。如果是这样,我定义的对象设置为,否则设置为window对象:

if typeof module is 'undefined'
  window['My-module'] = My_module_object
else
  module.exports = exports = My_module_object

这一切都适合我,因为我没有真正需要的Node.js依赖项,这些依赖项在浏览器环境中不存在。我担心,对于较大的项目,确实需要像Browserify这样的解决方案,但我仍然很好奇是否有其他解决方案,例如在为Node.js打包库时创建不同的构建环境或者(例如)亭子。

答案 3 :(得分:0)

您可以使用node-browser-resolvebrowser添加package.json部分:

{
  "browser": {
    "./index.js": "./browser.js"
  }
}

请参阅https://nolanlawson.com/2017/01/09/how-to-write-a-javascript-package-for-both-node-and-the-browser/