Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Browserify and RequireJS on the same page?

So i've come across an interesting use case where i'm using Browserify to bundle all of my assets together in a project, but a large external (external to the project) module needs to be loaded in when a certain in-app window is accessed. (It's a video player module made up of three scripts that get pulled in asynchronously when required).

At the moment i'm getting all kinds of errors from uncalled object errors if the requireJS module is loaded in before the Browserified app.js file, to cannot find module errors if loaded in after the Browserified code.

Is there anyway i can get Browserify and RequireJS to play nicely on the same page? I'm losing my mind!

like image 298
Scotty Avatar asked Jun 11 '14 17:06

Scotty


3 Answers

TL;DR - use window.require in your browserified script.

Maybe it would still help someone. I happen to use an 'external' dojo-based library totally based on requireJS-style AMD, which is absolutely un-"browserifyeble" and un-convertable to CommonJS or anything sane. My own code is totally Browserified. It's working OK like this:

  1. Load the AMD loader (which defines the global require function) before the browserified script:

    <script src="dojo/dojo.js"></script> <!-- RequireJS/AMD loader, defining a global 'require'-->
    <script src="app/main.js"></script> <!-- The Browserify bundle -->
    
  2. In your own js, call the require function on window object ('cause you'll have a local browserify-require shadowing the global one)

    window.require(['dojo/dojo'], function (dojo) { ... });
    
  3. The 'external' app or library, which calls require on its own to load submodules etc., works just fine 'cause that code is out of browserify context and the global require is not shadowed there.

Maybe if you have some pure nice standard RequireJS modules, you could somehow convert them to be Browserifiable, but in my case that wasn't an option.

like image 151
Sergey B Avatar answered Nov 11 '22 15:11

Sergey B


For a gulp friendly solution (similar to what @Cride5 proposed) you can use gulp-derequire plugin.

Basic example from docs:

var derequire = require('gulp-derequire');
var browserify = require('browserify');
var source = require('vinyl-source-stream');

gulp.task('build', function() {
    var bundleStream = browserify({entries: './index.js', standalone: 'yourModule'}).bundle();
    return bundleStream
        .pipe(source('yourModule.js'))
        .pipe(derequire())
        .pipe(gulp.dest('./build'));
});

Plugin is also based on derequire module so all options are supported.

like image 45
Olga Avatar answered Nov 11 '22 14:11

Olga


There is a tool called browserify-derequire that resolves this issue by renaming browserify's require statmenets to avoid the naming collision.

It can be installed with npm using:

npm install -g browserify-derequire

Use it as a browserify plugin by changin your build command to:

browserify src/*.js -p browserify-derequire > module.js

There is more discussion on this issue at: https://github.com/substack/node-browserify/issues/790

like image 3
Cride5 Avatar answered Nov 11 '22 14:11

Cride5