grunt-contrib-requirejs 淘汰组件问题
grunt-contrib-requirejs knockout component issue
使用 grunt-contrib-requirejs to build my project, my knockout components' 模块时,仅在组件本身(text
和 mapping
)中引用的模块不会添加到我的压缩输出脚本文件中。
我的淘汰模块:
define(['knockout', 'text!./foo.html', 'mapping'], ....)
由于组件是在 运行 时间异步注入的 - AFAIK -
g运行t-contrib-requirejs 没有提取它们并将它们添加到我的压缩文件中,out: "<%= settings.getBuildPath() %>/js/lib/require/require.js",
下面:
g运行t 配置:
requirejs: {
compile: {
options: {
baseUrl: 'src/js',
mainConfigFile: "src/js/app.js",
name: 'app',
out: "<%= settings.getBuildPath() %>/js/optimized.js",
preserveLicenseComments: false,
include: ['lib/require/require.js']
}
}
}
如果我在我的另一个脚本文件中引用它们,但该脚本文件不是淘汰组件模块,则项目构建正常。
那么,如何让 g运行t-contrib-requirejs 添加在我的组件中也引用的脚本?
我对这个问题的解决方案是使用一个模块来注册组件,并在此处要求模板和视图模型以确保 r.js 将它们包含在包中。
我通常在main.js中需要并调用这个模块。
// registerComponents.js
define(
['knockout', 'componentViewModel', 'text!componentTemplate.html', ],
function (ko, componentViewModel, componentTemplate) {
return function () {
ko.components.register('myComponent', {
viewModel: componentViewModel,
template: componentTemplate
});
};
});
// main.js
require(['registerComponents'], function (registerComponents) {
registerComponents();
});
根据您的应用程序的大小,您可能希望将所有 HTML 放入单个 JS 文件并使用自定义 Knockout 组件加载器。
grunt.registerTask("generate-templates", function () {
var componentTemplates = grunt.file.expand('components/**/*.html');
var incldesContent = '';
var imports = componentTemplates.map(function (item) {
var content = fs.readFileSync(item, { encoding: 'utf8' }).toString();
content = content.trim().replace(/["'\\n\r\u2028\u2029]/g, function (character) {
// Escape all characters not included in SingleStringCharacters and
// DoubleStringCharacters on
// http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4
switch (character) {
case '"':
case "'":
case '\':
return '\' + character
// Four possible LineTerminator characters need to be escaped:
case '\n':
return '\n'
case '\r':
return '\r'
case '\u2028':
return '\u2028'
case '\u2029':
return '\u2029'
}
})
return "templatesCache['" + item + "'] = '" + content + "';";
});
grunt.file.write('wwwroot/templates.js', '// This file is autogenerated. DO NOT EDIT.\nvar templatesCache=[];\n' + imports.join('\n'));
});
下面是模板注册代码。它在 TypeScript 中,但应该很容易翻译成 JS。
declare var templatesCache: any[];
enter code here
/**
* Dynamically register component based on component naming conventions
*/
function registerComponent(componentName: string, folderName: string, componentData?: string) {
componentData = componentData || componentName;
var componentTemplate: string | KnockoutComponentTypes.AMDModule;
if (window["templatesCache"]) {
componentTemplate = templatesCache["components/" + folderName + "/" + componentData + "/" + componentData + ".html"];
} else {
componentTemplate = { require: "text!components/" + folderName + "/" + componentData + "/" + componentData + ".html" }
}
ko.components.register(componentName, {
template: componentTemplate,
viewModel: { require: "components/" + folderName + "/" + componentData + "/" + componentData + "" }
});
}
/* Shared components */
registerComponent("tabbar", "shared");
registerComponent("left-bar", "shared");
registerComponent("photo-loader", "shared");
本质上,我的 grunt 任务 prepare templates.js
声明了组件加载器使用的 templateCache
变量,但它需要我手动注册 KO 组件。您可以通过遵循命名约定和从文件夹结构生成注册文件来避免这种情况。我的应用程序相对简单,所以我最终手动注册,没有执行额外的步骤。
使用 grunt-contrib-requirejs to build my project, my knockout components' 模块时,仅在组件本身(text
和 mapping
)中引用的模块不会添加到我的压缩输出脚本文件中。
我的淘汰模块:
define(['knockout', 'text!./foo.html', 'mapping'], ....)
由于组件是在 运行 时间异步注入的 - AFAIK -
g运行t-contrib-requirejs 没有提取它们并将它们添加到我的压缩文件中,out: "<%= settings.getBuildPath() %>/js/lib/require/require.js",
下面:
g运行t 配置:
requirejs: {
compile: {
options: {
baseUrl: 'src/js',
mainConfigFile: "src/js/app.js",
name: 'app',
out: "<%= settings.getBuildPath() %>/js/optimized.js",
preserveLicenseComments: false,
include: ['lib/require/require.js']
}
}
}
如果我在我的另一个脚本文件中引用它们,但该脚本文件不是淘汰组件模块,则项目构建正常。
那么,如何让 g运行t-contrib-requirejs 添加在我的组件中也引用的脚本?
我对这个问题的解决方案是使用一个模块来注册组件,并在此处要求模板和视图模型以确保 r.js 将它们包含在包中。
我通常在main.js中需要并调用这个模块。
// registerComponents.js
define(
['knockout', 'componentViewModel', 'text!componentTemplate.html', ],
function (ko, componentViewModel, componentTemplate) {
return function () {
ko.components.register('myComponent', {
viewModel: componentViewModel,
template: componentTemplate
});
};
});
// main.js
require(['registerComponents'], function (registerComponents) {
registerComponents();
});
根据您的应用程序的大小,您可能希望将所有 HTML 放入单个 JS 文件并使用自定义 Knockout 组件加载器。
grunt.registerTask("generate-templates", function () {
var componentTemplates = grunt.file.expand('components/**/*.html');
var incldesContent = '';
var imports = componentTemplates.map(function (item) {
var content = fs.readFileSync(item, { encoding: 'utf8' }).toString();
content = content.trim().replace(/["'\\n\r\u2028\u2029]/g, function (character) {
// Escape all characters not included in SingleStringCharacters and
// DoubleStringCharacters on
// http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4
switch (character) {
case '"':
case "'":
case '\':
return '\' + character
// Four possible LineTerminator characters need to be escaped:
case '\n':
return '\n'
case '\r':
return '\r'
case '\u2028':
return '\u2028'
case '\u2029':
return '\u2029'
}
})
return "templatesCache['" + item + "'] = '" + content + "';";
});
grunt.file.write('wwwroot/templates.js', '// This file is autogenerated. DO NOT EDIT.\nvar templatesCache=[];\n' + imports.join('\n'));
});
下面是模板注册代码。它在 TypeScript 中,但应该很容易翻译成 JS。
declare var templatesCache: any[];
enter code here
/**
* Dynamically register component based on component naming conventions
*/
function registerComponent(componentName: string, folderName: string, componentData?: string) {
componentData = componentData || componentName;
var componentTemplate: string | KnockoutComponentTypes.AMDModule;
if (window["templatesCache"]) {
componentTemplate = templatesCache["components/" + folderName + "/" + componentData + "/" + componentData + ".html"];
} else {
componentTemplate = { require: "text!components/" + folderName + "/" + componentData + "/" + componentData + ".html" }
}
ko.components.register(componentName, {
template: componentTemplate,
viewModel: { require: "components/" + folderName + "/" + componentData + "/" + componentData + "" }
});
}
/* Shared components */
registerComponent("tabbar", "shared");
registerComponent("left-bar", "shared");
registerComponent("photo-loader", "shared");
本质上,我的 grunt 任务 prepare templates.js
声明了组件加载器使用的 templateCache
变量,但它需要我手动注册 KO 组件。您可以通过遵循命名约定和从文件夹结构生成注册文件来避免这种情况。我的应用程序相对简单,所以我最终手动注册,没有执行额外的步骤。