项目结构
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预构建版本)
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预建版本)
define(function () {
console.log('dropdown initialized');
return 'foo';
});
HTML页面
在页面的<head>
中包含此脚本标记,用于加载需要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>
问题
dropdown
回调是undefined
,而不是我从定义的模块返回的预期“foo”字符串。
实际上,控制台也没有包含“dropdown initialized”的日志项。这让我相信模块没有以某种方式被调用?但是,很奇怪dropdown.js作为加载到页面中的脚本存在于F12调试器中。因此,require需要调用加载它,但是没有运行define的内容吗?
值得注意的提及
dropdown
并且依赖于具有正确路径的baseUrl
配置。编辑#1
我已经为每个评论者请求添加了与grunt一起使用的r.js构建配置。与此同时,我更新了文件结构以包含整体项目结构,而不仅仅是运行时公共wwwroot结构。
r.js流程将汇总来自源位置~/wwwroot/scripts/modules
的{{1}}中的global.js +其他模块的构建形式。
~/modules
编辑#2
认为包含我正在使用的requirejs包的版本是个好主意:
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;
}
感谢。
答案 0 :(得分:1)
r.js处理分配给下拉模块的名称是&#34; modules / dropdown / dropdown.js&#34;。我不确定我是否应该以某种方式使用它,或者我是否正确引用该模块只是下拉并依赖我的baseUrl配置具有正确的路径。
从某种意义上说,是的,你应该使用那条完整的道路。这就是Require所指的模块ID - &#34; modules / dropdown / dropdown&#34; (如果上面输出中的.js是真实的,我建议在&#34;名称中删除该扩展名&#34;配置.js由RequireJS承担,你不希望你的模块ID中的那个字符串) 。当给定ID时,使用basePath将一些未知ID转换为文件路径(例如&#39; bootstrap&#39; id - &gt;(应用路径配置) - &gt;&#39; ../../ lib / bootstrap / js / bootstrap&#39; - &gt;(应用基本URL) - &gt;&#39; scripts / modules /../../ lib / bootstrap / js / bootstrap&#39;)。
但是,真的,只允许r.js将所有内容连接到一个文件中 是首选的方式。您可以使用include选项将global.js未引用的模块包含在优化的包中(https://github.com/jrburke/r.js/blob/master/build/example.build.js#L438)
至于您的具体问题:您的懒惰require(['dropdown'])
电话会误导您。通过将请求的模块ID与basePath组合,RequireJS会提供您想要的URL - scripts/modules/dropdown
- 它定义了模块标识为scripts/module/dropdown
的模块 - 但是因为您请求了模块标识{{1}你什么也得不到。 (我猜想你会得到一个RuntimeError而不是undefined,但我想这就是事情的进展)。您需要以某种方式解决ID /路径不匹配问题。
答案 1 :(得分:1)
虽然我已经通过 wyantb 的提示解决了我的问题,但由于其带来的简单性,我已经将我的方法改为单个文件concat。我仍然希望发布我如何解决这个问题的具体细节,以便其他任何人能够解决这个问题。
在grunt构建配置选项中,我添加了onBuildWrite
字段来转换内容,因此我分配的模块ID与我懒得加载它们的方式排成一行。
onBuildWrite: function (moduleName, path, contents) {
return contents.replace(/modules\/global.js/, 'global');
}
此代码专门用于global.js文件。我为其他模块文件(在foreach循环中)实现了类似的onBuildWrite
。转换将基本上从r.js指定的模块名称中删除路径和扩展名。
以下是之前和之后的一些示例:
Before After
/modules/global.js global
/modules/dropdown/dropdown.js dropdown
/modules/loginButton/loginButton.js loginButton
因此,当我使用原始问题中的HTML脚本加载模块时,requirejs会解析并找到匹配项。
答案 2 :(得分:-1)
要么按路径要求,要么在global.cs中定义global
和dropdown
require(['./global'], function () {
require(['./dropdown'], function (dropdown) {
console.log(dropdown);
});
});