使用r.js打包一个使用'text'加载视图的SPA应用程序 [英] Using r.js to package a SPA application that loads views using 'text'

查看:244
本文介绍了使用r.js打包一个使用'text'加载视图的SPA应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



在dev中,我成功地使用'text'按照构建durandal应用程序的标准方式动态加载视图。不同的是,我需要为视图做一些服务器端模板,所以它们实际上是动态生成的。



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

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

Uncaught TypeError:undefined不是函数 code> text.load 放在以下行:

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

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



我的grunt配置是:

  / *全局模块,要求* / 

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

//允许配置对象合并到一起的库
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,//允许混合制表符和空格
-W004:true,//需要避免TS伪造继承错误
忽略:[
'App / main -built.js'//建立/压缩文件
]
},
all:[//在这些文件上运行jshint
'gruntfile.js',
'App / ** / *。js'
]
},
// TODO:可以在这里添加jasmine来执行JS测试
clean:{
build:['build / *']
},
copy:{
scripts:{
src:'Scripts / ** / **',
dest :'build /'
}
},
durandal:{
main:{
src:[
'App /**/*.* ',
'!App / main-built.js',//忽略
'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,//防止绑定.html(因为我们是动态生成的这些内容)
优化:'无',/ /关闭优化 - uglify将单独运行grunt来做到这一点
出:'构建/应用程序/主-built.js'
}
}
},
uglify:{
options:{
banner:'/ *! <%= pkg.name%> <%= grunt.template.today(yyyy-mm-dd)%> \\\
'+
'*版权所有(c)<%= grunt.template.today(yyyy)%> Kieran Benton \\\
'+
'* / \''
},
build:{
src:'build / App / main.js',
dest:'build / App / main-built.js'
}
}
}
);

//载入插件
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');

//只有一个咕噜任务
grunt.registerTask('build',[
'jshint',
'clean',
'copy' ,
'durandal:main']);
};


解决方案

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



要解决这个问题,可以将RequireJS包含在捆绑包中而不是Almond中。请参阅此处的示例。你必须在r.js配置文件的路径部分为 require.js 创建一个别名为 require 是一个特殊的保留依赖项名称。然后,在配置的名称字段中指定此别名,而不是Almond。您将得到如下所示的内容:

options:{
name:'requireLib ',//使用别名
baseUrl:requireConfig.baseUrl,
mainPath:'App / main',
paths:mixIn(
{},
requireConfig。路径,
{'requireLib':'../Scripts/require.js'}),//声明别名
exclude:[],
inlineText:false,
优化:'none',
out:'build / app / main-built.js'
}


I'm attempting to build a SPA application (requirejs, durandal 2, knockout) into a single main-build.js file using grunt, and I'm running into serious issues with the 'text' plugin that durandal is using to load my views.

In dev, I'm successfully using 'text' to load views dynamically as per the standard way of building durandal apps. The difference is that I need to do some server side templating for the views and so they are actually being dynamically generated.

With that in mind I'd like to use r.js to package the apps models, view models and services (via the grunt-durandal plugin) into a single file, but to NOT package the views (.html) and still load them dynamically as needed.

In my grunt config, I'm using the inlineText: false option - which I have checked is suppressing the 'text!*' modules in the build. But when I run the application I'm getting:

Uncaught TypeError: undefined is not a function from inside text.load on the following line:

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

The module name being loaded seems to be correct (its a 'text!*' one) but beyond that I have no idea how to proceed to debug this issue. What am I doing wrong?

My grunt configuraiton is:

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

解决方案

Almond doesn't support dynamic loading. It doesn't implement require.toUrl and doesn't support asynchronous loader plugins. James Burke, the creator of RequireJS and Almond, answered about the same issue here.

To work around this, you can include RequireJS into the bundle instead of Almond. See an example here. You have to create an alias for require.js in the paths section of the r.js config as require is a special reserved dependency name. Then, specify this alias in the name field of the config instead of Almond. You'll get something like this:

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

这篇关于使用r.js打包一个使用'text'加载视图的SPA应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆