JointJS requires Backbone, Lodash, and JQuery. Backbone requires underscore. Lodash is a replacement for underscore. So in order to use Backbone with Lodash for JointJS you need to configure SystemJS to load Lodash when asked for Underscore by Backbone. This is pretty much the same as their documentation on RequireJS at http://resources.jointjs.com/tutorial/requirejs
I have this set up with npm to manage the JavaScript dependencies, Gulp to copy the files around and SystemJS to load them.
npm install --save jointjs
npm install jquery@3.1.1 --save
npm install lodash@3.10.1 --save
npm install backbone@1.3.3 --save
npm install -D @types/jquery
npm install -D @types/jointjs
npm install -D @types/lodash
npm install -D @types/backbone
gulpfile.js
/* eslint-env node, es6 */
/* eslint no-console: off */
////////////////////////////////
// Setup //
////////////////////////////////
// Plugins
var gulp = require('gulp'),
pjson = require('./package.json'),
gutil = require('gulp-util'),
sass = require('gulp-sass'),
autoprefixer = require('gulp-autoprefixer'),
cssnano = require('gulp-cssnano'),
rename = require('gulp-rename'),
del = require('del'),
plumber = require('gulp-plumber'),
pixrem = require('gulp-pixrem'),
uglify = require('gulp-uglify'),
imagemin = require('gulp-imagemin'),
exec = require('child_process').exec,
runSequence = require('run-sequence'),
browserSync = require('browser-sync').create(),
reload = browserSync.reload,
ts = require('gulp-typescript'),
sourcemaps = require('gulp-sourcemaps'),
merge = require('merge-stream');
// Relative paths function
var pathsConfig = function(appName) {
this.app = './' + (appName || pjson.name);
this.static = this.app + '/static';
this.frontend = this.app + '/frontend';
return {
app: this.app,
templates: this.app + '/templates',
static: this.static,
css: this.static + '/css',
sass: this.static + '/sass',
fonts: this.static + '/fonts',
images: this.static + '/images',
js: this.static + '/js',
frontend: this.frontend,
build: this.frontend + '/build',
node: './node_modules',
};
};
var paths = pathsConfig();
var tsProject = ts.createProject('tsconfig.json');
var moduleDirs = {
'jointjs/dist/*.{js,css,png}': 'libs/jointjs',
'lodash/*.js': 'libs/lodash',
};
var modules = {
'core-js/client/shim.min.js': 'libs/core.js',
'zone.js/dist/zone.js': 'libs/zone.js',
'systemjs/dist/system.js': 'libs/system.js',
'@angular/core/bundles/core.umd.js': 'libs/@angular/core/bundles/core.umd.js',
'@angular/common/bundles/common.umd.js': 'libs/@angular/common/bundles/common.umd.js',
'@angular/compiler/bundles/compiler.umd.js': 'libs/@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser/bundles/platform-browser.umd.js': 'libs/@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js': 'libs/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http/bundles/http.umd.js': 'libs/@angular/http/bundles/http.umd.js',
'@angular/http/bundles/http-testing.umd.js': 'libs/@angular/http/bundles/http-testing.umd.js',
'@angular/router/bundles/router.umd.js': 'libs/@angular/router/bundles/router.umd.js',
'@angular/forms/bundles/forms.umd.js': 'libs/@angular/forms/bundles/forms.umd.js',
'jquery/dist/jquery.min.js': 'libs/jquery/dist/jquery.min.js',
'vex-js/dist/css/vex.css': 'css/vex.css',
'vex-js/dist/css/vex-theme-plain.css': 'css/vex-theme-plain.css',
'backbone/backbone-min.js': 'libs/backbone-min.js'
};
////////////////////////////////
// Tasks //
////////////////////////////////
gulp.task('clean', function() {
return del.sync(paths.build);
});
gulp.task('collectDirs', ['clean'], function() {
var streams = [];
Object.keys(moduleDirs).forEach(function(path) {
streams.push(
gulp.src(path, {'cwd': paths.node})
.pipe(gulp.dest(moduleDirs[path], {'cwd': paths.build}))
);
});
return merge(streams);
});
gulp.task('collectModules', ['clean'], function() {
var streams = [];
Object.keys(modules).forEach(function(path) {
streams.push(
gulp.src(path, {'cwd': paths.node})
.pipe(rename(modules[path]))
.pipe(gulp.dest(paths.build))
);
});
return merge(streams);
});
gulp.task('collectAppResources', ['clean'], function() {
return gulp.src(['**/*.html', '**/*.css'], {'cwd': paths.frontend})
.pipe(gulp.dest(paths.build + '/app'))
});
// Collects libs from node_module
gulp.task('collect', ['collectDirs', 'collectModules', 'collectAppResources']);
// Compile TypeScript Files
gulp.task('app', ['collect'], function() {
return gulp.src(paths.frontend + '/**/*.ts')
.pipe(sourcemaps.init())
.pipe(tsProject())
.pipe(sourcemaps.write())
.pipe(gulp.dest(paths.build + '/app'));
});
// Javascript minification
gulp.task('scripts', function() {
return gulp.src(paths.js + '/project.js')
.pipe(plumber()) // Checks for errors
.pipe(uglify()) // Minifies the js
.pipe(rename({suffix: '.min'}))
.pipe(gulp.dest(paths.js));
});
// Image compression
gulp.task('imgCompression', function() {
return gulp.src(paths.images + '/*')
.pipe(imagemin()) // Compresses PNG, JPEG, GIF and SVG images
.pipe(gulp.dest(paths.images));
});
// Task to run ./manage.py/collectstatic
gulp.task('collectStatic', ['app'], function() {
exec('python manage.py collectstatic --noinput', function(err, stdout, stderr) {
console.log('Collecting static files');
console.log(stdout);
console.log(stderr);
});
});
// Default task
gulp.task('default', function() {
return runSequence(['app']);
});
systemjs configuration:
(function () {
System.config({
// map tells the System loader where to look for things
map: {
'app': '/static/app',
// angular bundles
'@angular/core': '/static/libs/@angular/core/bundles/core.umd.js',
'@angular/common': '/static/libs/@angular/common/bundles/common.umd.js',
'@angular/compiler': '/static/libs/@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': '/static/libs/@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': '/static/libs/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': '/static/libs/@angular/http/bundles/http.umd.js',
'@angular/http/testing': '/static/libs/@angular/http/bundles/http-testing.umd.js',
'@angular/router': '/static/libs/@angular/router/bundles/router.umd.js',
'@angular/forms': '/static/libs/@angular/forms/bundles/forms.umd.js',
// other
'rxjs': '/static/libs/rxjs',
'jquery': '/static/libs/jquery/dist/jquery.min.js',
'lodash': '/static/libs/lodash/index.js',
'underscore': '/static/libs/lodash/index.js',
'*': {
'underscore': '/static/libs/lodash/index.js',
},
'backbone': '/static/libs/backbone-min.js',
'jointjs': '/static/libs/jointjs/joint.js',
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.js',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
},
},
meta: {
'jointjs': {
exports: 'joint',
deps: ['jquery', 'lodash', 'underscore', 'backbone']
},
'backbone': {
deps: ['underscore'],
},
}
});
})();