lcoder
lcoder

Reputation: 1

r.js cannot resolve dependencies mentioned in shim

I've recently joined a project which is built using Backbonejs, (uses Marionette for view rendering) + nodejs. They also use requirejs to load the backbonejs files. Would like to add at this stage, that I've never worked with backbonejs or requirejs before and hence I'm struggling with the issue I describe later.

Some code that will help explain the issue that I run into (All this code was already written by previous dev's)

Folder Structure:

/public
 /js
  /collection (consists all Backbone.js collections files)
  /lib
   /bower_components
    /backone
    /marionette
    /etc
  /models (consists all Backbone.js models files)
  /views (consists all Backbone.js view files)
  /main.js
  /main.build.js
  /app.js
  /controller.js
  /router.js

Code from files that I think relate to issue:

main.js

requirejs.config({
    paths: {
        'async': 'lib/bower_components/requirejs-plugins/src/async',
        'jquery': 'lib/bower_components/jquery/dist/jquery.min',
        'underscore': 'lib/bower_components/underscore/underscore-min',
        'lodash': 'lib/bower_components/lodash/dist/lodash.min',
        'backbone': 'lib/bower_components/backbone/backbone',
        'marionette': 'lib/bower_components/marionette/lib/backbone.marionette.min',
        'markercluster':'lib/markercluster',
        'jquerymobile': 'lib/jquery.mobile-1.4.0.min',
        'hogan': 'lib/template-2.0.0.min',
        'templates': '/templates',
        'real': 'lib/mainjs',
        'touch': 'lib/jquery.touchSwipe.min',
        'mouse': 'lib/jquery.mousewheel',
        'moment': 'lib/moment-2.5.1.min',
        'humanize': 'lib/bower_components/humanize-plus/public/dist/humanize.min',
        'validator': 'lib/bower_components/validator-js/validator.min',
        'real': 'lib/mainfile'
    },
    shim: {
        backbone: {
            deps: ["underscore"]
        },
        marionette: {
            deps: ["backbone"]
        },
        templates: {
            deps: ["hogan", "jquery"]
        },
        real: {
            deps: ["jquery", "jquerymobile", "touch", "mouse"]
        },
        markercluster: {
            exports: "MarkerClusterer"
        },
        humanize: {
            exports: "humanize"
        }
    },
    waitSeconds: 0
});

define('gmaps', ['async!http://maps.google.com/maps/api/js?v=3&key=AIzaSyBiV8f88yLWJ_IMSdP1fVNO1-gt3eLVSgg&sensor=true&callback=gMapsCallback'], function(){
// define('gmaps', ['http://maps.google.com/maps/api/js?v=3&sensor=false'], function(){
    return window.google.maps;
});

require(['app', 'templates', 'real'], function(app) {
    app.start({
        version: "0.9.9"
    });
});

main.build.js

({
    baseUrl: ".",
    name: "main",
    wrapShim: true,
    out: "main-built.js"
})

app.js

define(['underscore', 'controller', 'router', 'models/Cache', 'views/RootView'], function(_, Controller, Router, Cache, RootView) {
    var Application = Marionette.Application.extend({
        propertyListPageSize: 3,
        initialize: function() {
            _.templateSettings = { interpolate : /\{\{(.+?)\}\}/g };
        },
        onStart: function(options){
            new RootView();
            this.controller = new Controller();
            this.router = new Router({controller: this.controller});
            this.cache = new Cache();
            this.context = {};
            //this.evHistory = [];//@todo remove once BB/marionette navigation is in place
            if(Backbone.history) Backbone.history.start({ pushState: false });
            if(Backbone.history.fragment === "") this.navigate('home');
        },
        navigate: function(fragment, trigger, replace){
            this.router.navigate(fragment, {trigger:trigger, replace:replace});
        },
        back: function() {
            window.history.back();
        }
    });
    app = new Application();
    return app;

});

rootView.js

define(['marionette', 'views/HomeView', 'views/HeaderView', 'views/FooterView', 'views/MenuView', 'views/VideoView', 'views/LocationSearchView', 'views/LoginView', 'views/FindView', 'views/ServicesView', 'views/ValueView', 'views/PropertyListView', 'views/SideBySideView', 'views/ConfirmRegistrationView', 'views/ForgotPasswordView', 'views/CreateAccountView', 'views/UserHomeView', 'views/MyBrokerView', 'views/GiveFeedbackView', 'views/SeeFeedbackView', 'views/ViewingScheduleView', 'views/MyViewingsSummaryView', 'views/MyAccountView', 'views/ViewingConfirmView', 'views/ValueAddressPropertyListView'],
    function(Marionette, HomeView, HeaderView, FooterView, MenuView, VideoView, LocationView, LoginView, FindView, ServicesView, ValueView, PropertyListView, SideBySideView, ConfirmRegistrationView, ForgotPasswordView, CreateAccountView, UserHomeView, MyBrokerView, GiveFeedbackView, SeeFeedbackView, ViewingScheduleView, MyViewingsSummaryView, MyAccountView, ViewingConfirmView, ValueAddressPropertyListView) {
    var RootView = Marionette.LayoutView.extend({

    ...some view code

});

Use case I'm trying to solve:

So when I access the site in the browser, I notice in the debugger that it loads all the js files right at the beginning. During the load process my site is blank and user has to wait a while before he can use the site.

So what I've been able to understand is that when app is 'started' in main.js, app.js creates an instance of rootView.js , which in turn has all the views listed as dependencies. This triggers a download request for all the other views which in turn would solve their own dependencies and download all the relevant models and collections. Hence all files being downloaded when the user accessed the site.

Solution I've been trying:

Since requirejs is being used, I'm trying to use r.js to optimize and combine all the js files to reduce the number of downloads.

Issue I'm running into:

When i run r.js. i get the following error

Tracing dependencies for: main
Error: ENOENT: no such file or directory, open '/var/node_projects/rm/rm.src.server/src/public/js/underscore.js'
In module tree:
    main
      app

Error: Error: ENOENT: no such file or directory, open '/var/node_projects/rm/rm.src.server/src/public/js/underscore.js'
In module tree:
    main
      app

    at Error (native)

If I add the underscore.js files directly to the specified path in the error, then I get the same error for marionette.js. What I think is happening is that app.js is not recognizing the shim'ed dependencies and hence its trying to find the files directly at specified path in the error.

Things I've tried: - I've added wrapShim: true in the main.build.js file but that did not help

Honestly, I've been sitting on this for a couple of days and I'm not sure what I can do next and hence this post.

Any help/direction would be appreciated.

Upvotes: 0

Views: 128

Answers (1)

Julian V. Modesto
Julian V. Modesto

Reputation: 308

You need to include the same shim configuration in your build file, as wrapShim is not sufficient.

If shim config is used in the app during runtime, duplicate the config here. Necessary if shim config is used, so that the shim's dependencies are included in the build. Using "mainConfigFile" is a better way to pass this information though, so that it is only listed in one place. However, if mainConfigFile is not an option, the shim config can be inlined in the build config.

https://github.com/jrburke/r.js/blob/master/build/example.build.js

Upvotes: 0

Related Questions