Cuando utilizo grunt-contrib-requirejs para crear mi proyecto, mi módulos knockout ', a los que solo se hace referencia en el componente en sí (text y mapping) no se agregarán a mi archivo de secuencia de comandos de salida comprimido.

mi módulo eliminatorio:

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

Dado que el componente se inyecta de forma asincrónica en tiempo de ejecución - AFAIK - grunt-contrib-requirejs no los recoge y los agrega a mi archivo comprimido, out: "<%= settings.getBuildPath() %>/js/lib/require/require.js", a continuación:

configuración de gruñido:

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

Si hago referencia a ellos en otro de mis archivos de script que no son un módulo de componente eliminado, el proyecto se construye bien.

Entonces, ¿cómo puedo hacer que grunt-contrib-requirejs agregue scripts a los que también se hace referencia en mis componentes?

2
Johan 30 ene. 2016 a las 00:22

2 respuestas

La mejor respuesta

Mi solución a este problema es usar un módulo para registrar componentes y requerir las plantillas y modelos de vista aquí para asegurar que r.js los incluirá en el paquete.

Normalmente requiero y llamo a este módulo en 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();
});
2
lagerone 30 ene. 2016 a las 17:11

Dependiendo del tamaño de su aplicación, tal vez le gustaría colocar todo su HTML en un solo archivo JS y usar el cargador de componentes Knockout personalizado.

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'));
});

Y debajo el código de registro de la plantilla. Está en TypeScript, pero debería traducirse fácilmente a 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");

Esencialmente, mi tarea gruñona preparar templates.js que declara la variable templateCache que es utilizada por el cargador de componentes, pero es necesario que registre manualmente los componentes KO. Puede evitarlo siguiendo las convenciones de nomenclatura y la generación del archivo de registro a partir de la estructura de su carpeta. Mi aplicación era relativamente simple, así que termino con el registro manual y no hago ese paso adicional.

1
codevision 30 ene. 2016 a las 19:17