javascript - 如何编写一个可以与 Node.js、RequireJS 以及没有它们一起工作的模块

标签 javascript node.js requirejs amd js-amd

我正在为 JSON/XML processing 开发一个 JavaScript 库。 .我的库可以在浏览器和 Node.js 中使用(带有 xmldomxmlhttprequest 模块)。

其中一位用户最近要求 RequireJS 支持。我已经查看了 RequireJS/AMD 的东西,并认为这是一个很好的方法,所以我想提供这个。

但是我想保留可移植性:我的库必须在浏览器(有和没有 RequireJS)以及 Node.js 中工作。而在浏览器环境中我不依赖 xmldomxmlhttprequest 因为这些东西是由浏览器本身提供的。

我的问题是:如何实现我的库,以便它在浏览器以及没有 RequireJS 的 Node.js 中工作?

一点历史和我目前的解决方案

我最初为浏览器编写了我的库。所以它只是创建了一个全局范围的对象并将所有内容放入其中:

var Jsonix = { ... };

后来用户要求 Node.js 支持。所以我补充说:

if(typeof require === 'function'){
    module.exports.Jsonix = Jsonix;
}

我还必须导入上面提到的几个模块。我有条件地这样做了,这取决于 require 功能是否可用:

if (typeof require === 'function')
{
    var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;
    return new XMLHttpRequest();
}

现在有了 RequireJS 的故事。如果 RequireJS 存在,那么 require 函数也存在。但是模块加载的工作方式不同,我必须使用 define 函数等。我也不能只是 require 东西,因为 require 有一个异步 API在 RequireJS 中。此外,如果我的库是通过 RequireJS 加载的,它似乎会处理源代码并检测 require('something') 即使我有条件地这样做

if (typeof require === 'function' && typeof require.specified !== 'function) ...

RequireJS 仍然会检测到 require('xmlhttprequest') 并尝试加载相应的 JS 文件。

目前我正在采用以下解决方案。

// Module factory function, AMD style
var _jsonix = function(_jsonix_xmldom, _jsonix_xmlhttprequest, _jsonix_fs)
{
    // Complete Jsonix script is included below 
    var Jsonix = { ... };
    // Complete Jsonix script is included above
    return { Jsonix: Jsonix };
};

// If require function exists ...
if (typeof require === 'function') {
    // ... but define function does not exists, assume we're in the Node.js environment
    // In this case, load the define function via amdefine
    if (typeof define !== 'function') {
        var define = require('amdefine')(module);
        define(["xmldom", "xmlhttprequest", "fs"], _jsonix);
    }
    else {
        // Otherwise assume we're in the RequireJS environment
        define([], _jsonix);
    }
}
// Since require function does not exists,
// assume we're neither in Node.js nor in RequireJS environment
// This is probably a browser environment
else
{
    // Call the module factory directly
    var Jsonix = _jsonix();
}

这就是我现在检查依赖项的方式:

if (typeof _jsonix_xmlhttprequest !== 'undefined')
{
    var XMLHttpRequest = _jsonix_xmlhttprequest.XMLHttpRequest;
    return new XMLHttpRequest();
}

如果我有 require 但没有 define 那么我假设这是一个 Node.js 环境。我使用 amdefine 来定义模块并传递所需的依赖项。

如果我有 requiredefine 我假设这是一个 RequireJS 环境,所以我只使用 define 函数。目前我还假设这是一个浏览器环境,因此像 xmldomxmlhttprequest 这样的依赖项不可用并且不需要它们。 (这可能也不正确。)

如果我没有 require 函数,那么我认为这是一个没有 RequireJS/AMD 支持的浏览器环境,所以我直接调用模块工厂 _jsonix 并导出结果作为一个全局对象。

所以,这是我目前的方法。对我来说似乎有点尴尬,作为 RequireJS/AMD 的新手,我正在寻求建议。这是正确的方法吗?有没有更好的方法来解决这个问题?非常感谢您的帮助。

最佳答案

看看如何underscore.js处理它。

// Export the Underscore object for **Node.js**, with
// backwards-compatibility for the old `require()` API. If we're in
// the browser, add `_` as a global object.
if (typeof exports !== 'undefined') {
  if (typeof module !== 'undefined' && module.exports) {
    exports = module.exports = _;
  }
  exports._ = _;
} else {
  root._ = _;
}

...

// AMD registration happens at the end for compatibility with AMD loaders
// that may not enforce next-turn semantics on modules. Even though general
// practice for AMD registration is to be anonymous, underscore registers
// as a named module because, like jQuery, it is a base library that is
// popular enough to be bundled in a third party lib, but not be part of
// an AMD load request. Those cases could generate an error when an
// anonymous define() is called outside of a loader request.
if (typeof define === 'function' && define.amd) {
  define('underscore', [], function() {
    return _;
  });
}

关于javascript - 如何编写一个可以与 Node.js、RequireJS 以及没有它们一起工作的模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25274930/

相关文章:

javascript - 数组操作/映射返回未定义

javascript - 当从一个页面快速导航到另一个脚本时显示警报,为什么?

javascript - 如何正则表达式匹配双下划线,但不是单下划线(__不是_)

javascript - 如何在 requirejs 中使用 Angular 场景

javascript - 缩小之后加载的 RequireJS 模块

Javascript 应用程序作为具有外部依赖项的 AMD 模块

javascript - 将数据从 mongoDB 同步到 firebase,反之亦然

javascript - 如何更新火力地堡

javascript - 获取所有角色权限列表

node.js - 如何使用 Nodejs 绑定(bind)从 DAML 中的存档合约中获取数据?