如何编写一个适用于Node.js,RequireJS以及没有它们的模块 [英] How to write a module that works with Node.js, RequireJS as well as without them

查看:123
本文介绍了如何编写一个适用于Node.js,RequireJS以及没有它们的模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发 JSON / XML处理的JavaScript库。我的库在浏览器和Node.js中工作(带有 xmldom xmlhttprequest 模块)。

I am working on a JavaScript library for JSON/XML processing. My library works in browser as well as Node.js (with xmldom and xmlhttprequest modules).

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

One of the users recently asked for RequireJS support. I have taken a look at the RequireJS/AMD thing and think it is a good approach so I'd like to provide this.

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

However I'd like to retain the portability: my library must work in browsers (with and without RequireJS) as well as Node.js. And in the browser environment I don't depend on xmldom or xmlhttprequest since these things are provided by the browser itself.

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

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

A bit of historyand my current solution

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

I initially wrote my library for browsers. So it just created a global-scope object and put everything inside it:

var Jsonix = { ... };

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

Later on users asked for Node.js support. So I added:

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

我还必须导入上面提到的几个模块。我是有条件的,取决于 require 函数是否可用:

I also had to import few modules mentioned above. I did it conditionally, depending on whether the require function is available or not:

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

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

Now there's this story with RequireJS. If RequireJS is present then the require function is present as well. But module loading works differently, I have to use the define function etc. I also can't just require things since require has an async API in RequireJS. Moreover, if my library is loaded via RequireJS, it seems to process the source code and detects require('something') even if I do it conditionally like

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

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

RequireJS still detects require('xmlhttprequest') an tries to load the corresponding JS file.

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

Currently I'm coming to the following solution.

// 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();
}

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

And this is how I check for dependencies now:

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

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

If I have require but not define then I assume this is a Node.js environment. I use amdefine to define the module and pass the required dependencies.

如果我有 require define 我认为这是一个RequireJS环境,所以我只使用 define 功能。目前我还假设这是一个浏览器环境,因此 xmldom xmlhttprequest 等依赖项不可用,并且不需要它们。 (这可能也不正确。)

If I have require and define thet I assume this is a RequireJS environment, so I just use the define function. Currently I also assume this is a browser environment so dependencies like xmldom and xmlhttprequest are not available and don't require them. (This is probably nor correct.)

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

If I don't have the require function then I assume this is a browser environment without RequireJS/AMD support so I invoke the module factory _jsonix directly and export the result as a global object.

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

So, this is my approach so far. Seems a little bit awkward to me, and as a newbie to RequireJS/AMD I'm seeking advise. Is it the right approach? Are there better ways to address the problem? I'd be grateful for your help.

推荐答案

看一下 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 _;
  });
}

这篇关于如何编写一个适用于Node.js,RequireJS以及没有它们的模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆