Skip to content

Commit

Permalink
Proper multi-environment build using rollup
Browse files Browse the repository at this point in the history
There are 3 bundles here without any external dependencies
included. These are meant for a further bundling in a
different environments.

**stampit.mjs** - full featured ES6 including modules,
essentially same thing as source file
**stampit.js** - ES6 without modules to be used in NodeJS 6 only
**stampit.es5.js** - ES5 with required polyfills included,
mainly for browserify & webpack 1.x

Lastly there is also **stampit.full.js** (+ minified) which
is also ES5 compatible, but with all dependencies included.
This is drop-in bundle for CDNJS and similar.

Here is also reason why I had to change the source code and instead of

    import isFunction from 'lodash/isFunction';
    import isObject from 'lodash/isObject';

... there is usual `import _ from 'lodash';` now. Unfortunately lodash doesn't support true tree-shaking yet and doing it in current way means that lodash would be included in every bundle, even just those necessary functions. With little help of [babel-plugin-lodash](https://github.com/lodash/babel-plugin-lodash) this is handled more correctly.

I have also replaced use of `assign` from lodash with `Object.assign`.

Closes #208
  • Loading branch information
danielkcz committed May 31, 2016
1 parent eba8ba1 commit 9bd809b
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 34 deletions.
4 changes: 4 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"presets": ["es2015", "stage-1"],
"plugins": ["transform-runtime"]
}
86 changes: 86 additions & 0 deletions build/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/* eslint-disable no-console */

import pkg from '../package.json';

import rollup from 'rollup';
import babel from 'rollup-plugin-babel';
import nodeResolve from 'rollup-plugin-node-resolve';
import commonJs from 'rollup-plugin-commonjs';
import uglify from 'rollup-plugin-uglify';

const moduleName = 'stampit';

function execute() {
return Promise.all([
makeBundle(
{ format: 'es6', ext: '.mjs' }
),
makeBundle(
{ format: 'cjs', ext: '.js' },
),
makeBundle(
{ format: 'cjs', ext: '.es5.js',
babelPresets: ['es2015-rollup'],
babelPlugins: ['transform-runtime']
}
),
makeBundle(
{ format: 'umd', ext: '.full.js',
babelPresets: ['es2015-rollup'],
babelPlugins: ['transform-runtime', 'lodash']
}
),
makeBundle(
{ format: 'umd', ext: '.full.min.js', minify: true,
babelPresets: ['es2015-rollup'],
babelPlugins: ['transform-runtime', 'lodash']
}
)
]);
}

async function makeBundle(config) {
const isUMD = config.format === 'umd';

const inputConfig = {
entry: 'src/stampit.js',
plugins: [
babel({
babelrc: false,
exclude: 'node_modules/**',
presets: ['stage-1'].concat(config.babelPresets || []),
plugins: config.babelPlugins || [],
runtimeHelpers: isUMD,
externalHelpers: isUMD
}),
nodeResolve({ preferBuiltins: true, browser: isUMD }),
commonJs()
]
};

if (!isUMD) {
inputConfig.external = Object.keys(pkg.dependencies);
}

if (config.minify) {
inputConfig.plugins.push(uglify());
}

const outputConfig = {
dest: `dist/${moduleName}${config.ext}`,
format: config.format,
sourceMap: !config.minify,
moduleName: moduleName,
exports: 'named'
};

const bundle = await rollup.rollup(inputConfig);
await bundle.write(outputConfig);
console.log('created', outputConfig.dest);
}

console.log('building...');

execute()
.then(() => console.log('finished'))
.catch((err) => console.log(err.stack || err));
3 changes: 3 additions & 0 deletions build/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
require('babel-polyfill');
require('babel-register');
require('./build.js');
33 changes: 24 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
"name": "Eric Elliott",
"url": "https://ericelliottjs.com"
},
"main": "./dist/stampit.js",
"main": "dist/stampit.js",
"jsnext:main": "dist/stampit.mjs",
"browser": "dist/stampit.es5.js",
"keywords": [
"object",
"prototype",
Expand All @@ -28,16 +30,29 @@
"stamp-specification": "^1.1.1"
},
"devDependencies": {
"babel": "^5.5.8",
"babel-eslint": "^4.1.3",
"browserify": "^11.2.0",
"babel-core": "^6.9.1",
"babel-eslint": "^6.0.4",
"babel-plugin-lodash": "^3.1.4",
"babel-plugin-transform-es2015-modules-commonjs": "^6.8.0",
"babel-plugin-transform-runtime": "^6.9.0",
"babel-polyfill": "^6.9.1",
"babel-preset-es2015": "^6.9.0",
"babel-preset-es2015-rollup": "^1.1.1",
"babel-preset-stage-1": "^6.5.0",
"babel-register": "^6.9.0",
"babel-runtime": "^6.9.2",
"check-compose": "^1.1.3",
"dependency-check": "^2.5.0",
"eslint": "^1.7.1",
"isparta": "^3.0.3",
"nsp": "^2.1.0",
"require-all": "^1.1.0",
"rimraf": "^2.3.4",
"rollup": "^0.26.3",
"rollup-plugin-babel": "^2.4.0",
"rollup-plugin-commonjs": "^2.2.1",
"rollup-plugin-node-resolve": "^1.5.0",
"rollup-plugin-uglify": "^0.3.1",
"tape": "^4.2.2",
"uglifyjs": "^2.4.10",
"watch": "^0.16.0"
Expand All @@ -46,12 +61,12 @@
"cov": "npm run cov:clean && npm run cov:generate",
"cov:clean": "rimraf ./coverage/",
"cov:generate": "babel-node node_modules/.bin/isparta cover --report text --report html test/index.js",
"prepublish": "npm run check",
"test": "tape -r babel/register test/index.js",
"prepublish": "npm run check && npm run build",
"test": "tape -r babel-register test/index.js",
"clean": "rimraf dist/* && mkdir dist || true",
"uglify": "uglifyjs dist/stampit.js -m -c warnings=false -o dist/stampit.min.js",
"lint": "eslint src && eslint test",
"build": "npm run clean && babel src --out-dir dist && npm run uglify",
"build": "npm run clean && node build",
"deps": "npm run deps:missing && npm run deps:extra",
"deps:missing": "dependency-check package.json",
"deps:extra": "dependency-check package.json --extra --no-dev --ignore",
Expand All @@ -66,8 +81,8 @@
{
"basePath": "/dist/",
"files": [
"stampit.js",
"stampit.min.js"
"stampit.full.js",
"stampit.full.min.js"
]
}
]
Expand Down
54 changes: 29 additions & 25 deletions src/stampit.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
import assign from 'lodash/assign';
import isObject from 'lodash/isObject';
import isFunction from 'lodash/isFunction';
import _ from 'lodash';
import compose, {merge} from 'stamp-specification';

export const isComposable = isObject;
export const isStamp = obj => isFunction(obj) && isFunction(obj.compose);
export const isComposable = _.isObject;
export const isStamp = obj => _.isFunction(obj) && _.isFunction(obj.compose);

function extractFunctions(...args) {
const functions = args.reduce((result, arg) => {
if (isFunction(arg)) { return result.concat(arg); }
if (_.isFunction(arg)) { return result.concat(arg); }
if (Array.isArray(arg)) { return result.concat(extractFunctions(...arg) || []); }
if (isObject(arg)) { return result.concat(extractFunctions(...Object.values(arg)) || []); }
if (_.isObject(arg)) { return result.concat(extractFunctions(...Object.values(arg)) || []); }
return result;
}, []);
return functions.length === 0 ? undefined : functions;
}

const rawUtilities = {
methods(...args) {
return (this.compose || compose).call(this, {methods: assign({}, ...args)});
return (this.compose || compose).call(this, {methods: Object.assign({}, ...args)});
},
properties(...args) {
return (this.compose || compose).call(this, {properties: assign({}, ...args)});
return (this.compose || compose).call(this, {properties: Object.assign({}, ...args)});
},
initializers(...args) {
return (this.compose || compose).call(this, {initializers: extractFunctions(...args)});
Expand All @@ -30,13 +28,13 @@ const rawUtilities = {
return (this.compose || compose).call(this, {deepProperties: merge({}, ...args)});
},
staticProperties(...args) {
return (this.compose || compose).call(this, {staticProperties: assign({}, ...args)});
return (this.compose || compose).call(this, {staticProperties: Object.assign({}, ...args)});
},
staticDeepProperties(...args) {
return (this.compose || compose).call(this, {staticDeepProperties: merge({}, ...args)});
},
configuration(...args) {
return (this.compose || compose).call(this, {configuration: assign({}, ...args)});
return (this.compose || compose).call(this, {configuration: Object.assign({}, ...args)});
},
deepConfiguration(...args) {
return (this.compose || compose).call(this, {deepConfiguration: merge({}, ...args)});
Expand Down Expand Up @@ -72,18 +70,24 @@ function standardiseDescriptor({
deepConfiguration,
deepConf
} = {}) {
const p = isObject(props) || isObject(refs) || isObject(properties) ?
assign({}, props, refs, properties) : undefined;
let dp = isObject(deepProps) ? merge({}, deepProps) : undefined;
dp = isObject(deepProperties) ? merge(dp, deepProperties) : dp;
const sp = isObject(statics) || isObject(staticProperties) ?
assign({}, statics, staticProperties) : undefined;
let dsp = isObject(deepStatics) ? merge({}, deepStatics) : undefined;
dsp = isObject(staticDeepProperties) ? merge(dsp, staticDeepProperties) : dsp;
const c = isObject(conf) || isObject(configuration) ?
assign({}, conf, configuration) : undefined;
let dc = isObject(deepConf) ? merge({}, deepConf) : undefined;
dc = isObject(deepConfiguration) ? merge(dc, deepConfiguration) : dc;
const p = _.isObject(props) || _.isObject(refs) || _.isObject(properties) ?
Object.assign({}, props, refs, properties) : undefined;

let dp = _.isObject(deepProps) ? merge({}, deepProps) : undefined;
dp = _.isObject(deepProperties) ? merge(dp, deepProperties) : dp;

const sp = _.isObject(statics) || _.isObject(staticProperties) ?
Object.assign({}, statics, staticProperties) : undefined;

let dsp = _.isObject(deepStatics) ? merge({}, deepStatics) : undefined;
dsp = _.isObject(staticDeepProperties) ? merge(dsp, staticDeepProperties) : dsp;

const c = _.isObject(conf) || _.isObject(configuration) ?
Object.assign({}, conf, configuration) : undefined;

let dc = _.isObject(deepConf) ? merge({}, deepConf) : undefined;
dc = _.isObject(deepConfiguration) ? merge(dc, deepConfiguration) : dc;

return {
methods: methods,
properties: p,
Expand All @@ -99,7 +103,7 @@ function standardiseDescriptor({
}

const baseStampit = compose({
staticProperties: assign({
staticProperties: Object.assign({
refs: rawUtilities.properties,
props: rawUtilities.properties,
init: rawUtilities.initializers,
Expand All @@ -124,7 +128,7 @@ function stampit(...args) {
return baseStampit.compose(...args);
}

export default assign(stampit,
export default Object.assign(stampit,
{
isStamp,
isComposable,
Expand Down

0 comments on commit 9bd809b

Please sign in to comment.