7

I'm having a bit of trouble with my the requirejs optimizer. After I run the optimizer, I get a few error messages in my build/compiled file. When running my web application without the optimize step I do not have any errors.

This is my client.js file (contains config) (coffeescript)

requirejs.config
  baseUrl: '/source/'
  paths:
    text:                 'lib/text'
    io:                   'lib/socket.io'
    underscore:           'lib/underscore'
    backbone:             'lib/backbone'
    jquery:               'lib/jquery'
#    almond:               'lib/almond'
    bootstrap:            'lib/bootstrap'
    bootstrapFileUpload:  'lib/bootstrap-fileupload'
    jqueryUniform:        'lib/jquery.uniform'
    jqueryBrowser:        'lib/jquery.browser'
    datatables:           'lib/jquery.dataTables'
    datatables_bootstrap: 'lib/DT_bootstrap'
  shim:
    io:
      exports: 'io'
    jquery:
      exports: 'jQuery'
    jqueryBrowser:
      deps:    ['jquery']
    jqueryUniform:
      deps:    ['jqueryBrowser', 'jquery']
    underscore:
      exports: '_'
    backbone:
      deps:    ['underscore', 'jquery']
      exports: 'Backbone'
    datatables_bootstrap:
      deps:    ['jquery', 'datatables']
    datatables:
      deps:    ['jquery']


require ['routers/router', 'backbone'], (Router, Backbone) ->
  MainRouter = new Router()
  Backbone.history.start()

And here is my config for the optimizer. I run the optimizer from nodejs after requiring 'requirejs' as a module.

  config =
    baseUrl: __dirname + '/../client/source'
    name:    'lib/almond'
    include: './client'
    optimize: 'none'
    out:     __dirname + '/../client/' + hash + '.js'
    paths:
      text:                 'lib/text'
      io:                   'lib/socket.io'
      underscore:           'lib/underscore'
      backbone:             'lib/backbone'
      jquery:               'lib/jquery'
      bootstrap:            'lib/bootstrap'
      bootstrapFileUpload:  'lib/bootstrap-fileupload'
      jqueryUniform:        'lib/jquery.uniform'
      jqueryBrowser:        'lib/jquery.browser'
      datatables:           'lib/jquery.dataTables'
      datatables_bootstrap: 'lib/DT_bootstrap'
    shim:
      bootstrap:
        exports: 'bootstrap'
      bootstrapFileUpload:
        exports: 'bootstrapUpload'
      io:
        exports: 'io'
      jquery:
        exports: 'jQuery'
      jqueryBrowser:
        deps:    ['jquery']
      jqueryUniform:
        deps:    ['jqueryBrowser', 'jquery']
      underscore:
        exports: '_'
      backbone:
        deps:    ['underscore', 'jquery']
        exports: 'Backbone'
      datatables:
        deps:    ['jquery']
      datatables_bootstrap:
        deps:    ['jquery', 'datatables']



  requirejs.optimize config, (buildResponse) ->
    js = true
    if js && css
      require './server'
  , (err) ->
    console.log 'requirejs err'
    console.log err

The specific error I'm seeing in chrome is: "Uncaught TypeError: Cannot read property 'defaults' of undefined"

Which correlates to this snippet:

/* Set the defaults for DataTables initialisation */
$.extend( true, $.fn.dataTable.defaults, {

Any idea what might be going wrong? Thanks!

3 Answers 3

14

I encountered the same issue. I think the reason this error occurs is because DT_bootstrap.js is not a AMD module while it depends on the side effects of one. In this case jquery.dataTables.js.

When RequireJS optimizer combines all the modules you reference into one big JS file, the raw DT_bootstrap.js is somewhere in the middle of it, some place after jquery.dataTables.js. The problem is that DT_bootstrap.js is evaluated immediately when your combined js file is loaded. It wants $.fn.dataTable to be defined when it encounters the line:

$.extend( true, $.fn.dataTable.defaults, {

Since jquery.dataTables.js is a AMD module it has been compiled but not evaluated yet. Only in later code where it is required as a dependency will it be evaluated, and only then will it define $.fn.dataTable.

I worked around this by wrapping 'DT_bootstrap.js' in a AMD module definition, like is done here: https://github.com/amdjs/backbone/blob/master/backbone.js#L8-L24

For example:

(function(root, factory) {
  // Set up DT_bootstrap appropriately for the environment.
  if (typeof define === 'function' && define.amd) {
    // AMD
    define(['jquery', 'datatables', 'bootstrap'], function($) {
      factory($);
    });
  } else {
    // Browser globals
    factory(root.jQuery);
  }
}(this, function($) {
    // <--- original DT_bootstrap.js goes here 
}));

It solved the issue for me.

Sign up to request clarification or add additional context in comments.

2 Comments

hi, I'm struggling on this too. But my console says that $.fn.DataTable is not a function
In this line define(['jquery', 'dataTable', 'bootstrap'] replace 'dataTable' with your variable name from requirejs path of datatables
0

Peter is almost correct. The only thing he missed was that the defines must match Casey's config. So in the above answer, instead of:

define(['jquery', 'dataTable', 'bootstrap'], function($) ...

it would need to be:

define(['jquery', 'datatables', 'bootstrap'], function($) ...

Otherwise require js will look for the file dataTable.js and not the one it needs to retrieve.

1 Comment

I updated my answer with this change. Thanks @Mario.
0

Since require 2.1.11 the wrapShim option handle this problem, so you can keep the original source file.

3 Comments

I spent 5 mn trying this. and it does not work for the require.js seems wrapShim is only for r.js no"?
Dependencies management is the same before & after optimizing — the wrapShim option works in both cases :-) It seems that there are some limitations on this option, but when I've used it, it has worked without problems.
I posted an issue on the requirejs github. Let's see how it ends up. I thought the wrapShim option was only used by the r.js When you have a look into the require.js js you see nothing related to wrapShim github.com/jrburke/requirejs/issues/1149

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.