I'm working on a single-page app that uses multiple external dependencies. The app is mostly built with Angular 1. I'm implementing some performance critical parts of the app using React and ES6 syntax. I have rewritten all the app files using ES6 modules syntax, for example:
myComponent.js
let Component = {
bindings: {
binding: '<'
},
controller: controller
};
// @ngInject
function controller() {
var vm = this;
}
export default Component;
index.js
import angular from 'angular';
let module = angular.module('app', []);
import Component from './myComponent';
module.component('myComponent', Component);
export default module;
However, there's still legacy code that depends on Angular, jQuery and other libraries. To bundle the code, I'm using Gulp and Browserify with some transformers. I'm also splitting the code into two bundles: bundle.js and vendor.js. The former one is for the application logic, whereas the latter one consists of several npm modules plus a dozen of custom libraries located in the libs directory. Some of the custom libraries require either angular or jquery.
I'm able to generate both bundles: bundle.js containing all the application code, and the vendor.js containing all the required npm modules and custom libraries. However, the issue is that when I try to run the application on a browser, I get multiple 'Uncaught ReferenceError: jQuery is not defined' and 'Uncaught ReferenceError: angular is not defined' which point to the custom libraries in vendor.js. I guess the reason is that only npm modules are getting browserified and shimmed and then merged with the custom libraries.
All ideas of how to bundle and shim the vendor scripts properly are welcome.
Below are stripped versions of both package.json and Gulpfile.js
package.json
"browserify": {
"transform": [
[
"babelify"
],
[
"browserify-shim"
]
]
},
"browser": {
"jQuery": "./node_modules/jquery/dist/jquery.js",
"angular": "./node_modules/angular/angular.js"
},
"browserify-shim": {
"jQuery": "global:jQuery",
"angular": "global:angular"
}
Gulpfile.js
'use strict';
var gulp = require('gulp');
var babelify = require('babelify'),
browserify = require('browserify'),
buffer = require('vinyl-buffer'),
rename = require('gulp-rename'),
source = require('vinyl-source-stream'),
sourceMaps = require('gulp-sourcemaps'),
watchify = require('watchify'),
concat = require("gulp-concat"),
uglify = require("gulp-uglify"),
ngannotate = require('browserify-ngannotate'),
stream = require('merge-stream');
var globalShim = require('browserify-global-shim').configure({
'jQuery': 'jQuery',
'angular': 'angular'
});
var config = {
js: {
src: './app/app.js',
libs: './app/libs/**/*.js',
outputDir: './dist/',
mapDir: './',
appOutputFile: 'bundle.js',
vendorOutputFile: 'vendor.js'
},
};
var vendors = ['react', 'angular', 'jquery'];
function appBundler(bundler) {
bundler
.bundle()
.pipe(source(config.js.src))
.pipe(buffer())
.pipe(rename(config.js.appOutputFile))
.pipe(sourceMaps.init({
loadMaps: true
}))
.pipe(sourceMaps.write(config.js.mapDir))
.pipe(gulp.dest(config.js.outputDir));
}
gulp.task('build:app', function() {
var bundler = browserify({
entries: config.js.src,
debug: true
})
.external(vendors)
.transform(babelify)
.transform(globalShim)
.transform('browserify-ngannotate')
appBundler(bundler);
})
function vendorBundler(bundler) {
return bundler
.bundle()
.pipe(source('vendor.js'));
}
var customLibsStream = gulp.src(config.js.libs);
gulp.task('build:vendor', function() {
var bundler = browserify({
debug: true
})
.require(vendors)
.transform(globalShim);
stream(vendorBundler(bundler), customLibsStream)
.pipe(buffer())
.pipe(concat('vendor.js'))
.pipe(rename(config.js.vendorOutputFile))
.pipe(sourceMaps.init({
loadMaps: true
}))
.pipe(sourceMaps.write(config.js.mapDir))
.pipe(gulp.dest(config.js.outputDir));
})