Unable to load jQuery plugins when using requirejs & r.js optimizer

可紊 提交于 2019-12-10 04:19:45

问题


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!


回答1:


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.




回答2:


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.




回答3:


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



来源:https://stackoverflow.com/questions/15371233/unable-to-load-jquery-plugins-when-using-requirejs-r-js-optimizer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!