7

Project Intro

My project is a single page storefront. The project has multiple modules, and each module contains a set of controller.js, view.js and model.js files, as well as a template.html file. And uses requirejs to manage dependencies.

Problem Statement

I want to use mainConfigFile to provide paths to reference modules in grunt-requirejs. Part of my mainConfigFile's require.config is stored in separate file (base.dependency.config), and require.config.paths are pieced together by underscore at runtime.

base.dependency.config

config = {
    baseDependencyConfig: {
        paths: { ... }
        shim: { ... }
    }
}

main.js

var dependencies = config.baseDependencyConfig;
var basePaths = config.baseDependencyConfig.paths;
var extensionPaths = {
    // extra sets of paths
};

// combine base paths and extension paths at runtime using underscore
var dependencyPaths = _.extend(basePaths, extensionPaths);

dependencies.paths = dependencyPaths;
require.config(dependencies);

// application startup
require(['app', 'eventbus']) {
    // code
}

Error

However, grunt requirejs is ignoring mainConfigFile, grunt requirejs tries to find 'app.js' under root, when in fact, 'app' is defined under require.config paths as

'app': 'modules/base/app/base.app.controller'

my gruntFile:

module.exports = function (grunt) {
    grunt.initConfig({
        // ... other plugin config
        requirejs: {
            options: {
                baseUrl: 'public',
                // the paths for the named modules such as 'app' are defined 
                // in main.js under require.config paths
                name: 'main',
                include: [
                    'app',
                    'cart',
                    'category'
        ],
        out: 'public/build/app-optimized.js',
        mainConfigFile: 'public/main.js',
        findNestedDependencies: true,
        optimizeCss: 'none',
        cssImportIgnore: 'style/style.css, style/mocha.css',
            }
        }
    })
}

my file structure

public
    |--modules/
    |       |--base/
    |       |       |--cart
    |       |       |--category
    |       |               |--category.controller.js
    |       |               |--category.view.js
    |       |               |--category.model.js
    |       |               └-category.template.html
    |       |
    |       └--extension/
    |
    |--style/
    |--image/
    |--main.js <-- main config file
    |--other .js files
  • mainConfigFile, main.js lives in root, along with a few other application startup js files
  • main bulk of application files lives inside modules folder
  • each module folder contains its controller, view and model js file, as well as a template.html file

Edit

the gruntFile worked before, with different mainConfigFile (main.js) setup:

require.config({
    paths: {...}
    shim: {...}
})

// application startup
require(['app', 'eventbus']) {
    // code
}
Anna Morning
  • 522
  • 1
  • 5
  • 18
  • What happens if you add a forward slash to the baseURL like `baseUrl: '/public'`? Also where is requirejs located? – Dropzilla Oct 16 '13 at 23:06
  • `requirejs` is located inside `public/scripts/lib` folder. And `/public` doesn't work, because truthfully speaking, `public` isn't the root folder I execute grunt. Public is the only the root folder for app. There are other component of the project, e.g. `stylesrc`(for css less), unit test, node modules etc living on the same level of public. – Anna Morning Oct 17 '13 at 16:26
  • Is it possible then that you are not traversing back far enough, so like `../../public`? – Dropzilla Oct 17 '13 at 17:49
  • Hi Dropzilla, thank you for answering my question. I don't believe finding public or requirejs is the problem. The exact setup with same gruntFile and file structure worked when the require.config.paths are all defined inside main.js directly. Please see the *edit* section of post above. – Anna Morning Oct 17 '13 at 19:12
  • @user2480414, Did you get it running so far? I have a similar project layout (though a bit simpler RequireJS configurtation implmentation) and am facing the same error: r.js/RequireJs does not respect my path configuration trying to load "jquery.js" from `baseUrl` instead the configured relative path "../libs/jquery-N.NN.js" (with version suffix). – try-catch-finally Apr 22 '14 at 06:26

1 Answers1

3

r.js uses Esprima as Javascript parser to extract the config object from the specified mainConfigFile. It only looks for certain signatures in the code.

Look at

  • hasRequire(): determine the AST node is a configuration call candidate
  • findConfig(): calls the above deciding how to extract the config

I've created a patch making it aware of recognizing

requirejs.config(_VariableToExport = { ... });

This is limited and the Javascript parser approach makes it very complicated to make r.js able to extract configurations that were created by functions (like in your code) or so. This patch has not been submitted to the project yet. I'm struggling with bureaucracy yet.

I think the only working workaround so far is

  • not to use mainConfigFile
  • exporting the config as NodeJS module
  • requiring the main.js/config.js in Node (Grunt)
  • passing the object as value to the config attribute or method

See my comment to this issue for a scribble.

This approach is proven in another, a bit older project I'm working on.

Related to r.js 2.1.11.

try-catch-finally
  • 7,436
  • 6
  • 46
  • 67