Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to solve a conflict between browserify (Backbone based app) and require.js on the same page?

I have a backbone app up and running correctly. It's meant to be used as a widget in 3rd pages. Unfortunately, I just realised that one of these pages has already Backbone / underscore loaded.

I get errors such as this:

Uncaught TypeError: Cannot read property 'extend' of undefined 

Which usually appear when underscore has not been previously loaded.

My typical view is like this: (normal Backbone view)

./view1.js

var Backbone = require('backbone')
var _ = require('underscore')
var $ = require('jquery')
Backbone.$ = $

module.exports = Backbone.View.extend({

  events: {

  },

  initialize: function () {

  },

  render: function () {

  }
})

then I just have to call it:

var View1 = require('view1')
var view1Instance = new View1(...)

Thanks for any help :)

EDIT after investigation: When running through the debugger, it appears that the Backbone variable is an empty object instead of being Backbone. As if the require('backbone') just returned {}

EDIT2: It seems related to this issue: https://github.com/substack/node-browserify/issues/790

like image 382
Kev Avatar asked Dec 14 '22 19:12

Kev


2 Answers

The problem with Backbone and Requirejs (as indicated by thlorenz here)

  • backbone looks for define before looking for module.exports
  • requirejs works with globals which is not good practice and in this case causes problems since it affects everything that runs in the same browser tab

He advises to wrap everything in a scope and hide the define function. He has also a tool to do that.browserify-shim

However I did not use that but the postBundleCB option from Browserify: (thx to a coworker).

In my Gruntfile:

browserify: {
  dist: {
    src: ['src/app/app.js'],
    dest: 'www/app.js',
    options: {
      postBundleCB: function (err, src, next) {
        return next(null, '(function () { var define = undefined; '+src+' })();')
      }
    }
  }
},

This solved my problem :)

I didn't try browserify-shim, so I don't know much about it.

like image 61
Kev Avatar answered Dec 28 '22 05:12

Kev


In case someone is using gulp and the official browserify (so postBundleCB is not available) I used gulp-wrap to wrap the 'define' definition:

var wrap = require('gulp-wrap');

[...]

bundler.bundle()
  .on('error', swallowError)
  .pipe(source(file))
  .pipe(wrap('(function () { var define = undefined; <%=contents%> })();'))
  .pipe(rename(renameOptions))
  .pipe(gulp.dest(argv.output?argv.output:'./dist'));
like image 39
Raphael Isidro Avatar answered Dec 28 '22 07:12

Raphael Isidro