From 3c895e08ae330530691beec4cb0794b9c37ffe14 Mon Sep 17 00:00:00 2001 From: Nico Rehwaldt Date: Mon, 2 Apr 2018 23:15:15 +0200 Subject: [PATCH] chore(project): build pre-packaged distros with Rollup * enables tree-shaking * simplifies build --- .eslintrc | 2 +- .npmignore | 3 +- package.json | 15 ++- resources/banner-min.txt | 2 +- resources/banner.txt | 4 +- rollup.config.js | 140 +++++++++++++++++++++++++ tasks/build-distro.js | 31 ++++-- tasks/bundle.js | 217 --------------------------------------- 8 files changed, 173 insertions(+), 241 deletions(-) create mode 100644 rollup.config.js delete mode 100644 tasks/bundle.js diff --git a/.eslintrc b/.eslintrc index a6d452c1..1bcb1f56 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,5 +1,5 @@ { - "extends": "plugin:bpmn-io/es5", + "extends": "plugin:bpmn-io/es6", "env": { "browser": true } diff --git a/.npmignore b/.npmignore index 26eb7fe2..35efd949 100644 --- a/.npmignore +++ b/.npmignore @@ -11,4 +11,5 @@ test/* .eslintrc .travis.yml .wiredeps -CONTRIBUTING.md \ No newline at end of file +CONTRIBUTING.md +rollup.config.js \ No newline at end of file diff --git a/package.json b/package.json index 44f5f766..bddc0731 100644 --- a/package.json +++ b/package.json @@ -37,19 +37,13 @@ "license": "SEE LICENSE IN LICENSE", "devDependencies": { "babel-core": "^6.26.0", - "babel-plugin-add-module-exports": "^0.2.1", "babel-preset-env": "^1.6.1", "babelify": "^8.0.0", - "browser-pack-flat": "^3.0.8", "browserify": "^14.5.0", - "browserify-derequire": "^0.9.1", - "bundle-collapser": "^1.1.1", "chai": "^4.1.2", "chai-match": "^1.1.1", - "common-shakeify": "^0.4.6", "cpx": "^1.5.0", "del": "^3.0.0", - "envify": "^4.1.0", "eslint": "^4.19.0", "eslint-plugin-bpmn-io": "^0.5.2", "execa": "^0.8.0", @@ -71,11 +65,16 @@ "npm-run-all": "^4.1.2", "phantomjs-prebuilt": "^2.1.12", "puppeteer": "^0.13.0", + "rollup": "^0.57.1", + "rollup-plugin-commonjs": "^9.1.0", + "rollup-plugin-json": "^2.3.0", + "rollup-plugin-license": "^0.6.0", + "rollup-plugin-node-resolve": "^3.3.0", + "rollup-plugin-replace": "^2.0.0", + "rollup-plugin-uglify": "^3.0.0", "sinon": "^4.4.6", "sinon-chai": "^2.14.0", "stringify": "^5.2.0", - "uglify-es": "^3.3.10", - "unassertify": "^2.1.0", "watchify": "^3.11.0" }, "dependencies": { diff --git a/resources/banner-min.txt b/resources/banner-min.txt index ba0a831a..9094f598 100644 --- a/resources/banner-min.txt +++ b/resources/banner-min.txt @@ -1 +1 @@ -/*! bpmn-js - {{ variant }} v{{ version }} | Copyright (c) 2014-present, camunda Services GmbH | bpmn.io/license */ \ No newline at end of file +/*! bpmn-js - {{ name }} v{{ version }} | Copyright (c) 2014-present, camunda Services GmbH | bpmn.io/license */ \ No newline at end of file diff --git a/resources/banner.txt b/resources/banner.txt index d118744a..fc982379 100644 --- a/resources/banner.txt +++ b/resources/banner.txt @@ -1,5 +1,5 @@ /*! - * bpmn-js - {{ variant }} v{{ version }} + * bpmn-js - {{ name }} v{{ version }} * * Copyright (c) 2014-present, camunda Services GmbH * @@ -9,4 +9,4 @@ * Source Code: https://github.com/bpmn-io/bpmn-js * * Date: {{ date }} - */ + */ \ No newline at end of file diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 00000000..f6d06ea6 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,140 @@ +import uglify from 'rollup-plugin-uglify'; +import nodeResolve from 'rollup-plugin-node-resolve'; +import commonjs from 'rollup-plugin-commonjs'; +import json from 'rollup-plugin-json'; +import license from 'rollup-plugin-license'; +import replace from 'rollup-plugin-replace'; + +import { + readFileSync +} from 'fs'; + +import pkg from './package.json'; + +const outputDir = 'dist'; + +const distros = [ + { + input: 'Viewer', + output: 'bpmn-viewer' + }, + { + input: 'NavigatedViewer', + output: 'bpmn-navigated-viewer' + }, + { + input: 'Modeler', + output: 'bpmn-modeler' + } +]; + +const configs = distros.reduce(function(configs, distro) { + const { + input, + output + } = distro; + + return [ + ...configs, + { + input: `./lib/${input}.js`, + output: { + name: 'BpmnJS', + file: `${outputDir}/${output}.development.js`, + format: 'umd' + }, + plugins: pgl([ + banner(output) + ]) + }, + { + input: `./lib/${input}.js`, + output: { + name: 'BpmnJS', + file: `${outputDir}/${output}.production.min.js`, + format: 'umd' + }, + plugins: pgl([ + banner(output, true), + uglify({ + output: { + comments: /license|@preserve/ + } + }) + ]) + } + ]; +}, []); + +export default configs; + + +// helpers ////////////////////// + +function banner(bundleName, minified) { + + const bannerName = ( + minified + ? 'banner-min' + : 'banner' + ); + + const bannerTemplate = readFileSync(`${__dirname}/resources/${bannerName}.txt`, 'utf8'); + + const banner = processTemplate(bannerTemplate, { + version: pkg.version, + date: today(), + name: bundleName + }); + + return license({ + banner + }); +} + +function pgl(plugins=[]) { + return [ + replace({ + 'process.env.NODE_ENV': JSON.stringify('production') + }), + nodeResolve({ + module: true, + main: true, + browser: true + }), + commonjs(), + json(), + ...plugins + ]; +} + +function pad(n) { + if (n < 10) { + return '0' + n; + } else { + return n; + } +} + +function today() { + const d = new Date(); + + return [ + d.getFullYear(), + pad(d.getMonth() + 1), + pad(d.getDay()) + ].join('-'); +} + +function processTemplate(str, args) { + return str.replace(/\{\{\s*([^\s]+)\s*\}\}/g, function(_, n) { + + var replacement = args[n]; + + if (!replacement) { + throw new Error('unknown template {{ ' + n + '}}'); + } + + return replacement; + }); +} \ No newline at end of file diff --git a/tasks/build-distro.js b/tasks/build-distro.js index 5c8dc928..8d84b1dc 100644 --- a/tasks/build-distro.js +++ b/tasks/build-distro.js @@ -1,10 +1,9 @@ 'use strict'; -var bundle = require('./bundle'); - var path = require('path'); -var mkdirp = require('mkdirp').sync, +var exec = require('execa').sync, + mkdirp = require('mkdirp').sync, cp = require('cpx').copySync, del = require('del').sync; @@ -29,13 +28,23 @@ cp(resolve('bpmn-font', '/dist/{font,css}/**'), dest + '/assets/bpmn-font'); console.log('copy diagram-js.css to ' + dest); cp(resolve('diagram-js', '/assets/**'), dest + '/assets'); -bundle(dest, { - 'bpmn-viewer': 'lib/Viewer.js', - 'bpmn-navigated-viewer': 'lib/NavigatedViewer.js', - 'bpmn-modeler': 'lib/Modeler.js' -}, function(err) { +console.log('building pre-packaged distributions'); - if (err) { - console.error('bundling failed', err); +var NODE_ENV = process.env.NODE_ENV; + +[ 'production', 'development' ].forEach(function(env) { + + try { + process.env.NODE_ENV = env; + + exec('rollup', [ '-c' ]); + } catch (e) { + console.error('failed to build pre-package distributions', e); + + process.exit(1); } -}); \ No newline at end of file + + process.env.NODE_ENV = NODE_ENV; +}); + +console.log('done.'); \ No newline at end of file diff --git a/tasks/bundle.js b/tasks/bundle.js deleted file mode 100644 index 242720e8..00000000 --- a/tasks/bundle.js +++ /dev/null @@ -1,217 +0,0 @@ -'use strict'; - -var bbl = require('babel-plugin-add-module-exports'); - -var browserify = require('browserify'), - derequire = require('browserify-derequire'), - collapse = require('bundle-collapser/plugin'), - fs = require('fs'), - path = require('path'), - flattenBundle = require('browser-pack-flat/plugin'), - commonShake = require('common-shakeify'), - unassertify = require('unassertify'), - uglify = require('uglify-es'), - envify = require('envify'); - -var pkg = require('../package'); - -var asyncSeries = require('./helpers').asyncSeries; - -var BANNER = fs.readFileSync(__dirname + '/../resources/banner.txt', 'utf8'), - BANNER_MIN = fs.readFileSync(__dirname + '/../resources/banner-min.txt', 'utf8'); - - -module.exports = function bundleAll(dest, 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(dest, variant, entry, done); - }; - }); - - asyncSeries(fns, done); -}; - - - -function Timer() { - this.reset(); -} - -Timer.prototype.done = function(message) { - console.log(message, '[' + (this.now() - this.s) + 'ms]'); - this.reset(); -}; - -Timer.prototype.reset = function() { - this.s = this.now(); -}; - -Timer.prototype.start = function(msg) { - this.reset(); -}; - -Timer.prototype.now = function() { - return new Date().getTime(); -}; - -function processTemplate(str, args) { - return str.replace(/\{\{\s*([^\s]+)\s*\}\}/g, function(_, n) { - - var replacement = args[n]; - - if (!replacement) { - throw new Error('unknown template {{ ' + n + '}}'); - } - - return replacement; - }); -} - -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(dest, variant, entry, done) { - - var src = path.resolve(entry); - - 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('babelify', { - global: true, - babelrc: false, - presets: [ 'env' ], - plugins: [ - bbl - ] - }) - .transform(envify, { - NODE_ENV: 'production' - }) - .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 + '.production.min.js', minified.code, 'utf8'); - - timer.done('wrote ' + targetFileBase + '.production.min.js'); - - done(); - }); - }, - - // development - function(done) { - timer.start('build dev'); - - browserify(browserifyOptions) - .transform('babelify', { - global: true, - babelrc: false, - presets: [ 'env' ], - plugins: [ - bbl - ] - }) - .transform(envify, { - NODE_ENV: 'development' - }) - .plugin(collapse) - .plugin(derequire) - .add(src) - .bundle(function(err, result) { - - timer.done('bundled'); - - if (err) { - return done(err); - } - - var code = banner + result.toString('utf-8'); - - fs.writeFileSync(targetFileBase + '.development.js', code, 'utf8'); - - timer.done('wrote ' + targetFileBase + '.development.js'); - - done(); - }); - } - ]; - - asyncSeries(fns, done); -} \ No newline at end of file