简体   繁体   English

如何给予JavaScript模块有条件的AMD支持?

[英]How to give a JavaScript module conditional AMD support?

I'm building a module that I want to make available both for people that use AMD and for ones that don't. 我正在构建一个模块,以使使用AMD的人员和不使用AMD的人员都能使用。 For example, I want to make it work with RequireJS: 例如,我想使其与RequireJS一起使用:

require(['Module'], function (Module) {
  // do stuff with module
});

But I also want it to work by manually inserting all dependencies (considering they also work without AMD). 但是我也希望它通过手动插入所有依赖项来工作(考虑到它们也可以在没有AMD的情况下工作)。

How can I test that this behavior is correct? 如何测试这种行为是正确的?

A working approach I found was to use the module pattern in my script file so that there are no leaked dependencies. 我发现一种可行的方法是在脚本文件中使用模块模式,这样就不会泄漏依赖项。 Afterwards, I build an internal function that receives my dependencies as parameters and returns the object that represents the module I want to export. 之后,我构建一个内部函数,该函数接收我的依赖项作为参数,并返回代表我要导出的模块的对象。

Then, I check if there is a define function available and if it has the amd property set on it. 然后,我检查是否有可用的define函数,以及是否设置了amd属性。 If yes, then I register the module with define, otherwise I export it as a global. 如果是,那么我将使用define来注册模块,否则将其导出为全局模块。

Here's a skeleton of the code for this. 这是此代码的框架。 We'll assume that the module is named Module and it has two dependencies, dep1 and dep2 : 我们假设该模块名为Module ,并且具有两个依赖项dep1dep2

(function (exports) {
  "use strict";
  var createModule = function (dep1, dep2) {
    var Module;
    // initialize the module
    return Module;
  }
  if (typeof define === 'function' && define.amd) {
    define(['dep1', 'dep2'], function (dep1, dep2) {
      return createModule(dep1, dep2);
    });
  } else {
    exports.Module = createModule(dep1, dep2);
  }
})(this);

Regarding the tests, I'm currently using yeoman for it, with mocha and PhantomJS . 关于测试,我目前正在将yeeoman与mochaPhantomJS Here's how to make testing work with require. 这是使测试与require一起工作的方法。 The approach I've taken to test both cases (with and without AMD) is to have two separate html tests. 我用来测试这两种情况(使用和不使用AMD)的方法是进行两个单独的html测试。 First of all, you need to add the second page in the Gruntfile: 首先,您需要在Gruntfile中添加第二页:

// headless testing through PhantomJS
mocha: {
  all: ['http://localhost:3501/index.html', 'http://localhost:3501/no-amd.html']
},

In the first case, there's the normal require-based template: 在第一种情况下,有一个普通的基于需求的模板:

<script src="lib/mocha/mocha.js"></script>
<!-- assertion framework -->
<script src="lib/chai.js"></script>

<!-- here, main includes all required source dependencies, 
    including our module under test -->
<script data-main="scripts/main" src="scripts/vendor/require.js"></script>

<script>
  mocha.setup({ui: 'bdd', ignoreLeaks: true});
  expect = chai.expect;
  should = chai.should();
  require(['../spec/module.spec'], function () {
    setTimeout(function () {
      require(['../runner/mocha']);
    }, 100);
  });
</script>

For testing non-amd, we need to explicitly include the module and all dependencies. 为了测试非amd,我们需要明确包含模块和所有依赖项。 After all is present in the page, we include the runner. 页面中显示所有内容后,我们将包括跑步者。

<script src="lib/mocha/mocha.js"></script>
<!-- assertion framework -->
<script src="lib/chai.js"></script>

<!-- include source files here... -->
<script src="scripts/vendor/dep1.js"></script>
<script src="scripts/vendor/dep2.js"></script>
<script src="scripts/Module.js"></script>

<script>
  mocha.setup({ui: 'bdd', ignoreLeaks: true});
  expect = chai.expect;
  should = chai.should();
</script> 
<script src="spec/romania.spec.js"></script>
<script src="runner/mocha.js"></script>

It doesn't make any sense to have two different specs, but the spec should also work with AMD and without it. 拥有两个不同的规范没有任何意义,但是该规范也可以在没有AMD的情况下使用。 The solution is similar to the one we used for the module. 该解决方案类似于我们用于该模块的解决方案。

(function () {
  "use strict";
  var testSuite = function (Module) {
    // break the module into pieces :)
  };
  if (typeof require === 'function') {
    require(['Module'], function (Module) {
      testSuite(Module);
    });
  } else {
    // if AMD is not available, assume globals
    testSuite(Module);
  }
})();

If you have different or more elegant ways to do this, please post them as answers here. 如果您有其他或更优雅的方法,请在此处将其发布为答案。 I'd be happy to accept a better answer. 我很乐意接受更好的答案。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM