Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

concatenate requirejs modules into single file

I'm trying to concatenate all my requires modules and a few text templates into a single concatenated and uglified main.min.js, so I can include that file in my HTML.

I figured out concatenation and uglifying part. However, I am not able to actually run any code in the browser then.

I created a bare-bone project on github, to reproduce the problem.

File structure:

  • main.js
  • index.html
  • log.js
  • build-production
  • lib/require.js
  • node_modules/require/bin/r.js

I concatenate main.js, log.js and require.js using the build file build-production:

./node_modules/requirejs/bin/r.js -o build-production.js

main.js

require.config({
    paths: {
        requireLib : 'lib/require/require'
    },
    waitSeconds: 1000
});

console.log('loading main.js');

define(function(require) {
    var log = require('log');
    console.log('loaded')

    log.fine('main loaded');
});

build-production.js:

({
    mainConfigFile : 'main.js',
    include : [ 'requireLib' ],
    name : 'main.js',
    out : 'main.min.js' })

index.html:

<script src="main.min.js" type="text/javascript"></script>

so index.html in a browser should print out

loading main.js
loaded loaded main

but it only prints out the first line

loading main.js

anybody knows, why that is the case?

like image 628
forste Avatar asked Apr 02 '13 12:04

forste


1 Answers

I've just had a closer look at your code.

I'm not sure why you're loading in the minified file using:

<script src="main.min.js" type="text/javascript"></script>

It's still an AMD module, hence needs to be loaded in using an AMD loader (otherwise the define doesn't get handled).

This works:

<script type="text/javascript" src="lib/require/require.js"></script>
<script type="text/javascript">
    require(['main.min'], function () {
        require(['main'], function () {});
    });
</script>

Edit: whilst the outer require loads in the minified file (containing all modules), you also need a second, nested require to load the actual module still known as main.

It's quite misleading having a single module named main and then a minified version of all modules named main.min. For example, I might expect main to be exactly the same as main.min, but without any optimisations applied. You may consider renaming to something like:

  • entry-point: myApp
  • compiled (optimize: 'none'): main
  • compiled (optimize: 'uglify2'): main.min

Edit 2: in your build file:

name: 'main.js'name: 'main'

That will make requirejs name that module main instead:

define('main.js', ...);define('main', ...);

Now: require(['main']) finds (and loads) the module named main in the local scope of the compiled file.

Before: require(['main']) didn't find a module named main (it was named main.js) so treats it as a file name and loads ./main.js.

Edit 3: alternatively to Edit 2, in your build file you could retain:

name: 'main.js'

and add a path alias to either the build config or the run-time config:

paths: { 'main' : 'main.js' }

(This random thought comes with no warranty.)

like image 189
c24w Avatar answered Oct 28 '22 13:10

c24w