为啥简化的 CommonJS Wrapper 语法不适用于我的 Dojo AMD 模块?
Posted
技术标签:
【中文标题】为啥简化的 CommonJS Wrapper 语法不适用于我的 Dojo AMD 模块?【英文标题】:Why is the Simplified CommonJS Wrapper syntax not working on my Dojo AMD module?为什么简化的 CommonJS Wrapper 语法不适用于我的 Dojo AMD 模块? 【发布时间】:2012-02-09 08:58:51 【问题描述】:我开始考虑 requirejs 和新的 Dojo AMD 结构,但我在一些早期测试中遇到了问题:
cg/signup.js:
define(['dojo/_base/fx', 'dojo/dom'], function(fx, dom)
return function()
this.hidePreloader = function(id)
var preloader = dom.byId(id);
fx.fadeOut(node : preloader).play()
)
这很好用。在主 cg.js 文件中:
require(['dojo/_base/kernel', 'dojo/_base/loader'])
dojo.registerModulePath('cg', '../cg')
require(['cg/signup', 'dojo/domReady!'], function(Signup)
var sp = new Signup();
sp.hidePreloader('preloader')
)
巴姆。完毕。但是,在使用 Simplified CommonJS Wrapper 结构时:
define(function(require)
var fx = require('dojo/_base/fx'),
dom = require('dojo/dom');
return function()
this.hidePreloader = function(id)
var preloader = dom.byId(id);
fx.fadeOut(node : preloader).play()
)
我收到一个 undefinedModule 错误。它似乎来自dojo/_base/fx
行,但我不知道为什么。
更新
为了澄清。
index.html 脚本
<script type="text/javascript" src="js/dojo/dojo.js.uncompressed.js" data-dojo-config="isDebug:true,async:true"></script>
<script type="text/javascript" src="js/cg.js"></script>
cg.js
require(['dojo/_base/kernel', 'dojo/_base/loader'])
dojo.registerModulePath('cg', '../cg')
require(['cg/signup', 'dojo/domReady!'], function(signup)
signup.testFunc()
)
js/cg/signup.js
define(['require', 'exports'], function(require, exports)
var dom = require('dojo/_base/kernel');
// Any other require() declarations (with very very few exceptions like 'dojo/_base/array throw undefinedModule errors!!!
// without any error causing requires, this works fine.
exports.testFunc = function()
alert("hello")
)
【问题讨论】:
嗯,稍微不同的变体似乎适用于 JSFiddle。 (但我现在无法链接到它,因为 JSFiddle 处于只读模式。)您能否提供有关确切错误的更多详细信息? 这就是确切的错误。通过使用具有相同路径和相同 require 语句的 Simplified CommonJS Wrapper 技术,控制台会打印错误undefinedModule
。我在脚本配置中有isDebug=true
,debugAtAllCosts
不会再抛出任何东西。适合您的变化是什么?
我无法在 JSFiddle 上分成多个文件,所以我尝试了 define("foo", function (require) ... )
,其中 ...
包含您的要求语句,加上 console.log
s 用于 fx
和 dom
对象。控制台记录了两个看起来很疯狂的对象... Dojo 1.7.1?
嗯...除了 _base 中的几个模块之外,我似乎什么都没有加载。 dojo/_base/kernel
和 dojo/_base/array
工作,但我尝试过许多其他的抛出 undefinedModule
错误。这是路径问题吗?我尽可能多地关注 T 的参考资料,但它不起作用。
此外,使用第一个“name”参数(在您的示例中为 foo),则结果对象为 3
,因此没有属性。没有那个参数,我至少可以访问exports
。
【参考方案1】:
dojo 完全支持 Simplified CommonJS Wrapper 格式。但是,有一个先决条件...您必须没有依赖项数组。
define(function (require, exports, module)
var fx = require('dojo/_base/fx'),
dom = require('dojo/dom');
// continue...
);
这将不一样
define(['require', 'exports', 'module'], function (require, exports, module)
var fx = require('dojo/_base/fx'),
dom = require('dojo/dom');
// continue...
);
这也不会……
// in this case require, exports and module will not even exist
define([], function (require, exports, module)
var fx = require('dojo/_base/fx'),
dom = require('dojo/dom');
// continue...
);
【讨论】:
感谢您对本次对话的补充,我将不得不打开该项目备份并进行更多测试。这是一个有趣的警告,你知道为什么吗? 这样做是因为要支持这种格式,需要扫描函数体以查找require(...)
的用法,这会增加一些开销。为了避免不需要的开销,您需要使用这种格式向加载程序“发出信号”(或不取决于您的观点)。您使用这种格式的“信号”没有依赖项数组 - 这就是为什么一个空的依赖项数组与根本没有依赖项数组不同。
我在dojo 1.8.3中尝试了这个简单的例子,但它根本不起作用。
您是从源代码还是从构建/CDN 使用 dojo?默认的构建选项会去掉支持这个的代码。【参考方案2】:
这里是 Dojo 定义的一个小包装器,它使用来自 RequireJS 的代码根据定义函数的 toString 计算依赖关系。它将当前的“define”包装在全局命名空间中,计算依赖关系,然后调用包装好的define。
defineWrapper.js:
// Workaround for the fact that Dojo AMD does not support the Simplified CommonJS Wrapper module definition
(function()
var commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
cjsRequireRegExp = /require\(\s*["']([^'"\s]+)["']\s*\)/g,
ostring = Object.prototype.toString;
function isArray(it)
return ostring.call(it) === '[object Array]';
function isFunction(it)
return ostring.call(it) === '[object Function]';
var oldDefine = define;
define = function(name, deps, callback)
//Allow for anonymous functions
if (typeof name !== 'string')
//Adjust args appropriately
callback = deps;
deps = name;
name = null;
//This module may not have dependencies
if (!isArray(deps))
callback = deps;
deps = [];
//If no name, and callback is a function, then figure out if it a
//CommonJS thing with dependencies.
if (!deps.length && isFunction(callback))
//Remove comments from the callback string,
//look for require calls, and pull them into the dependencies,
//but only if there are function args.
if (callback.length)
callback
.toString()
.replace(commentRegExp, '')
.replace(cjsRequireRegExp, function(match, dep)
deps.push(dep);
);
//May be a CommonJS thing even without require calls, but still
//could use exports, and module. Avoid doing exports and module
//work though if it just needs require.
//REQUIRES the function to expect the CommonJS variables in the
//order listed below.
deps = (callback.length === 1 ? ['require'] :
['require', 'exports', 'module']).concat(deps);
if(name === null)
return oldDefine(deps, callback);
else
return oldDefine(name, deps, callback);
)();
你会如何使用它?
<script src="...dojo..."></script>
<script src="defineWrapper.js"></script>
<script>require(["some_simplified_commonjs_defined_module"], function(module)
// use module here
);</script>
【讨论】:
【参考方案3】:请注意,Dojo 不支持在构建时使用简化的 CommonJS 样式进行依赖检测。这意味着您要么需要使用正常的依赖列表样式,要么在构建配置文件中定义层时必须复制所有依赖项。
这是他们跟踪器中的相关错误:
http://bugs.dojotoolkit.org/ticket/15350
【讨论】:
从 dojo 1.9.0 开始,现在构建支持此功能【参考方案4】:require
是否已定义?我看不出那个参数值来自哪里。我想你可能不得不做类似的事情
define(["require"], function(require) ...
【讨论】:
不,它适用于dojo/_base/kernel
,但不适用于dojo/_base/fx
,因此定义了require。【参考方案5】:
我开始想,也许我不适合学习 Dojo。但是,这一切都伴随着更多的阅读。我不确定我到底做了什么不同或其他什么,但这是工作布局。
index.html 脚本和配置
<script type="text/javascript">
dojoConfig =
async : true,
isDebug : true,
debugAtAllCosts : true,
packages : [
name : 'cg',
location : '/../js/cg'
]
</script>
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.7.1/dojo/dojo.js"></script>
<script type="text/javascript" src="js/cg.js"></script>
js/cg.js
require(['cg/signup', 'dojo/ready'], function(signup)
signup.init('preloader')
)
js/cg/signup.js
define(['dojo', 'require'], function(dojo, require)
var fx = require('dojo/_base/fx')
return new function()
this.init = function(id)
fx.fadeOut(node : dojo.byId(id)).play()
)
同样,不完全确定为什么var fx = require(...)
语句在这个语句中的工作方式与其他语句不同,可能是我下载的构建版本与 CDN 的区别,谁在乎呢。有用。我用来帮助其他人的一些链接可能在同一条船上:
Writing Modular JS
AMD vs CommonJS Wrapper
Dojo Toolkit AMD
Dojo Config (1.7)
【讨论】:
以上是关于为啥简化的 CommonJS Wrapper 语法不适用于我的 Dojo AMD 模块?的主要内容,如果未能解决你的问题,请参考以下文章
javascript CommonJS`require`语法用于使用React lazy
用于导入 commonjs / amd 模块的新 es6 语法,即 `import foo = require('foo')`
模块化 angularjs 应用程序 commonJS 与 AMD 模块语法
导入 3rd 方库时的 CommonJS 汇总插件语法错误,主要与“进程”有关