requirejsgrunt-contrib-requirejsrequirejs-optimizer

Requirejs optimized file is not executed


I am seriously missing some vital element on how to use the r.js optimiser. This is probably a trivial answer for many, but I can for the life of me not figure out the problem. I've set up my environment using a grunt task to build an optimised file. The optimised file is built and dependencies seems to resolve correctly, but the code in my mainfile is never executed.

I've created a minimal environment to help you help me where there is pretty much only the Gruntfile, the mainfile and some dependencies (jquery, almond).

My project structure is:

require_this/
│
├──Gruntfile.coffee
│
└──src/
    │
    ├──index.html 
    │
    ├──bower_components/(jquery,almond,requirejs)
    │
    └──app/
        │
        └──main.js

Gruntfile:

module.exports = (grunt) ->
  'use strict'

  grunt.initConfig
    pkg: grunt.file.readJSON 'package.json'
    settings:
      distDirectory: 'dist'
      srcDirectory: 'src'
      tempDirectory: '.temp'
      allFile: 'main.js'
    clean:
      working: ['<%= settings.tempDirectory %>', '<%= settings.distDirectory %>']
      finished: ['<%= settings.tempDirectory %>']

    copy:
      app:
        files: [
          cwd: '<%= settings.srcDirectory %>'
          src: '**'
          dest: '<%= settings.tempDirectory %>'
          expand: true
        ]

    requirejs:
      scripts:
        options:
          baseUrl: '<%= settings.tempDirectory %>'
          mainConfigFile: '<%= settings.tempDirectory %>/app/main.js'
          optimize: 'none'
          logLevel: 0

          findNestedDependencies: true
          name: 'main'
          include: ['requireLib']

          paths:
            'main':       'app/main'
            'requireLib': 'bower_components/almond/almond'
          out: '<%= settings.distDirectory %>/<%= settings.allFile %>'

    processhtml:
      your_target:
        files:
          'dist/index.html': '.temp/index.html'

  grunt.loadNpmTasks 'grunt-processhtml'
  grunt.loadNpmTasks 'grunt-contrib-clean'
  grunt.loadNpmTasks 'grunt-contrib-copy'
  grunt.loadNpmTasks 'grunt-contrib-requirejs'

  grunt.registerTask 'build', [
    'clean:working'
    'copy:app'
    'requirejs'
    'processhtml'
  ]

index.html:

<!DOCTYPE html>
<head>
  <!-- build:js main.js --> 
  <!-- The line below will be changed to <script src="main.js"></script> after processhtml -->
  <script src="bower_components/requirejs/require.js" data-main="app/main.js"></script>
  <!-- /build -->
</head>
<body>
</body>

main.js

require.config({
  baseUrl: './',
  paths: {
    'jquery': 'bower_components/jquery/dist/jquery.min'
  }
});
define([
  'jquery',
], function ($) {
  console.log('changing html');
  $('body').append('<div>Hello World</div>');
});

After completing the build task, my dist directory will contain index.html and main.js file. The dist/main.js file will look like:

/*almond stuff*/
/*jquery stuff*/
require.config({
  baseUrl: './',
  paths: {
    'jquery': 'bower_components/jquery/dist/jquery.min'
  }
});
define('main',[
  'jquery',
], function ($) {
  console.log('changing html');
  $('body').append('<div>Hello World</div>');
});

Using a static fileserver against the uncompressed files works as expected. When using the build files, nothing is logged and nothing is added to the html even though the optimised file is loaded.

I suspect the answer is similar to Why is my RequireJS ignoring the code in my optimized main.js?, (some module name mismatch?) but I did not understand this well enough to fix my own problem.

Help is greatly appreciated!


Solution

  • The optimized version simply defines module main but it is never executed because it is never required. I'm not sure why is main executed in the non-optimized version.

    The main.js could have rather looked like:

    require.config({
      baseUrl: './',
      paths: {
        'jquery': 'bower_components/jquery/dist/jquery.min'
      }
    });
    
    // use require instead of define here
    require([
      'jquery',
    ], function ($) {
      console.log('changing html');
      $('body').append('<div>Hello World</div>');
    });
    

    the difference is that instead of defining a module this code requires jquery and passes it to the anonymous function, which is executed right away. It doesn't look like your app actually relied on that code being available as a module (the function doesn't return anything), so this change should be sufficient.