为节点和浏览器环境构build包
我开发了一个节点NPM包,它主要是一个包装器(使用节点的http
, https
和querystring
模块)用于特定的JSON API。 它构build在Coffeescript中,并使Node.js服务器能够与此API进行通信。 Api主要是REST。
现在我想让这个库也可用于浏览器。 这意味着对http
模块的调用需要用XMLHttpRequest
(asynchronous)代替。 在我看来,我会做适配器的包装。 对于Node环境,这个适配器会将所有的调用传递给http
模块,并将浏览器环境传递给XMLHttpRequest
对象。
有没有一种很好的方法来构build系统,使npm包含两个版本,我也可以在Github上发布普通的“浏览器版本”? 节点包然后通过require('package-name')
可用,并且应该把一个JS文件(用于浏览器)放在一个目录中。
我已经看过Component ,这对客户端包pipe理很好,但问题仍然是如何创build不同的构build环境。
一个使用browserify为node.js和浏览器交叉开发的示例解决scheme: https : //github.com/amitayd/grunt-browserify-jasmine-node-example ( 以及在我的博客文章中的讨论 )。
特别是对于Browser / Node.js有不同的实现来检查PersistentReaderWriter.js 。
一旦你有一些模板开始使用browserify,并且你意识到一些陷阱,你可能会发现你也想用它来做一些小型的库。
编辑:请注意,如果您浏览模块,isBrowser()检查不应该通过检查是否定义模块和module.exports,因为Browserify的包装将在模块上下文中定义它们。 相反,在我的例子中,我检查要定义的窗口。
我find了一个解决scheme,虽然不是第一个想到的,不同的构build环境。
在我的情况下,我有一个非常小的库使用节点的http
, https
, querystring
和url
包。 我不想使用像Browserify这样的东西 ,因为将所有这些包捆绑到一个小的API库似乎是不合适的。 相反,我用XMLHttpRequest包replace了http
和https
function。 querystring
和url
提供的小function很容易被重写。
在我的库中,我检查,运行时,如果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
variables。 如果是这样,我已经定义的对象被设置为,否则它被设置为window
对象:
if typeof module is 'undefined' window['My-module'] = My_module_object else module.exports = exports = My_module_object
这一切都适合我,因为我没有真正需要的Node.js的依赖关系,这是浏览器环境中不存在的。 恐怕对于大型项目来说,像Browserify这样的解决scheme确实是需要的,但是如果还有其他的解决scheme,比如为Node.js打包库或者打包(比如)Bower时创build不同的构build环境,我还是很好奇。
您可以使用node-browser-resolve
将browser
部分添加到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/