Domanda

I’m developing a multi-page app, using requirejs to manage my javascript libs / dependencies. My idea is that i'll have a main.js that holds the config, and then an .js file for each page that needs it, for example "register.js"

My require config is in javascripts/main.js

requirejs.config({
     baseUrl: '/javascripts',
     waitSeconds: 200,
     paths: {
          'async': 'lib/require.async',
          'jquery': 'lib/jquery-1.7.2.min',
          'knockout': 'lib/knockout-3.0.0'
});

I’ve got a knockout view model that looks like this: javascripts/viewModels/userDetailsViewModel.js

define(['knockout'], function(ko) {
    return function() {
        var self = this;

        self.name = ko.observable();
        self.email = ko.observable();
});

My ‘entry point’ is javascripts/register.js

require(['./main', 'knockout', 'viewModels/userDetailsViewModel'], function(main, ko, userDetailsViewModel) {
    ko.applyBindings(new userDetailsViewModel());
});

On my register.html page, i’ve got the script reference like this:

<script data-main="/javascripts/register" src="/javascripts/lib/require.js"></script>

When my page loads, I get these errors in the console:

GET http://localhost:3000/javascripts/knockout.js 404 (Not Found)

and

Uncaught Error: Script error for: knockout

I’m not sure why it’s looking for knockout.js - I’ve specified knockout in the paths section of my config, to look in lib/knockout-3.0.0

My dir structure is:

javascripts/
Most of my pages js files go here

javascripts/viewModels
Has knockout viewmodels

javascripts/lib Contains knockout, jquery, requirejs etc...

È stato utile?

Soluzione

The problem is that RequireJS will execute the call require(['./main', 'knockout', 'viewModels/userDetailsViewModel'] without a configuration. Yes, ./main is listed before knockout but there is no order guarantee between the dependencies passed in a single require call. RequireJS may load ./main first, or knockout first. And even if ./main were loaded first by this specific call, I believe it would not have any impact on how the other modules loaded by this call would load. That is, I think this require would operate on the basis of the configuration that existed at the time it was called, and that any configuration changes caused by the modules it loads would take effect only for subsequent require calls.

There are many ways to fix this. This should work:

require(['./main', function(main) {
    require(['knockout', 'viewModels/userDetailsViewModel'], function(ko,  userDetailsViewModel) {
        ko.applyBindings(new userDetailsViewModel());
    });
});

Or you might want to restructure your files and what you pass to data-main so that your requirejs.config is loaded and executed before your first require call. Here's an example of restructuring. Change your entry point to be /javascripts/main.js:

<script data-main="/javascripts/main.js" src="/javascripts/lib/require.js"></script>

Change /javascripts/main.js so that it contains:

requirejs.config({
     baseUrl: '/javascripts',
     waitSeconds: 200,
     paths: {
          'async': 'lib/require.async',
          'jquery': 'lib/jquery-1.7.2.min',
          'knockout': 'lib/knockout-3.0.0'
});

require(['knockout', 'viewModels/userDetailsViewModel'], function(ko, userDetailsViewModel) {
    ko.applyBindings(new userDetailsViewModel());
});

And remove /javascripts/register.js. This would be one way to do it. However, it is hard for me to tell whether this would be what you want in your specific project, because I do not know the whole project. The way to restructure for your specific project really depends on what other pages might use RequireJS, what information is common to all pages, what is specific to each page, whether you use a template system to produce HTML, etc.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top