0

I keep seeing this error when executing the compiled file:

Uncaught Error: No json

Here's my current requirejs grunt task configuration:

requirejs: {
    options: {
            baseUrl: "build/repos/staging/dev",
            mainConfigFile: "dev/main.js",

            generateSourceMaps: false,
            preserveLicenseComments: false,

            name: "almond",
            out: "./static/js/compiled.js",
            //excludeShallow: ['vendor'],
            findNestedDependencies: true,
            removeCombined: true,
            //wrap: true,
            optimize: "uglify2",
            uglify2: {
                output: {
                    beautify: true,
                },
                lint: true,
                mangle: false,
                compress: false,
                compress: {
                    sequences: false
                }
            }
        }
    }

And here's my dev/main.js file:

// This is the runtime configuration file.
// It also complements the Gruntfile.js by supplementing shared properties.require.config({
waitSeconds: 180,
urlArgs: 'bust=' + (new Date()).getTime(),
paths: {

    "underscore": "../vendor/underscore/underscore",
    "backbone": "../vendor/backbone/backbone",
    "layoutmanager": "../vendor/layoutmanager/backbone.layoutmanager",
    "lodash": "../vendor/lodash/lodash",
    "ldsh": "../vendor/lodash-template-loader/loader",
    "text": "../vendor/requirejs-plugins/lib/text",
    "json": "../vendor/requirejs-plugins/json",
    "almond": "../vendor/almond/almond",

    // jquery
    "jquery": "../vendor/jquery/jquery",
    "jquery.transit": "../vendor/jquery.transit/jquery.transit",
    "jquery.mousewheel": "../vendor/jquery.mousewheel/jquery.mousewheel",
    "jquery.jscrollpane": "../vendor/jquery.jscrollpane/jquery.jscrollpane"
},

shim: {
    'backbone': {
        deps: ['underscore']
    },
    'layoutmanager': {
        deps: ['backbone', 'lodash', 'ldsh']
    },
    'jquery.transit': {
        deps: ['jquery']
    },
    'json': {
        deps: ['text']
    }
}});
// App initialization
require(["app"], function(instance) {
    "use strict";
    window.app = instance;
    app.load();
});

And finally, my dev/app.js file:

define(function(require, exports, module) {

"use strict";

// External global dependencies.
var _ = require("underscore"),
    $ = require("jquery"),
    Transit = require('jquery.transit'),
    Backbone = require("backbone"),
    Layout = require("layoutmanager");

module.exports = {

    'layout': null,

    'load': function() {

        var paths = [

                // ***
                // *** 1- define its path
                // ***

                'json!config/main.json',
                'modules/nav',
                'modules/store',
                'modules/utils',
                'modules/preloader',
                'modules/popup',
                'modules/login',
                'modules/user',
                'modules/footer',
            ];

        try {
            require(paths, function(

                    // ***
                    // *** 2- call it a name
                    // ***

                    Config,
                    Nav,
                    Store,
                    Utils,
                    Preloader,
                    Popup,
                    Login,
                    User,
                    Footer
                ) {

                    // ***
                    // *** 3- instance it in the app
                    // ***

                    app.Config = Config;
                    app.Nav = Nav;
                    app.Store = Store;
                    app.Utils = Utils;
                    app.Preloader = Preloader;
                    app.Popup = Popup;
                    app.Login = Login;
                    app.User = User;
                    app.Footer = Footer;

                    // require and instance the router
                    require(['router'], function(Router) {

                        // app configuration
                        app.configure();

                        // app initialization
                        app.Router = new Router();
                    });
            });
        } catch (e) {
            console.error(e);
        }
    },


    'configure': function() {

        var that = this;

        // set environment
        this.Config.env = 'local';

        // Ajax global settings
        Backbone.$.ajaxSetup({
            'url': that.Config.envs[that.Config.env].core,
            'timeout': 90000,
            'beforeSend': function() {
            },
            'complete': function(xhr, textstatus) {
            }
        });

        // Template & layout
        _.templateSettings = {
            interpolate: /\{\{(.+?)\}\}/g
        };

        Layout.configure({
            // Allow LayoutManager to augment Backbone.View.prototype.
            manage: true,
            // Indicate where templates are stored.
            prefix: "app/templates/",
            // This custom fetch method will load pre-compiled templates or fetch them
            // remotely with AJAX.
            fetch: function(path) {
                // Concatenate the file extension.
                path = path + ".html";
                // If cached, use the compiled template.
                if (window.JST && window.JST[path]) {
                    return window.JST[path];
                }
                // Put fetch into `async-mode`.
                var done = this.async();
                // Seek out the template asynchronously.
                $.get('/' + path, function(contents) {
                    window.JST[path] = contents;
                    done(_.template(contents));
                }, "text");
            }
        });
    },

};
});

Any ideas why is that json module not "required" when executing grunt requirejs ?

Thanks in advance.

Rich Scriven
  • 97,041
  • 11
  • 181
  • 245
whallz
  • 2,365
  • 2
  • 22
  • 24

1 Answers1

0

Not sure if this is still an issue, but from the requirejs optimizer docs (http://requirejs.org/docs/optimization.html):

The optimizer will only combine modules that are specified in arrays of string literals that are passed to top-level require and define calls, or the require('name') string literal calls in a simplified CommonJS wrapping. So, it will not find modules that are loaded via a variable name...

It sounds like the requirejs optimizer doesn't like the require calls being made with a variable that is an array of dependencies.

It also sounds like the requirejs optimizer doesn't like the syntax of require([dependency array], callback) being used within the actual file being optimized.

You may have to refactor your dependency declarations within dev/app.js to conform to this specification. For example, you might be able to use the following refactoring of steps 1 and 2:

var Config = require('json!config/main.json');
var Nav = require('modules/nav');
var Store = require('modules/store');
var Utils = require('modules/utils');
var Preloader = require('modules/preloader');
var Popup = require('modules/popup');
var Login = require('modules/login');
var User = require('modules/user');
var Footer = require('modules/footer');

If this does work, it looks like you'll also have to do something similar for the Router dependency declaration.

Also, a minor addition that you might want to include to your requirejs configuration once you get it running is:

stubModules : ['json']

Since the built file should have the JSON object within it, you won't even need the plugin within the built file! As such, you can reduce your file size by removing the json plugin from it.

pieceOpiland
  • 361
  • 3
  • 10