如何在没有RequireJS的页面中编写AMD模块?

时间:2012-09-24 03:31:21

标签: javascript requirejs amd

我需要重新构建现有的AMD模块,以便在有/无RequireJS的页面中使用它。我该怎么做,是否有任何示例代码?优选地,它可以是一种不污染全局命名空间的方式,但不是严格的要求。

6 个答案:

答案 0 :(得分:8)

这根本不是一个坏主意,通常需要JS库来支持AMD /非AMD环境。以下是解决方案的一种变体:

!function (name, definition) {
    if (typeof module != 'undefined') module.exports = definition()
    else if (typeof define == 'function' && define.amd) define(name, definition)
    else this[name] = definition()
}('reqwest', function () {

    // Module here

});

唯一的缺点是你不能请求其他依赖项,所以这只适用于独立的库,如下面的那些

答案 1 :(得分:3)

我最近写了一篇关于这个主题的要点,所以我在下面复制了相关内容;但是,请随时查看original Gist以获取更多信息。

以下样板文件允许您编写模块一次,并使其在CJS / NodeJs,AMD或Browser Global环境中工作。

最佳使用时......

  • 您正在从命名空间(错误,全局)代码迁移到AMD或CJS模块或两者兼而有之。
  • 你还不能分解浏览器全局,但也需要通过NodeJS测试你的代码(例如Mocha

好处&权衡

  • 单一模块格式,允许您定位AMD,CJS / NodeJS以及window.*等旧版浏览器全局。
  • 允许定义多个依赖项。
  • 通过CLI / NodeJS运行器(例如Mocha)运行单元测试。
  • 逐渐迁移到CJS / NodeJS或AMD模块时减少痛苦。
  • 你放弃了类似Java的命名空间(例如com.company.package.module) - 嗯,无论如何它们都是一团糟。
  • 这个(UMD)不是标准;公平地说,AMD也不是(这是一个定义明确的规范的公约)。
  • 非常重要的样板(和丑陋)。

实施例

/**
 * Creates a an "AppWidget" module that imports a "SingleDependency" constructor and exposes an "AppWidget" constructor.
 * 
 * Allows you to access AppWidget as a CJS/AMD module (i.e. NodeJS or RequireJs):
 * 
 * @example
 *    var AppWidget = require('app-widget')
 * 
 * Allows you to access AppWidget as a legacy browser global:
 * 
 * @example
 *    var AppWidget = window.AppWidget
 */

!(function (name, context, definition) {
  if (typeof exports === 'object') { module.exports = definition(require); } else if (typeof define === 'function' && define.amd) { define(definition); } else { context[name] = definition(); }
}).call(this, 'AppWidget', this, function (require) {
  'use strict'

  // imports
  var SingleDependency = (typeof require === 'function') ? require('./single-dependency') : window.SingleDependency;
  var singleDependency = new SingleDependency();

  function AppWidget() {}
  AppWidget.prototype.start = function () {};

  // exports
  return AppWidget;

});

答案 2 :(得分:1)

结帐UMD。您应该找到适合您目的的模式。模板有些难看但很有效。

答案 3 :(得分:0)

我认为这是一个非常糟糕的主意。

您必须采取的步骤以确保其有效:

  1. 确保在该页面上加载所有模块的依赖项(jQuery,Backbone等)
  2. 按照您知道应该执行的顺序在页面上包含您的模块
  3. 确保任何作为另一个模块的依赖关系的模块创建一个全局变量 具有相同名称的“导入”模块期望并在其代码中引用
  4. 确保您的模块引用相同名称的依赖项(包括其他模块)
  5. 覆盖/创建执行模块工厂功能的全局方法define
  6. 这只是你必须做的事情的一部分。那么你需要与你的RequireJS页面符合AMD标准的第三方(或至少是shim配置),你的非RequireJS页面应该是全局的吗?

    简单地说,IMO,将现有代码重新编写为AMD版本更容易,使您的模块非AMD

答案 4 :(得分:0)

根据Simon Smiths的回答,我解决了模块依赖问题:

(function (root, factory) {
    if (typeof exports === "object") {
        module.exports = factory();
    } else if (typeof define === "function" && define.amd) {
        define(['jquery', 'ol'], factory);
    } else {
        root.module_name = factory();
    }
}(this, function (_$, _ol) {
    return new function () {
        // supposed that window.ol and window.$ are defined
        var ol = goog.isDef(_ol) ? _ol : window.ol;
        var $ = goog.isDef(_$) ? _$ : window.$;
}
}));

goog.isDef Google Closure函数的位置:

goog.isDef = function(val) {

  return val !== void 0;
};

希望它会对某人有所帮助。

答案 5 :(得分:-1)

查看Browserify,它将创建单个独立的.js文件,其中包含从AMD / JS代码中嵌入的所有依赖项。

然后您可以发送2个版本的代码,一个用于AMD用户,另一个用于“oldschool”js用户。