title: How do I properly separate my app.js and vendor.js bundles using Browserify?
body: <p>My goals are to include the following in my HTML file and have them all work properly:</p>
  <p>index.html:</p>
  <pre><code>&lt;script type=&quot;text/javascript&quot; src=&quot;./vendor.js&quot;&gt;&lt;/script&gt;
  &lt;script type=&quot;text/javascript&quot; src=&quot;./app.js&quot;&gt;&lt;/script&gt;
  $(document).ready(function() {
      // jQuery should be available as `window.$`
      $(&quot;.myclass&quot;).doSomethingWithJquery(); 
  }
  &lt;div class=&quot;row&quot;&gt;
      &lt;h1 class=&quot;col-md-3 col-md-offset-3&quot;&gt;
          I should be able to use bootstrap, including bootstrap's javascript libraries, in my templates
      &lt;/h1&gt;
  &lt;/div&gt;
  &lt;!-- I should be able to use app.js, with its various require('module') 
  statements and attach rendered HTML to the DOM (I'm using React) --&gt;
  &lt;div id=&quot;attach-app-js&quot;&gt;&lt;/div&gt;
  </code></pre>
  <p>Therefore:</p>
  <ol>
  <li>jQuery should be available as a global <code>$</code> variable.</li>
  <li>Bootstrap's javascript functions should also work, as they're part of vendor.js</li>
  <li>My <code>app.js</code> should also work and not re-declare variables like <code>$</code> that is already declared under global scope via <code>vendor.js</code>.</li>
  </ol>
  <p>See the files below. My current solution errors where I have <code>$(&quot;.myclass&quot;).doSomethingWithJquery();</code> When my internet is off, I get the error:</p>
  <blockquote>
  <p>Uncaught ReferenceError: $ is not defined</p>
  </blockquote>
  <p>...which makes me think that (maybe) snackbarjs or another module is leaking jQuery to global scope.</p>
  <p>Then, when I change the line in <code>vendor.js</code> to: <code>var $ = jQuery = require('jquery');</code> I get the error:</p>
  <blockquote>
  <p>Uncaught ReferenceError: $ is not defined</p>
  </blockquote>
  <p>but now it's getting called on the line <code>$(document).ready(function.....</code></p>
  <p>Third, if I comment out <code>vendor.js</code> entirely, I get both errors:</p>
  <blockquote>
  <p>Uncaught ReferenceError: $ is not defined</p>
  <p>Uncaught ReferenceError: jQuery is not defined</p>
  </blockquote>
  <p>How can I get this frontend setup to correctly shim variables when necessary in the global scope, and not if it's not necessary??</p>
  <p>gulpfile.js:</p>
  <pre><code>.task('vendor', ['clean'], function() {
      var b = browserify(package.paths.vendor);
      var packages = getBowerPackageIds();
  
      packages.forEach(function (id) {
    
        var resolvedPath = bowerResolve.fastReadSync(id);
    
        b.require(resolvedPath, {
    
          // exposes the package id, so that we can require() from our code.
          // for eg:
          // require('./vendor/angular/angular.js', {expose: 'angular'}) enables require('angular');
          // for more information: https://github.com/substack/node-browserify#brequirefile-opts
          expose: id
    
        });
      });
      return b
      .bundle()
      .pipe(source(package.dest.vendor))
      .pipe(gulp.dest(package.dest.dist));
    })
  
  .task('js', ['clean', 'install'], function() {
      var b = browserify(package.paths.app);
      // mark vendor libraries defined in bower.json as an external library,
      // so that it does not get bundled with app.js.
      // instead, we will load vendor libraries from vendor.js bundle
      getBowerPackageIds().forEach(function (lib) {
        b.external(lib);
      });
    
      var w = watchify(b, watchify.args);
      var file = package.dest.app,
          dest = package.dest.dist;
    
      w = w
        .transform(reactify)
        .transform(browserifyShim);
    
      w.on('update', rebundle);
    
      function rebundle() {
          return w.
              bundle()
              .on('error', errorHandler)
              .pipe(source(file))
              .pipe(gulp.dest(dest))
              .pipe(shell([
                'python manage.py collectstatic --noinput'
              ], {
                  cwd: '../'
              }))
              // TODO: Do I need this?
              .pipe(browserSync.reload({stream: true}));
      }
      return rebundle();
    })
  /**
     * Running livereload server
     */
    .task('server', ['clean', 'install', 'vendor', 'js', 'less'], function() {
      browserSync({
        proxy: &quot;localhost:8000&quot;
      });
    })
  /**
     * Compiling resources and serving application
     */
    .task('serve', ['install', 'backup', 'clean', 'lint', 'less', 'vendor', 'js', 'server'], function() {
      return gulp.watch([
        package.paths.js,
        package.paths.app,
        package.paths.html,
        package.paths.less,
        package.paths.python
      ], [
       'lint', 'less', browserSync.reload
      ]);
    })
  </code></pre>
  <p>vendor.js:</p>
  <pre><code>$ = jQuery = require('jquery');
  require('bootstrap');
  require('snackbarjs');
  </code></pre>
  <p>package.json (<code>browserify-shim</code> config):</p>
  <pre><code>  &quot;browserify-shim&quot;: {
      &quot;jquery&quot;: &quot;$&quot;,
      &quot;bootstrap&quot;: {
        &quot;depends&quot;: [
          &quot;jquery:jQuery&quot;
        ],  
        &quot;exports&quot;: &quot;bootstrap&quot;
      },  
      &quot;jquery-cookie&quot;: {
        &quot;depends&quot;: [
          &quot;jquery:jQuery&quot;
        ]   
      },  
      &quot;eonasdan-bootstrap-datetimepicker&quot;: {
        &quot;depends&quot;: [
          &quot;jquery:jQuery&quot;,
          &quot;moment:moment&quot;,
          &quot;bootstrap:bootstrap&quot;
        ],  
        &quot;exports&quot;: &quot;$.fn.datetimepicker&quot;
      },  
      &quot;image-picker&quot;: {
        &quot;depends&quot;: [
          &quot;jquery:jQuery&quot;
        ],  
        &quot;exports&quot;: &quot;$.fn.imagepicker&quot;
      },  
      &quot;raven-js&quot;: {
        &quot;depends&quot;: [
          &quot;jquery:jQuery&quot;
        ],  
        &quot;exports&quot;: &quot;raven-js&quot;
      },  
      &quot;parsleyjs&quot;: {
        &quot;depends&quot;: [
          &quot;jquery:jQuery&quot;
        ],  
        &quot;exports&quot;: &quot;parsleyjs&quot;
      }   
    },  
    &quot;browser&quot;: {
      &quot;jquery&quot;: &quot;./bower_components/jquery/dist/jquery.js&quot;,
      &quot;jquery-cookie&quot;: &quot;./bower_components/jquery-cookie/jquery.cookie.js&quot;,
      &quot;image-picker&quot;: &quot;./bower_components/image-picker/image-picker/image-picker.js&quot;,
      &quot;eonasdan-bootstrap-datetimepicker&quot;: &quot;./bower_components/eonasdan-bootstrap-datetimepicker/src/js/bootstrap-datetimepicker.js&quot;,
      &quot;moment&quot;: &quot;./bower_components/moment/moment.js&quot;,
      &quot;bootstrap&quot;: &quot;./bower_components/bootstrap/dist/js/bootstrap.js&quot;,
      &quot;raven-js&quot;: &quot;./bower_components/raven-js/dist/raven.js&quot;,
      &quot;parsleyjs&quot;: &quot;./bower_components/parsleyjs/dist/parsley.js&quot;
    },
  </code></pre>