From e3bf356461419e4007df7b5b075d53345ec7b41d Mon Sep 17 00:00:00 2001 From: Nico Rehwaldt Date: Fri, 5 Jan 2018 16:09:39 +0100 Subject: [PATCH] chore(project): drop grunt + bundle assets to dist directory * replace grunt with npm scripts * copy static assets to dist directory * build and copy library variants to dist directory Related to #725 --- .eslintignore | 1 + .npmignore | 4 +- Gruntfile.js | 109 -------------- package.json | 25 ++-- resources/banner-min.txt | 1 + resources/banner.txt | 12 ++ tasks/banner-min.txt | 1 - tasks/banner.txt | 12 -- tasks/build-distro.js | 14 ++ tasks/bundle.js | 303 +++++++++++++++++++++----------------- tasks/copy-assets.js | 12 ++ tasks/helpers.js | 23 +++ test/config/karma.unit.js | 8 +- 13 files changed, 247 insertions(+), 278 deletions(-) create mode 100644 .eslintignore delete mode 100644 Gruntfile.js create mode 100644 resources/banner-min.txt create mode 100644 resources/banner.txt delete mode 100644 tasks/banner-min.txt delete mode 100644 tasks/banner.txt create mode 100644 tasks/build-distro.js create mode 100644 tasks/copy-assets.js create mode 100644 tasks/helpers.js diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..53c37a16 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +dist \ No newline at end of file diff --git a/.npmignore b/.npmignore index 6d4d9c71..f00b9ba7 100644 --- a/.npmignore +++ b/.npmignore @@ -7,8 +7,8 @@ test/fixtures test/integration test/spec test/TestHelper.js +.eslintignore .eslintrc .travis.yml .wiredeps -CONTRIBUTING.md -Gruntfile.js \ No newline at end of file +CONTRIBUTING.md \ No newline at end of file diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index 4aae048c..00000000 --- a/Gruntfile.js +++ /dev/null @@ -1,109 +0,0 @@ -'use strict'; - -module.exports = function(grunt) { - - require('load-grunt-tasks')(grunt); - require('time-grunt')(grunt); - - // project configuration - grunt.initConfig({ - - pkg: grunt.file.readJSON('package.json'), - - config: { - sources: 'lib', - tests: 'test', - dist: process.env.BOWER_DIST || '../bower-bpmn-js/dist' - }, - - eslint: { - check: { - src: [ - '{lib,test}/**/*.js' - ] - }, - fix: { - src: [ - '{lib,test}/**/*.js' - ], - options: { - fix: true - } - } - }, - - karma: { - options: { - configFile: '<%= config.tests %>/config/karma.unit.js' - }, - single: { - singleRun: true, - autoWatch: false - }, - unit: { }, - translations: { - singleRun: true, - autoWatch: false, - - reporters: [ 'dots', 'translation-reporter' ], - - plugins: [ - 'karma-*', - require('./test/config/translation-reporter') - ], - - envPreprocessor: [ - 'TRANSLATIONS' - ] - } - }, - - bundle: { - viewer: { - name: 'bpmn-viewer', - src: '<%= config.sources %>/Viewer.js', - dest: '<%= config.dist %>' - }, - navigated_viewer: { - name: 'bpmn-navigated-viewer', - src: '<%= config.sources %>/NavigatedViewer.js', - dest: '<%= config.dist %>' - }, - modeler: { - name: 'bpmn-modeler', - src: '<%= config.sources %>/Modeler.js', - dest: '<%= config.dist %>' - } - }, - - copy: { - bpmn_js: { - files: [ - { expand: true, cwd: 'assets', src: [ '**' ], dest: '<%= config.dist %>/assets' } - ] - }, - - diagram_js: { - files: [ - { expand: true, cwd: 'node_modules/diagram-js/assets', src: [ '**' ], dest: '<%= config.dist %>/assets' } - ] - } - } - }); - - grunt.loadTasks('tasks'); - - - // tasks - grunt.registerTask('extract-translations', [ 'karma:translations' ]); - - grunt.registerTask('test', [ 'karma:single' ]); - - grunt.registerTask('lint', [ 'eslint:check' ]); - - grunt.registerTask('auto-test', [ 'karma:unit' ]); - - grunt.registerTask('build', [ 'bundle', 'copy' ]); - - grunt.registerTask('default', [ 'lint', 'test', 'build' ]); -}; diff --git a/package.json b/package.json index 3ee0973e..25d69c38 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,14 @@ "version": "0.26.6", "description": "A bpmn 2.0 toolkit and web modeler", "scripts": { - "all": "grunt", - "dev": "grunt auto-test", - "distro": "grunt build", - "test": "grunt test", - "lint": "grunt lint" + "all": "run-s lint test distro", + "lint": "eslint .", + "dev": "npm test -- --auto-watch --no-single-run", + "test": "karma start test/config/karma.unit.js", + "clean": "del dist/*", + "build-distro": "node tasks/build-distro.js", + "copy-assets": "node tasks/copy-assets.js", + "distro": "run-s clean copy-assets build-distro" }, "repository": { "type": "git", @@ -40,14 +43,11 @@ "bundle-collapser": "^1.1.1", "chai": "^4.1.2", "chai-match": "^1.1.1", - "common-shakeify": "^0.4.4", + "common-shakeify": "^0.4.5", + "cpx": "^1.5.0", + "del-cli": "^1.1.0", "eslint": "^4.14.0", "eslint-plugin-mocha": "^4.9.0", - "grunt": "^0.4.4", - "grunt-cli": "^0.1.13", - "grunt-contrib-copy": "^0.7.0", - "grunt-eslint": "^19.0.0", - "grunt-karma": "^2.0.0", "jsondiffpatch": "^0.1.26", "karma": "^1.7.0", "karma-browserify": "^5.1.1", @@ -60,16 +60,15 @@ "karma-safari-launcher": "^1.0.0", "karma-sinon-chai": "^1.3.2", "karma-spec-reporter": "0.0.31", - "load-grunt-tasks": "^0.3.0", "mocha": "^4.0.1", "mocha-test-container-support": "0.2.0", + "npm-run-all": "^4.1.2", "phantomjs-prebuilt": "^2.1.12", "puppeteer": "^0.13.0", "sinon": "^4.0.1", "sinon-chai": "^2.14.0", "source-map-concat": "^1.0.0", "stringify": "^5.2.0", - "time-grunt": "^0.3.2", "uglify-es": "^3.2.2", "unassertify": "^2.1.0", "watchify": "^3.7.0" diff --git a/resources/banner-min.txt b/resources/banner-min.txt new file mode 100644 index 00000000..0ebb1416 --- /dev/null +++ b/resources/banner-min.txt @@ -0,0 +1 @@ +/*! bpmn-js - {{ variant }} v{{ version }} | (c) 2014, 2017 camunda Services GmbH | bpmn.io/license */ \ No newline at end of file diff --git a/resources/banner.txt b/resources/banner.txt new file mode 100644 index 00000000..573a9455 --- /dev/null +++ b/resources/banner.txt @@ -0,0 +1,12 @@ +/*! + * bpmn-js - {{ variant }} v{{ version }} + + * Copyright 2014 - 2017 camunda Services GmbH and contributors + * + * Released under the bpmn.io license + * http://bpmn.io/license + * + * Source Code: https://github.com/bpmn-io/bpmn-js + * + * Date: {{ date }} + */ \ No newline at end of file diff --git a/tasks/banner-min.txt b/tasks/banner-min.txt deleted file mode 100644 index 80ef4c97..00000000 --- a/tasks/banner-min.txt +++ /dev/null @@ -1 +0,0 @@ -/*! <%= pkg.name %> - <%= config.variant %> v<%= pkg.version %> | (c) 2014, 2017 camunda Services GmbH | bpmn.io/license */ \ No newline at end of file diff --git a/tasks/banner.txt b/tasks/banner.txt deleted file mode 100644 index 40e4125e..00000000 --- a/tasks/banner.txt +++ /dev/null @@ -1,12 +0,0 @@ -/*! - * <%= pkg.name %> - <%= config.variant %> v<%= pkg.version %> - - * Copyright 2014 - 2017 camunda Services GmbH and other contributors - * - * Released under the bpmn.io license - * http://bpmn.io/license - * - * Source Code: https://github.com/bpmn-io/bpmn-js - * - * Date: <%= grunt.template.today("yyyy-mm-dd") %> - */ \ No newline at end of file diff --git a/tasks/build-distro.js b/tasks/build-distro.js new file mode 100644 index 00000000..2c383cb9 --- /dev/null +++ b/tasks/build-distro.js @@ -0,0 +1,14 @@ +'use strict'; + +var bundle = require('./bundle'); + +bundle({ + 'bpmn-viewer': 'lib/Viewer.js', + 'bpmn-navigated-viewer': 'lib/NavigatedViewer.js', + 'bpmn-modeler': 'lib/Modeler.js' +}, function(err) { + + if (err) { + console.error('bundling failed', err); + } +}); \ No newline at end of file diff --git a/tasks/bundle.js b/tasks/bundle.js index d1933daf..b7093b9b 100644 --- a/tasks/bundle.js +++ b/tasks/bundle.js @@ -11,14 +11,34 @@ var browserify = require('browserify'), unassertify = require('unassertify'), uglify = require('uglify-es'); -var assign = Object.assign; +var pkg = require('../package'); -var BANNER = fs.readFileSync(__dirname + '/banner.txt', 'utf8'), - BANNER_MIN = fs.readFileSync(__dirname + '/banner-min.txt', 'utf8'); +var asyncSeries = require('./helpers').asyncSeries; + +var BANNER = fs.readFileSync(__dirname + '/../resources/banner.txt', 'utf8'), + BANNER_MIN = fs.readFileSync(__dirname + '/../resources/banner-min.txt', 'utf8'); var SOURCE_MAP_HEADER = '//# sourceMappingURL=data:application/json;charset=utf-8;base64,'; +module.exports = function bundleAll(targets, done) { + + var fns = Object.keys(targets).map(function(k) { + + var variant = k; + var entry = targets[k]; + + return function(done) { + console.log('\nbundle ' + variant); + + bundle(variant, entry, done); + }; + }); + + asyncSeries(fns, done); +}; + + function extractSourceMap(content) { var idx = content.indexOf(SOURCE_MAP_HEADER), @@ -64,8 +84,6 @@ Timer.prototype.reset = function() { }; Timer.prototype.start = function(msg) { - console.log('start: ' + msg); - this.reset(); }; @@ -73,142 +91,151 @@ Timer.prototype.now = function() { return new Date().getTime(); }; +function processTemplate(str, args) { + return str.replace(/\{\{\s*([^\s]+)\s*\}\}/g, function(_, n) { -module.exports = function(grunt) { + var replacement = args[n]; - grunt.registerMultiTask('bundle', function(target) { - - var data = this.data, - variant = data.name, - dest = data.dest, - src = path.resolve(data.src); - - grunt.config.set('config.variant', variant); - - var done = this.async(); - - var browserifyOptions = { - standalone: 'BpmnJS', - builtins: false, - insertGlobalVars: { - process: function() { - return 'undefined'; - }, - Buffer: function() { - return 'undefined'; - } - } - }; - - var targetFileBase = path.join(dest, variant); - - var banner = grunt.template.process(BANNER, grunt.config.get()), - bannerMin = grunt.template.process(BANNER_MIN, grunt.config.get()); - - var timer = new Timer(); - - var fns = [ - - // production - function(done) { - - timer.start('build prod'); - - browserify(browserifyOptions) - .transform(unassertify) - .plugin(commonShake) - .plugin(flattenBundle) - .plugin(collapse) - .plugin(derequire) - .add(src) - .bundle(function(err, result) { - - timer.done('bundled'); - - if (err) { - return done(err); - } - - var str = result.toString('utf-8'); - - var minified = uglify.minify(str, { - compress: true, - mangle: true, - output: { - preamble: bannerMin - } - }); - - timer.done('minified'); - - grunt.file.write(targetFileBase + '.min.js', minified.code, 'utf8'); - - timer.done('saved'); - - done(); - }); - }, - - // development - function(done) { - - timer.start('build dev'); - - browserify(assign({ debug: true }, browserifyOptions)) - .plugin(collapse) - .plugin(derequire) - .add(src) - .bundle(function(err, result) { - - timer.done('bundled'); - - if (err) { - return done(err); - } - - try { - var bundled = extractSourceMap(result.toString('utf8')); - - timer.done('extracted source map'); - - var bannerBundled = - concat([ bundled ]) - .prepend(banner + '\n') - .add('//# sourceMappingURL=./' + variant + '.js.map') - .toStringWithSourceMap(); - - timer.done('added banner'); - - grunt.file.write(targetFileBase + '.js', bannerBundled.code, 'utf8'); - grunt.file.write(targetFileBase + '.js.map', bannerBundled.map, 'utf8'); - - timer.done('all saved'); - } catch (e) { - return done(e); - } - - done(); - }); - } - ]; - - function next(err) { - - if (err) { - return done(err); - } - - var fn = fns.shift(); - - if (!fn) { - return done(); - } else { - fn(next); - } + if (!replacement) { + throw new Error('unknown template {{ ' + n + '}}'); } - next(); - + return replacement; }); +} -}; \ No newline at end of file +function pad(n) { + if (n < 10) { + return '0' + n; + } else { + return n; + } +} + +function today() { + var d = new Date(); + + return [ + d.getFullYear(), + pad(d.getMonth() + 1), + pad(d.getDay()) + ].join('-'); +} + +function bundle(variant, entry, done) { + + var src = path.resolve(entry); + var dest = 'dist'; + + var config = { + variant: variant, + version: pkg.version, + date: today() + }; + + var browserifyOptions = { + standalone: 'BpmnJS', + builtins: false, + insertGlobalVars: { + process: function() { + return 'undefined'; + }, + Buffer: function() { + return 'undefined'; + } + } + }; + + var targetFileBase = path.join(dest, variant); + + var banner = processTemplate(BANNER, config), + bannerMin = processTemplate(BANNER_MIN, config); + + var timer = new Timer(); + + var fns = [ + + // production + function(done) { + + timer.start('build prod'); + + browserify(browserifyOptions) + .transform(unassertify) + .plugin(commonShake) + .plugin(flattenBundle) + .plugin(collapse) + .plugin(derequire) + .add(src) + .bundle(function(err, result) { + + timer.done('bundled'); + + if (err) { + return done(err); + } + + var str = result.toString('utf-8'); + + var minified = uglify.minify(str, { + compress: true, + mangle: true, + output: { + preamble: bannerMin + } + }); + + timer.done('minified'); + + fs.writeFileSync(targetFileBase + '.min.js', minified.code, 'utf8'); + + timer.done('saved'); + + done(); + }); + }, + + // development + function(done) { + timer.start('build dev'); + + browserify(Object.assign({ debug: true }, browserifyOptions)) + .plugin(collapse) + .plugin(derequire) + .add(src) + .bundle(function(err, result) { + + timer.done('bundled'); + + if (err) { + return done(err); + } + + try { + var bundled = extractSourceMap(result.toString('utf8')); + + timer.done('extracted source map'); + + var bannerBundled = + concat([ bundled ]) + .prepend(banner + '\n') + .add('//# sourceMappingURL=./' + variant + '.js.map') + .toStringWithSourceMap(); + + timer.done('added banner'); + + fs.writeFileSync(targetFileBase + '.js', bannerBundled.code, 'utf8'); + fs.writeFileSync(targetFileBase + '.js.map', bannerBundled.map, 'utf8'); + + timer.done('all saved'); + } catch (e) { + return done(e); + } + + done(); + }); + } + ]; + + asyncSeries(fns, done); +} \ No newline at end of file diff --git a/tasks/copy-assets.js b/tasks/copy-assets.js new file mode 100644 index 00000000..869e985e --- /dev/null +++ b/tasks/copy-assets.js @@ -0,0 +1,12 @@ +'use strict'; + +var path = require('path'); + +var copySync = require('cpx').copySync; + +var diagramAssets = path.join(path.dirname(require.resolve('diagram-js')), '/assets') + '/**'; + +console.log(diagramAssets); + +copySync('assets/**', 'dist/'); +copySync(diagramAssets, 'dist/'); \ No newline at end of file diff --git a/tasks/helpers.js b/tasks/helpers.js new file mode 100644 index 00000000..f9bcd1d0 --- /dev/null +++ b/tasks/helpers.js @@ -0,0 +1,23 @@ +'use strict'; + +module.exports.asyncSeries = function(fns, done) { + + var idx = 0; + + function next(err) { + + if (err) { + return done(err); + } + + var fn = fns[idx++]; + + if (!fn) { + return done(); + } else { + fn(next); + } + } + + next(); +}; \ No newline at end of file diff --git a/test/config/karma.unit.js b/test/config/karma.unit.js index a8a38b47..4792a076 100644 --- a/test/config/karma.unit.js +++ b/test/config/karma.unit.js @@ -64,14 +64,16 @@ module.exports = function(karma) { browserNoActivityTimeout: 30000, - singleRun: false, - autoWatch: true, + singleRun: true, + autoWatch: false, // browserify configuration browserify: { debug: true, paths: [ absoluteBasePath ], - transform: [ [ 'stringify', { global: true, extensions: [ '.bpmn', '.xml', '.css' ] } ] ] + transform: [ + [ 'stringify', { global: true, extensions: [ '.bpmn', '.xml', '.css' ] } ] + ] } }); };