2014-04-25 12 views
11

Ich versuche, eine SPA-Anwendung (requirejs, durandal 2, knockout) in eine einzige main-build.js-Datei mit Grunt und ich bin in ernsthafte Probleme mit dem 'Text' Plugin, das Durandal verwendet, um meine Ansichten zu laden.Verwenden von r.js zum Verpacken einer SPA-Anwendung, die Ansichten lädt mit 'Text'

In Dev, bin ich erfolgreich mit 'Text', um Ansichten dynamisch nach dem Standard-Weg der Erstellung Durandal-Anwendungen zu laden. Der Unterschied ist, dass ich einige Server-Templates für die Ansichten erstellen muss und sie daher tatsächlich dynamisch generiert werden.

In diesem Sinne möchte ich r.js verwenden, um die Apps Modelle zu verpacken, Modelle und Dienste (über das grunt-durandal-Plugin) in einer einzigen Datei zu packen, aber die Ansichten NICHT zu packen (.html) und laden sie immer noch dynamisch nach Bedarf.

In meiner grunt-Konfiguration verwende ich die Option inlineText: false - die ich überprüft habe unterdrückt die 'Text! *' Module im Build. Aber wenn ich die Anwendung ausführen ich erhalte:

Uncaught TypeError: undefined is not a function von innen text.load auf der folgenden Zeile:

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

Der Modulname geladen scheint korrekt zu sein (es ist ein ‚! Text *‘ one) Aber darüber hinaus habe ich keine Ahnung, wie ich vorgehen soll, um dieses Problem zu beheben. Was mache ich falsch?

Mein Grunzen configuraiton ist:

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

Antwort

10

Almond nicht unterstützt dynamische Belastung. Es implementiert require.toUrl nicht und unterstützt keine asynchronen Ladeprogramm-Plugins. James Burke, der Schöpfer von RequireJS und Almond, beantwortete das gleiche Problem here.

Um dies zu umgehen, können Sie RequireJS anstelle von Almond in das Bundle einschließen. Siehe ein Beispiel here. Sie müssen einen Alias ​​für require.js im Bereich paths der Konfiguration r.js erstellen, da require ein spezieller reservierter Abhängigkeitsname ist. Geben Sie dann diesen Alias ​​im Feld name der Konfiguration anstelle von Almond an. Sie werden so etwas wie dieses:

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

Gibt es eine Möglichkeit, r.js zu verwenden, um ein optimiertes Paket zu erstellen, aber immer noch die Vollversion von require js (und nicht Mandel), die Sie kennen? Ich bin nicht sicher, was ich als nächstes am besten mache ... –

+0

Hallo Dorn, ich habe auch das gleiche Problem damit, aber ich benutze Schluck-Durandal.Kannst du mir helfen zu erklären/zeigen mehr Details, wie das zu beheben? Ich bin sehr neu in diesen Dingen. Vielen Dank! –

0

Ich will nur auf diese Frage etwas mehr Kontext hinzuzufügen, da ich kommen immer zur Führung, um es zurück und löste schließlich mein Problem. Ich verwende Durandal w/TypeScript und grunt für die Optimierung. Ich bekam einige Ausnahmen um das Text-Plugin, z.

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

landete ich den relativen Pfad zu entfernen und nur Sie folgendermaßen vorgehen:

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

Damit ich in der Lage war, alles zu bekommen, mit der optimiertes Build-Arbeiten.