requirejs / r.js

Runs RequireJS in Node and Rhino, and used to run the RequireJS optimizer
Other
2.57k stars 673 forks source link

add baseUrl in paths. #884

Open lzl124631x opened 8 years ago

lzl124631x commented 8 years ago

Is it possible to make the paths configuration like the below? so that I don't need to repeat, repeat and repeat myself.

paths: {
    {
        baseUrl: '..',
        paths: {
            foo: 'foo',
            bar: 'bar',
            {
                baseUrl: 'common',
                path: {
                    zoo: 'zoo'
                }
            }
        }
    },
    {
        baseUrl: 'lib',
        paths: {
            jquery: 'jquery',
            bootstrap: 'bootstrap'
        }
    },
    blabla: 'blabla'
}

Now I have to write:

paths: {
    foo: '../foo',
    bar: '../bar',
    zoo: '../common/zoo',
    jquery: 'lib/jquery',
    bootstrap: 'lib/bootstrap',
    blabla: 'blabla'
}

When there are lots of files in relative folder, I have to repeat the relative prefix again and again.

lzl124631x commented 8 years ago

My paths config:

paths: {
    // Preload
    "require-lib": "../../lib/require",
    "require.config": "../../common/require.config",
    "jquery": "../../lib/jquery",
    "bootstrap": "../../lib/bootstrap",
    "crossroads": "../../lib/crossroads",
    "hasher": "../../lib/hasher",
    "knockout": "../../empty:",
    "signals": "../../lib/signals",
    "text": "../../lib/text",
    "underscore": "../../lib/underscore",
    "komapping": "../../lib/knockout.mapping",
    "chart": "../../lib/chart",
    "recorder": "../../lib/recorder",
    "recorder-worker": "../../lib/recorderWorker",
    "wx": "../../lib/jweixin",
    "fastclick": "../../lib/fastclick",
    "hammer": "../../lib/hammer",
    "utils": "../../common/utils",
    "transition": "../../common/transition",
    "mtutor-service": "../../common/mtutor",
    "audio": "../../common/audio",
    "loading": "../../common/components/loading/loading",
    "messagebox": "../../common/components/messagebox/messagebox",
    "modeless": "../../common/components/modeless/modeless",
    "feedback": "../../common/components/feedback/feedback",
    // App Preload
    "stack": "../../common/stack",
    "carousel": "../../common/carousel",

    "router": "../../common/router",
    "helper": "../../common/helper",
},
lzl124631x commented 8 years ago

BTW, ask a question. my js files can be categorized into two groups:

  1. commonly used files, which I want to zip them into common.js and each WebApp uses this same common.js
  2. app-specific files, which I want to zip them into .js and each WebApp only includes its corresponding .js.

My problem is that, one js file (say, router.js) in the first group needs to be loaded after another file (say, app.js) in the 2nd group being loaded. So, router.js depends on app.js.

// router.js
define(['app'], function() { /*...*/ }

But when optimizing the first group of file, the r.js fails because I cannot specify the app.js at the moment (different webapp uses different app.js which locates in different folders).

lzl124631x commented 8 years ago

In the config for common.js(named commonConfig), I tried exclude: ['app'] but it didn't work.

Then I tried to add "app": "empty:" to paths of commonConfig. It works!

But another problem is that, I have to repeat all the paths of commonConfig in appSpecificConfig.

Why do I have to specify the path for xxx, even if I excluded xxx in config?

alexindigo commented 8 years ago

Idea is that you can put commonConfig into exclude list, and r.js will exclude all it's modules automatically.

Another way to do it is to use something like https://www.npmjs.com/package/multibundle that will generate proper r.js configs from shorter/more concise form (and run bundling for each bundle in parallel to speed up the process).

You can find example config here: https://github.com/alexindigo/multibundle/blob/master/test/fixtures/config.js

lzl124631x commented 8 years ago

@alexindigo Thanks for your reply.

Idea is that you can put commonConfig into exclude list, and r.js will exclude all it's modules automatically.

Did you mean that I can put app into exclude list? It doesn't work. If you did mean commonConfig, maybe you misunderstood my question.

I will make some investigation on multibundle :)

alexindigo commented 8 years ago

Hmm, it was 7am when I replied your comment, so I must've misunderstood you.

I thought your problem in repeating all the modules of commonConfig in the exclude section of appSpecificConfig, to combat this problem, you can just put common into the exclude list of appSpecificConfig. If it's something else, then maybe a little bit more elaborate can go a long way. :)

lzl124631x commented 8 years ago

@alexindigo Thanks for your patience :+1: Let me be specific.

// folder structure
* - dist
* - src
  | - common // js written by myself and shared between apps.
  | - lib  // libraries
  | - foo-app // the 1st app
  | - bar-app // the 2nd app
  | - r.config.js // config for r.js

// r.config.js
var commonConfig = {
   baseUrl: 'src',
   paths: {
    router: 'common/router'
   },
   include: [ 'router' ]
   out: '../dist/common.js'
};

var fooAppConfig = {
        baseUrl: 'foo-app'
    paths: {
        app: 'js/app'
    },
        include: [ 'app' ],
        out: '../../dist/foo-app.js'
}

var barAppConfig = {
        baseUrl: 'bar-app'
    paths: {
        app: 'js/app'
    },
        include: ['app'],
        out: '../../dist/bar-app.js'
}

// common/router.js
define(['app'], // <-- HERE is the problem. the dependency 'app' cannot be resolved when optimizing common.js
  function() {
  /* router depends on app.js because app.js provides some routing information for router.js.
     The routing logic stays the same, while the routing data varies across apps.
   */
});

// foo-app/js/app.js
define([], function() { 
/* routing data for foo-app */
});

// bar-app/js/app.js
define([], function() {
/* routing data for bar-app */
}

So the problem is that, the optimizing task for commonConfig cannot be done with the above config, because r.js is looking for the path for app, which is not important (and not determined because different app has different path of app.js) and should be ignored.

However, even if I add exclude: [ 'app' ] to commonConfig, r.js is STILL looking for the path for app... I need to set the path for app to "empty:".

var commonConfig = {
   paths: {
    router: 'common/router',
        app: 'empty:' <-- it works! but ugly.
   },
   include: [ 'router' ]
   out: '../dist/common.js'
};

Another version of this problem is that, in fooAppConfig, I need to copy all the paths from commonConfig to fooAppConfig, even if I exclude them!

// r.js configs
var commonConfig = {
   baseUrl: 'src',
   paths: {
    router: 'common/router',
    jquery: 'lib/jquery',
    bootstrap: 'lib/bootstrap',
    knockout: 'lib/knockout',
    crossroads: 'lib/crossroads',
    // ... and others
   },
   include: [ 'router' ]
   out: '../dist/common.js'
};

var fooAppConfig = {
    paths: {
        app: 'foo-app/js/app',
        jquery: 'lib/jquery', <-- excluded but I have to specify the path.
        bootstrap: 'lib/bootstrap', <-- excluded but I have to specify the path.
        knockout: 'lib/knockout', <-- excluded but I have to specify the path.
        crossroads: 'lib/crossroads', <-- excluded but I have to specify the path.
    },
        include: [ 'app' ],
        exclude: commonConfig.include, 
        out: '../dist/foo-app.js'
}