问题 使用r.js打包使用“text”加载视图的SPA应用程序


我正在尝试使用grunt将SPA应用程序(requirejs,durandal 2,knockout)构建到单个main-build.js文件中,并且我遇到了durandal用于加载我的'text'插件的严重问题观点。

在开发中,我成功地使用“文本”按照构建durandal应用程序的标准方式动态加载视图。不同之处在于我需要为视图做一些服务器端模板,因此它们实际上是动态生成的。

考虑到这一点,我想使用r.js将应用程序模型,视图模型和服务(通过grunt-durandal插件)打包到单个文件中,但不打包视图(.html)并仍然加载它们根据需要动态。

在我的grunt配置中,我正在使用 inlineText: false 选项 - 我检查过是在构建中禁止'text!*'模块。但是当我运行应用程序时,我得到了:

Uncaught TypeError: undefined is not a function 从内部 text.load 在以下行:

var parsed = text.parseName(name),
            nonStripName = parsed.moduleName +
                (parsed.ext ? '.' + parsed.ext : ''),
            url = req.toUrl(nonStripName), // EXCEPTION THROWN HERE

正在加载的模块名称似乎是正确的(它是'text!*'one)但除此之外我不知道如何继续调试此问题。我究竟做错了什么?

我的咕噜声是:

/*global module, require */

module.exports = function (grunt) {
'use strict';

// library that allows config objects to be merged together
var mixIn = require('mout/object/mixIn');

var requireConfig = {
    baseUrl: 'App/',
    paths: {
        'jquery': '../Scripts/jquery-2.1.0',
        'knockout': '../Scripts/knockout-3.1.0',
        'text': '../Scripts/text',
        'durandal': '../Scripts/durandal',
        'plugins': '../Scripts/durandal/plugins',
        'transitions': '../Scripts/durandal/transitions',
    }
};

grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    jshint: {
        options: {
            "-W099": true, // allowed mixed tabs and spaces
            "-W004": true, // needed to avoid errors where TS fakes inheritance
            ignores: [
                'App/main-built.js' // ingore the built/compacted file
            ]
        },
        all: [ // run jshint on these files
            'gruntfile.js',
            'App/**/*.js'
        ]
    },
    // TODO: could add jasmine here to do JS testing
    clean: {
        build: ['build/*']
    },
    copy: {
        scripts: {
            src: 'Scripts/**/**',
            dest: 'build/'
        }
    },
    durandal: {
        main: {
            src: [
                'App/**/*.*',
                '!App/main-built.js', // ignore the built file!
                'Scripts/durandal/**/*.js'
            ],
            options: {
                name: '../Scripts/almond-custom',
                baseUrl: requireConfig.baseUrl,
                mainPath: 'App/main',
                paths: mixIn(
                    {},
                    requireConfig.paths,
                    { 'almond': '../Scripts/almond-custom.js' }),
                exclude: [],
                inlineText: false, // prevent bundling of .html (since we are dynamically generating these for content)
                optimize: 'none', // turn off optimisations - uglify will run seperately by grunt to do this
                out: 'build/app/main-built.js'
            }
        }
    },
    uglify: {
        options: {
            banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> \n' +
                '* Copyright (c) <%= grunt.template.today("yyyy") %> Kieran Benton \n' +
                '*/\n'
        },
        build: {
            src: 'build/App/main.js',
            dest: 'build/App/main-built.js'
        }
    }
}
);

// loading plugin(s)
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-jasmine');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-open');
grunt.loadNpmTasks('grunt-durandal');

// only one grunt task
grunt.registerTask('build', [
    'jshint',
    'clean',
    'copy',
    'durandal:main']);
};

4017
2018-04-25 12:27


起源



答案:


杏仁不支持动态加载。它没有实现 require.toUrl 并且不支持异步加载器插件。 RequireJS和Almond的创建者James Burke回答了同样的问题 这里

要解决此问题,您可以将RequireJS包含在捆绑包中而不是Almond中。看一个例子 这里。您必须为其创建别名 require.js 在里面 paths r.js配置的部分为 require 是一个特殊的保留依赖名称。然后,在中指定此别名 name 配置字段而不是杏仁。你会得到这样的东西:

options: {
    name: 'requireLib', // use the alias
    baseUrl: requireConfig.baseUrl,
    mainPath: 'App/main',
    paths: mixIn(
        {},
        requireConfig.paths,
        { 'requireLib': '../Scripts/require.js' }), // declare the alias
    exclude: [],
    inlineText: false,
    optimize: 'none',
    out: 'build/app/main-built.js'
}

10
2018-04-27 21:42



有没有办法使用r.js来构建一个优化的包,但仍然包含你知道的require js(而不是杏仁)的完整版本?我不确定接下来我最擅长做什么...... - Kieran Benton
嗨,我也面临同样的问题,但我正在使用gulp-durandal。你能帮我解释/显示更多细节如何解决这个问题吗?我对这件事情很新。谢谢! - Fariz Azmi


答案:


杏仁不支持动态加载。它没有实现 require.toUrl 并且不支持异步加载器插件。 RequireJS和Almond的创建者James Burke回答了同样的问题 这里

要解决此问题,您可以将RequireJS包含在捆绑包中而不是Almond中。看一个例子 这里。您必须为其创建别名 require.js 在里面 paths r.js配置的部分为 require 是一个特殊的保留依赖名称。然后,在中指定此别名 name 配置字段而不是杏仁。你会得到这样的东西:

options: {
    name: 'requireLib', // use the alias
    baseUrl: requireConfig.baseUrl,
    mainPath: 'App/main',
    paths: mixIn(
        {},
        requireConfig.paths,
        { 'requireLib': '../Scripts/require.js' }), // declare the alias
    exclude: [],
    inlineText: false,
    optimize: 'none',
    out: 'build/app/main-built.js'
}

10
2018-04-27 21:42



有没有办法使用r.js来构建一个优化的包,但仍然包含你知道的require js(而不是杏仁)的完整版本?我不确定接下来我最擅长做什么...... - Kieran Benton
嗨,我也面临同样的问题,但我正在使用gulp-durandal。你能帮我解释/显示更多细节如何解决这个问题吗?我对这件事情很新。谢谢! - Fariz Azmi


只是想为这个问题添加一些额外的上下文,因为我一直回到它的指导,并最终解决了我的问题。我正在使用Durandal w / TypeScript和grunt进行优化。我在文本插件中遇到了一些例外,例如

<div data-bind="compose: { model: someObject, view: '../../components/something/something.html' }"></div>

我最终删除了相对路径,只是执行以下操作:

<div data-bind="compose: { model: someObject, view: 'components/something/something.html' }"></div>

通过这种方式,我能够通过优化的构建工作获得所有功能。


0
2018-01-18 22:17