grunt-contrib-requirejs淘汰组件问题

时间:2016-01-29 21:22:16

标签: knockout.js gruntjs requirejs

使用grunt-contrib-requirejs构建项目时,我的knockout components'模块(仅在组件本身(textmapping中引用)不会获得添加到我的压缩输出脚本文件。

我的淘汰赛模块:

define(['knockout', 'text!./foo.html', 'mapping'], ....)

由于组件是在运行时异步注入的 - AFAIK - grunt-contrib-requirejs无法接收它们并将它们添加到我的压缩文件out: "<%= settings.getBuildPath() %>/js/lib/require/require.js",下面:

grunt config:

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']
        }
    }       
}

如果我在另一个不是淘汰组件模块的脚本文件中引用它们,那么项目构建正常。

那么,我怎样才能让grunt-contrib-requirejs添加我的组件中引用的脚本呢?

2 个答案:

答案 0 :(得分:2)

我对此问题的解决方案是使用模块注册组件,并在此处要求模板和视图模型以确保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();
});

答案 1 :(得分:1)

根据应用程序的大小,您可能希望将所有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任务准备templates.js,它声明组件加载器使用的templateCache变量,但是需要我手动注册KO组件。您可以通过遵循命名约定并从文件夹结构生成注册文件来避免这种情况。我的应用程序相对简单,因此我最终进行了手动注册,并且没有采取额外措施。