gulp-browserify icon indicating copy to clipboard operation
gulp-browserify copied to clipboard

Trouble with external (multiple bundles)

Open vincentmac opened this issue 11 years ago • 15 comments

I'm having trouble setting up multiple bundles. What I am trying to do is have one task to bundle my vendor libraries (vendor.js) and another task to bundle my application logic (main.js).

My vendor task is something like this:

var bower = 'app/bower_components';

// Vendor
gulp.task('vendor', function () {
  return gulp.src([
    bower + '/angular/angular.js',
    bower + '/angular-route/angular-route.js',
    bower + '/lodash/dist/lodash.js'
    ])
    .pipe($.browserify({
      debug: true,
      insertGlobals: true,
      transform: [
        'debowerify'
      ],
      shim: {
        angular: {
          path: bower + '/angular/angular.js',
          exports: 'angular'
        },
        'angular-route': {
          path: bower + '/angular-route/angular-route.js',
          exports: 'ngRoute',
          depends: {
            angular: 'angular'
          }
        },
        lodash: {
          path: bower + '/lodash/dist/lodash.js',
          exports: '_'
        }
      },
      alias: [
        bower + '/angular/angular.js:angular',
        bower + '/angular-route/angular-route.js:angular-route',
        bower + '/lodash/dist/lodash.js:lodash'
      ]
    }))
    .pipe($.concat('vendor.js'))
    // .pipe($.uglify())
    .pipe(gulp.dest('dist/scripts'))
    .pipe($.size());
});

My Scripts task (which should be able to require vendor libraries from the vendor.js bundle above) looks something like this:

// Scripts
gulp.task('scripts', function () {
  return gulp.src('app/scripts/main.js', {read: false})
    .pipe($.browserify({
      debug: true,
      transform: [
        'browserify-jade',
        'debowerify'
      ],
      external: ['angular', 'angular-route', 'lodash'],
      insertGlobals: true,
    })
    .on('prebundle', function(bundle) {
      bundle.external('angular');
      bundle.external('angular-route');
      bundle.external('lodash');
    }))
    // .pipe($.uglify())
    .pipe(gulp.dest('dist/scripts'))
    .pipe($.size())
    .pipe($.connect.reload());
});

When I run the scripts task any external library which should be requirable from vendor.js is still being included inside my main.js bundle. I've tried multiple variations on this (I'm a little unclear what exactly the {read: false} option does. I've also tried playing around with the bundle.external method including the aliased name (ie angular) and the path (app/bower_compontents/angular/angular.js or ./app/bower_compontents/angular/angular.js), but am still getting the vendor libraries bundled into main.js.

Can you please point me in the right direction? I'm able to do something very similar to this in grunt, but am unable to get this working correctly in gulp.

vincentmac avatar Feb 15 '14 01:02 vincentmac

A little follow up on this.

If I set the browserify-shims in my package.json file, browserify will correctly exclude my vendor files from the bundle.

I've updated my package.json file to include settings for browserify, browser, and browserify-shim:

{
  "name": "ngify-test",
  "version": "0.0.0",
  "devDependencies": {
    "gulp": "3.5.2",
    "gulp-load-plugins": "~0.3.0",
    "gulp-browserify": "~0.4.4",
    "gulp-util": "~2.2.14",
    "gulp-autoprefixer": "~0.0.6",
    "gulp-csso": "~0.2.3",
    "gulp-jade": "~0.4.1",
    "gulp-jshint": "~1.4.0",
    "gulp-imagemin": "~0.1.5",
    "gulp-clean": "~0.2.4",
    "gulp-uglify": "~0.2.1",
    "gulp-concat": "~2.1.7",
    "gulp-cache": "~0.1.1",
    "gulp-sass": "~0.7.0",
    "gulp-size": "~0.1.3",
    "gulp-connect": "~0.3.1",
    "browserify": "~3.30.0",
    "debowerify": "~0.5.2",
    "browserify-jade": "~0.1.1",
    "mocha": "~1.17.1",
    "should": "~3.1.2",
    "jshint-stylish": "~0.1.5",
    "browserify-shim": "~3.2.2"
  },
  "engines": {
    "node": ">=0.10.0"
  },
  "browserify": {
    "transform": ["browserify-shim"]
  },
  "browser": {
    "angular": "./app/bower_components/angular/angular.js"
  },
  "browserify-shim": {
    "angular": "global:angular"
  }
}

Now in the scripts task of my gulpfile.js file, I have updated it to look like this:

// Scripts
gulp.task('scripts', function () {
  return gulp.src('app/scripts/main.js', {read: false})
    .pipe($.browserify({
      debug: true,
      transform: [
        'browserify-jade',
        'debowerify'
      ],
      external: ['angular', 'angular-route', 'lodash']
    }))
    // .pipe($.uglify())
    .pipe(gulp.dest('dist/scripts'))
    .pipe($.size())
    .pipe($.connect.reload());
});

This works, however, it feels like something is not working correctly. Am I configuring my gulpfile incorrectly? I don't think having to set the browserify shim in package.json is an ideal solution.

vincentmac avatar Feb 15 '14 22:02 vincentmac

@vincentmac Thanks for sharing!

I don't think having to set the browserify shim in package.json is an ideal solution.

I don't either especially with gulp but that's browserify-shim's design. It only loads config from package.json. It's reasonable because the first priority of browserify transforms is to work with CLI.

This works, however, it feels like something is not working correctly.

Why do you think it's not working correctly?

shuhei avatar Feb 16 '14 04:02 shuhei

Yes, I understand that setting browserify-shim in package.json is the default behavior, however, in grunt-browserify you are able to set your shims directly in that task and they are passed to browserify-shim. Same applies for setting you external requires.

I'll post a sample of what I'm talking about from grunt when I get home. It's possible that I'm not explaining my issue clearly.

vincentmac avatar Feb 16 '14 05:02 vincentmac

@vincentmac thats because they are still on browserify-shim v2..0.10, with browserify-shim v3 the above method is the right way. Even grunt-browserify will be making some core changes in their v2.0 release https://github.com/jmreidy/grunt-browserify/issues/109

deepak1556 avatar Feb 16 '14 05:02 deepak1556

I would absolutely kill for a working example of what @vincentmac was attempting to accomplish here; I've followed guidance in this thread, https://github.com/deepak1556/gulp-browserify/issues/53, and https://github.com/deepak1556/gulp-browserify/issues/48, and none of them are complete or clear enough; still not working.

I refuse to believe that you have to specify src for each file, gulp shim paths for each file, alias paths for each file, AND the relevant package.json properties... Not to mention utilizing the transform in both places. That seems incredibly redundant.

humidair1999 avatar Mar 28 '14 23:03 humidair1999

Will provide one this weekend if still required?

jhchill666 avatar Apr 25 '14 17:04 jhchill666

Personally, I've moved away from using build tools like grunt and gulp with browserify, as they were doing nothing but increasing complexity and making it difficult to achieve what I was hoping to do.

I do think an example would still be useful, though, especially for future users of gulp-browserify.

humidair1999 avatar Apr 25 '14 21:04 humidair1999

I would really like to see an example for this as well, if you have time @jamiehill

TimothyKrell avatar Apr 28 '14 14:04 TimothyKrell

Ok guys, I've finally had time to tidy up my code and push an example. It's not production quality ;) but works out of the box, and will hopefully get you on track

https://github.com/jamiehill/externalise-bower

I think the key here, is to keep-it-simple and minimise complexity. The `package.json' file is where your config should be. No point cluttering up gulp.

As you can see, the only transform I'm using is Deamdify, which effectively 'shims' anything that needs 'shimming'. I experimented alot with Debowerify, but it just didn't give me what I wanted off the shelf.

More-over, it does the opposit - it includes by default all bower component packages in your app/whatever.js. Simply removing it and letting the brilliant Deamdify do it's magic is enough to get going.

jhchill666 avatar Apr 29 '14 14:04 jhchill666

Sweet! This is exactly what I've been looking for. Thanks!

TimothyKrell avatar Apr 29 '14 14:04 TimothyKrell

It uses a packager under the hood, that I wrote, which basically just resolves bower package names, and endpoints. Otherwise is standard Browserify functionality.

Might be worth wrapping Browserify and releasing as a plugin if there was sufficient interest.

jhchill666 avatar Apr 29 '14 14:04 jhchill666

Were you thinking of making a gulp plugin? It seems like it would be nice if it weren't coupled to a specific version of browserify, so users didn't have to wait for the plugin to be updated to use a newer version.

After doing some more research, I am using browserify straight without gulp-browserify.

  • https://github.com/hughsk/vinyl-source-stream (shows how to setup browserify with vinyl streams)
  • gulpjs/gulp#369 (discussion on whether browserify should be a plugin, plus examples)
  • gulpjs/plugins#47

I had also been messing with Debowerify like you, but ran into conflicts with Browserify-Shim. Your packager looks really handy either way, but I think I would like using it more without it wrapping Browserify. Just a thought.

TimothyKrell avatar Apr 29 '14 17:04 TimothyKrell

Hey guys,

I've forked @jamiehgill excellent example and replaced use of gulp-browerify with vanilla browserify + vinyl-source-stream (the recommended way these days)

https://github.com/sogko/externalise-bower

@jamiehill Your packager seems promising, and I would be interested in using it as a Bower util (to get package names/ids, resolves package names to ids, resolve ids to full path etc). But at the current state, there's too much coupling to gulp-browserify. I'm guessing it'd be more useful if its a standalone bower package util of some sorts.

In the forked example, I used your packager externally in gulpfile.js.

Hope this helps anyone else along the way trying to get gulp + browersify + bower + multiple bundles working.

_Update:_ I've replaced the use of the packager with bower-resolve instead. Still lacks a clean way to get all package ids in bower.json,

sogko avatar Aug 11 '14 08:08 sogko

unbelievable how ugly and unclear this still is, this entire issue, brave people @sogko, @jamiehill

iongion avatar Nov 03 '14 15:11 iongion

While this is no longer maintained, I've been having similar problems getting this working properly when using browserify directly and wanting to create a vendor bundle from modules being resolved from node_modules, I used this as an example of how to get this working. I stumbled across this issue while searching for a solution so maybe this'll help someone.

cherrydev avatar Dec 22 '15 10:12 cherrydev