Pregunta

I'm just getting started with Require.js. I have the basics working.

Here's the issue I'm trying to solve: I'm using KnockoutJs and Knockout.validation. I always use these files together. So I'd like to do something where I only have to reference knockout and it will include knockout.validation.

This: (loading both knockout and knockout.validation)

define(["knockout"],
    function (ko) {     
        return {
            name: ko.observable();
        };
    }
);

Instead of this:

define(["knockout", "kovalidation"],
    function (ko) {     
        return {
            name: ko.observable();
        };
    }
);

I need the reference to ko, I just need the other(s) loaded.

Update:

based on the answer bellow I'm trying the bundle configuration option. Unfortunately I can't get it to work.

My understanding is the config should look like:

<script>
    var require = {
        baseUrl: "/Scripts",
        bundles: {
            'knockout-3.0.0': ['knockout.validation']
        }
    };
</script>
<script src="~/Scripts/require.js" data-main="views/home"></script>

Then in my home.js:

require(["knockout-3.0.0"], function (ko) {
   ...
});

Inside home.js, I would expect to see that knockout and knockout.validation are both loaded, but only knockout is loaded.

Update:

It seems like the bundle option in the configuration should do what I need, but at least at this point and with the information I have, it's not the right solution. @daedalus28 gave some good information and a good example that helped me come up with a solution that is acceptable. I have accepted that answer, if a better answer comes a long, please up vote it so we'll all know it's better.

¿Fue útil?

Solución

I often have a LibraryPlugins module which I load in my initial require call. In that module, I load up all of the plugins I want available everywhere - like knockout bindings, underscore mixins, jquery plugins, etc. Since it's one of my first require calls, I know the extensions it adds are generally available throughout my application

Sometimes I will take a more modular approach and have one extra module for each library which returns the library it's operating on (i.e. one for knockout with custom bindings that returns ko and one for underscore with custom mixins that returns a modified underscore). That approach ends up looking much like Louis's answer, but without the extra map:* config. Some modules expose themselves as a named module which makes it a bit more difficult to work with - that's when you'd use the map:* alias like in Louis's solution. For projects where I'm not using a ton of different libraries, I tend to just have one LibraryPlugins module as it is easier to manage when there's a small number of dependencies.

Here's a jsfiddle where I show both approaches.

For convenience I'll also paste the code in here:

require.config({
    paths: {
        'knockout':'//cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min',
        'knockout.validation': '//cdnjs.cloudflare.com/ajax/libs/knockout-validation/1.0.2/knockout.validation.min',
        'underscore.core': 'http://underscorejs.org/underscore-min',
        'underscore.string': 'http://epeli.github.com/underscore.string/lib/underscore.string'
    },
    shim: {
        'underscore.core': {exports:'_'}
    }
});

// Approach 1: One module to load everything in advance
define('LibraryPlugins', ['knockout', 'knockout.validation'], function(ko){ });

// Approach 2: One module for each library
define('underscore', ['underscore.core', 'underscore.string'], function (_, _string) {
    _.mixin(_string.exports());
    return _;
});

require(['knockout', 'underscore', 'LibraryPlugins'], function(ko, _) {
    console.log(ko.validation);
    console.log(_.humanize);
});

Otros consejos

Have you checked out the bundle property of require.config?

Introduced in RequireJS 2.1.10: allows pointing multiple module IDs to a module ID that contains a bundle of modules.

You could adapt the method used to load jQuery with noConflict. I'm adapting the following from the documentation on that method:

require.config({
    // Add this map config in addition to any baseUrl or
    // paths config you may already have in the project.
   map: {
      // '*' means all modules will get 'knockout-private'
      // for their 'knockout' dependency.
      '*': { 'knockout': 'knockout-private' },

      // 'knockout-private' wants the real knockout module
      // though. If this line was not here, there would
      // be an unresolvable cyclic dependency.
     'knockout-private': { 'knockout': 'knockout' }
   }
});

The knockout-private module would be something like this:

define(['knockout', 'kovalidation'], function (ko) {
    return ko;
});

You can add any number of other modules to knockout-private.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top