requirejscallback未定义

项目结构

root wwwroot <-- files under this location are static files public to the site css lib bootstrap/js/bootstrap.js jquery/js/jquery.js knockout/knockout.js requires/require.js scripts modules ┌───────────────┐ global.js <--│ Built modules │ dropdown.js └───────────────┘ modules global.js ┌────────────────┐ dropdown <--│ Source modules │ dropdown.js └────────────────┘ gruntfile.js 

global.cs内容 (〜/ modules / global.js的预build版本)

 require.config({ baseUrl: "scripts/modules", paths: { jquery: "../../lib/jquery/js/jquery", bootstrap: "../../lib/bootstrap/js/bootstrap", knockout: "../../lib/knockout/knockout" }, shims: { bootstrap: { deps: ['jquery'] } }, }); define(function (require) { var $ = require('jquery'); var ko = require('knockout'); var bootstrap = require('bootstrap'); }); 

dropdown.js内容 (〜/ modules / dropdown.js的预build版本)

 define(function () { console.log('dropdown initialized'); return 'foo'; }); 

HTML页面

在页面的<head>中包含此脚本标记以进行加载require config:

 <script src="~/lib/requirejs/require.js" data-main="scripts/modules/global"></script> 

在HTML页面的主体中,我有以下几点:

 <script> require(['global'], function () { require(['dropdown'], function (dropdown) { console.log(dropdown); }); }); </script> 

问题

dropdowncallback是undefined而不是从定义的模块返回的预期的“foo”string。

事实上,控制台不包含“下拉初始化”的日志项目。 这使我相信模块不被调用? 然而,很奇怪dropdown.js是作为一个加载到页面的脚本在F12debugging器中出现的。 因此,要求确实调用了加载它,但没有运行定义的内容?

值得一提的是

  • 我正在使用r.js进行优化和构build。 global.js和dropdown.js都经过处理。
  • 由r.js处理分配给下拉模块的名称是“modules / dropdown / dropdown.js”。 我不确定是否应该以某种方式使用它,或者如果我正确地将模块称为dropdown并依赖于具有正确path的baseUrlconfiguration。

编辑#1

我已经添加了每个评论者请求使用的r.js构buildconfiguration。 结合起来,我更新了文件结构以包含整个项目结构,而不仅仅是运行时的公共wwwroot结构。

r.js过程将汇总来自源位置~/modules ~/wwwroot/scripts/modules内置forms的global.js +其他模块。

 function getRequireJsConfiguration() { var baseUrl = './'; var paths = { jquery: "wwwroot/lib/jquery/js/jquery", bootstrap: "wwwroot/lib/bootstrap/js/bootstrap", knockout: "wwwroot/lib/knockout/knockout" }; var shims = { bootstrap: { deps: ['jquery'] } }; var optimize = 'none'; var configuration = {}; var jsFilePaths = grunt.file.expand('modules/**/*.js'); jsFilePaths.forEach(function (jsFilePath) { var fileName = jsFilePath.split('/').pop(); if (configuration[fileName]) { throw 'Duplicate module name conflict: ' + fileName; } configuration[fileName] = { options: { baseUrl: './', name: jsFilePath, out: 'wwwroot/scripts/modules/' + fileName, paths: paths, shims: shims, optimize: optimize, exclude: ['jquery', 'knockout', 'bootstrap'] } }; }); configuration['global'] = { options: { baseUrl: './', name: 'modules/global.js', out: 'wwwroot/scripts/modules/global.js', paths: paths, shims: shims, optimize: optimize, } }; return configuration; } 

编辑#2

认为包含我使用的requirejs包的版本是个好主意:

 requirejs: 2.1.15 grunt-contrib-requirejs: 0.4.4 

谢谢。

由r.js处理分配给下拉模块的名称是“modules / dropdown / dropdown.js”。 我不确定是否应该以某种方式使用它,或者如果我正确地将模块称为下拉菜单并依赖于具有正确path的baseUrlconfiguration。

从某种意义上说,是的,你应该使用完整的path。 这就是要求引用为模块id – “modules / dropdown / dropdown”(如果上述输出中的.js是真实的,我build议剥离“name”configuration中的扩展名.js由RequireJS假定,不要在你的模块ID的string)。 当给定ID时,使用basePath将一些未知ID转换为文件path(例如'bootstrap'id – >(apply path config) – >'../../lib/bootstrap/js/bootstrap' – > (应用基URL) – >'scripts / modules /../../ lib / bootstrap / js / bootstrap')。

实际上,只要允许r.js将所有内容连接成一个文件是首选的方法。 您可以使用include选项将global.js未引用的模块也包含在优化的bundle中( https://github.com/jrburke/r.js/blob/master/build/example.build.js# L438 )

至于你的具体问题:你的懒惰require(['dropdown'])调用误导你。 通过将请求的模块id和basePath结合起来,RequireJS就会出现你想要的URL – scripts/modules/dropdown – 它定义了一个模块id为scripts/module/dropdown – 但是因为你要求模块id dropdown ,没有。 (我会猜你会得到一个RuntimeError而不是未定义的,但我想这就是事情的方式)。 这种或那种方式,你需要解决ID /path不匹配。

虽然我已经解决了提供wyantb提供的提示的提示,但是由于其带来的简单性,我已经将自己的方法改为单个文件concat。 我仍然想要发表具体的我如何解决这个问题的问题,任何人发生沿着它。

在grunt构buildconfiguration选项中,我添加了onBuildWrite字段来转换内容,所以我分配的模块ID与我如何延迟加载它们一致。

 onBuildWrite: function (moduleName, path, contents) { return contents.replace(/modules\/global.js/, 'global'); } 

这段代码专门用于global.js文件。 我为其他模块文件(在foreach循环中)实现了一个类似的onBuildWrite 。 转换将从r.js分配的模块名称中删除path和扩展名。

以下是一些前后的例子:

 Before After /modules/global.js global /modules/dropdown/dropdown.js dropdown /modules/loginButton/loginButton.js loginButton 

因此,当我使用我的原始问题的HTML脚本加载模块时,requirejsparsing并find匹配项。

要么通过path,要么在global.cs中定义globaldropdown

 require(['./global'], function () { require(['./dropdown'], function (dropdown) { console.log(dropdown); }); });