Search code examples
javascriptknockout.jsgulpdurandalalmond

Knockout Components "Uses require, but no AMD loader is present"


I am currently working in a Durandal project and researching the use of Knockout Components in my application. I'm building using Gulp and the gulp-durandal plugin and have it configured to use almond.

I'm running into an issue where I receive the following error when navigating to one of my pages which uses the newly registered components:

component: function () { return componentBindingValue; }" Message: Component 'myComponent': Uses require, but no AMD loader is present

In the hopes of providing as much information as possible, here is the gulpfile I am currently using as well.

var gulp = require('gulp');
var durandal = require('gulp-durandal');

gulp.task('durandal', function() {
    durandal({
        baseDir: 'app',
        main: 'main.js',
        output: 'main-built.js',
        almond: true,
        minify: true,
        rjsConfigAdapter: function (rjsConfig) {
            rjsConfig.paths = {
                'text': '../Scripts/text',
                'durandal': '../Scripts/durandal',
                'plugins': '../Scripts/durandal/plugins',
                'transitions': '../Scripts/durandal/transitions',
                'dataservice': 'domain/dataservice'
            };

            return rjsConfig;
        }
    }).pipe(gulp.dest('build'));
});


Solution

  • The Durandal Gulp task is calling r.js with the wrap parameter configured to encapsulate your application code in an IFFE with the Almond source. Unfortunately, Almond's require, requirejs, and define implementations are getting bundled inside and not being added to the global window scope the way Knockout is expecting.

    You can manipulate the wrap parameter in the rjsConfigAdapter to remove the IFFE wrappers, or just add require/define to the window object first thing in your application code to get around this.

    Ex.

    requirejs.config(config);
    window.require = require;
    window.requirejs = requirejs;
    window.define = define;