Commit 6e9ebd66 authored by Stefan Cameron's avatar Stefan Cameron

Update all dependencies to latest and move from ESM to CJS builds

parent a16c8aaa
Pipeline #81410698 passed with stages
in 3 minutes and 18 seconds
......@@ -13,6 +13,10 @@
"node": true // generally, code runs in Node.js
},
"globals": {
"DEV_ENV": "readonly" // {boolean}
},
//
// Rules: pull-in ESLint's recommended set, then tweak as necessary
// @see http://eslint.org/docs/rules/<rule-name>
......@@ -42,6 +46,7 @@
"no-new": "off", // OFF to allow `myFunction(new RegExp('foo'))`, for example
"no-new-func": "error", // disallow `new Function(...)` to declare a new function
"no-new-wrappers": "error", // disallow `new Number/String/Boolean()`
"no-prototype-builtins": "off", // OFF to allow {}.hasOwnProperty('foo')
"no-throw-literal": "error",
"no-warning-comments": ["error", {
"terms": [
......
......@@ -9,7 +9,14 @@ Date format is YYYY-MM-DD.
## Unreleased
n/a
### Breaking
- The ESM build output is replaced with a CJS build output as this is the most compatible with popular Webpack and Rollup build systems.
- The main package export is now the CJS build output.
- The CJS build output is found in `./dist/cjs/...`
- The UMD build output is now found in `./dist/umd/...`
### Changed
- Dependency updates: All to latest.
## 1.2.0 - 2019-05-19
......
......@@ -16,31 +16,35 @@ npm install rtvjs
The package's `/dist` directory contains two types of builds:
* `rtv.umd.js/rtv.umd.min.js`: UMD loader, full and minified.
* `rtv.esm.js/rtv.esm.min.js`: ES6 Module, full and minified.
* `./cjs/rtv[.dev].js`: CJS loader, full (.dev) and minified. This is the main package export.
* `./umd/rtv[.dev].js`: UMD loader, full (.dev) and minified.
## CJS
The CJS build can be used like this:
```javascript
const rtv = require('rtvjs');
```
Note that the main package export points to `./dist/cjs/index.js` which will automatically select the right build to include based on the value of `process.env.NODE_ENV`: If it's `"production"`, it will include the __minified__ version; otherwise, it will include __full__ version.
Use the [Webpack Define Plugin](https://webpack.js.org/plugins/define-plugin/) or the [Rollup Replace Plugin](https://www.npmjs.com/package/rollup-plugin-replace), for example, to configure this in your build.
## UMD
The UMD build can be used like this:
```javascript
// as a global, when loaded via a <script> tag in HTML
window.rtv;
// as a CommonJS module (e.g. Node.js)
const rtv = require('rtvjs');
// as an AMD module (e.g. RequireJS)
define(['rtvjs'], function(rtv) {
});
```
## ESM
The ES6 module build can be used like this:
```javascript
import rtv from 'rtvjs';
// as a global, when loaded via a <script> tag in HTML
window.rtv;
```
# Documentation
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -6,9 +6,7 @@
"node": ">=10.11.0",
"npm": ">=6.4.1"
},
"main": "dist/rtv.umd.min.js",
"module": "dist/rtv.esm.min.js",
"jsnext:main": "dist/rtv.esm.min.js",
"main": "dist/cjs/index.js",
"pre-commit": [
"precommit:msg",
"lint",
......@@ -23,7 +21,7 @@
"clean": "npm run clean:lib && npm run clean:internals",
"start": "npm run build:lib && npm run node",
"build:internals": "npm run clean:internals && rollup -c tools/rollup.internals.js",
"build:lib": "npm run clean:lib && BABEL_ENV=build rollup -c",
"build:lib": "npm run clean:lib && node ./tools/build/build.js",
"build": "npm run build:lib",
"docs": "jsdoc2md -f \"src/**/*.js\" -f \"src/**/*.jsdoc\" --heading-depth 1 > API.md",
"lint": "eslint ./*.js \"src/**/*.js\" \"test/**/*.js\" \"tools/**/*.js\"",
......@@ -79,27 +77,28 @@
],
"dependencies": {},
"devDependencies": {
"@babel/core": "^7.4.4",
"@babel/preset-env": "^7.4.4",
"@babel/register": "^7.4.4",
"jsdoc-to-markdown": "^5.0.0",
"lodash": "^4.17.11",
"@babel/core": "^7.6.0",
"@babel/preset-env": "^7.6.0",
"@babel/register": "^7.6.0",
"jsdoc-to-markdown": "^5.0.1",
"lodash": "^4.17.15",
"pre-commit": "^1.2.2",
"rollup": "^1.12.3",
"rollup-plugin-babel": "^4.3.2",
"rollup-plugin-commonjs": "^10.0.0",
"rollup": "^1.21.2",
"rollup-plugin-babel": "^4.3.3",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-json": "^4.0.0",
"rollup-plugin-node-resolve": "^5.0.0",
"rollup-plugin-terser": "^4.0.4",
"rollup-plugin-uglify": "^6.0.2"
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-replace": "^2.2.0",
"rollup-plugin-terser": "^5.1.1",
"rollup-plugin-uglify": "^6.0.3"
},
"optionalDependencies": {
"babel-plugin-istanbul": "^5.1.4",
"babel-plugin-istanbul": "^5.2.0",
"chai": "^4.2.0",
"eslint": "^5.16.0",
"eslint": "^6.3.0",
"live-server": "^1.2.1",
"mocha": "^6.1.4",
"mocha": "^6.2.0",
"nyc": "^14.1.1",
"sinon": "^7.3.2"
"sinon": "^7.4.2"
}
}
////// Rollup Configuration
const jsonPlugin = require('rollup-plugin-json');
const resolvePlugin = require('rollup-plugin-node-resolve');
const cjsPlugin = require('rollup-plugin-commonjs');
const babelPlugin = require('rollup-plugin-babel');
const {uglify: uglifyEs5Plugin} = require('rollup-plugin-uglify');
const {terser: uglifyEs6Plugin} = require('rollup-plugin-terser');
const pkg = require('./package.json');
const LIB_NAME = 'rtv';
const banner = `/*!
* ${pkg.name} ${pkg.version}
* @license MIT, https://gitlab.com/stefcameron/rtvjs/blob/master/LICENSE.md
* Parts of Lodash used internally: https://github.com/lodash/lodash/
*/`;
// base config with NO outputs
const getBaseConfig = function() {
return {
input: 'src/rtv.js',
output: [],
plugins: [
jsonPlugin(),
resolvePlugin(),
cjsPlugin({
include: 'node_modules/**'
}),
// NOTE: As of Babel 7, this plugin now ensures that Babel helpers are not
// repeated, and are inserted at the top of the generated bundle:
// "This rollup plugin automatically deduplicates those helpers, keeping
// only one copy of each one used in the output bundle. Rollup will combine
// the helpers in a single block at the top of your bundle."
// @see https://github.com/rollup/rollup-plugin-babel#helpers
babelPlugin({
exclude: 'node_modules/**'
})
],
watch: {
include: 'src/**',
exclude: ['node_modules/**', 'dist/**', 'dist_tools/**']
}
};
};
// uglify plugin (ES5 and ES6) configuration
const getUglifyConfig = function() {
return {
output: {
// comments: /^\/\*!/
comments(node, comment) {
const text = comment.value;
const type = comment.type;
if (type === 'comment2') {
// multiline comment: keep if it starts with a bang or contains
// some common preservation keywords
return text.indexOf('!') === 0 ||
(/@preserve|@license|@cc_on/i).test(text);
}
}
}
};
};
// UMD (ES5) build config
const getUmdConfig = function(minified) {
const config = getBaseConfig();
config.output.push({
file: `dist/${LIB_NAME}.umd.${minified ? 'min.js' : 'js'}`,
format: 'umd',
name: LIB_NAME,
noConflict: true,
sourcemap: true,
banner
});
if (minified) {
const uglifyConfig = getUglifyConfig();
config.plugins.push(uglifyEs5Plugin(uglifyConfig));
}
return config;
};
// ESM (ES5 but using ES6 module syntax) build config
const getEsmConfig = function(minified) {
const config = getBaseConfig();
config.output.push({
file: `dist/${LIB_NAME}.esm.${minified ? 'min.js' : 'js'}`,
format: 'es',
sourcemap: true,
banner
});
if (minified) {
const uglifyConfig = getUglifyConfig();
config.plugins.push(uglifyEs6Plugin(uglifyConfig));
}
return config;
};
const builds = require('./tools/build/rollup-builds');
module.exports = [
getUmdConfig(),
getUmdConfig(true), // minified
getEsmConfig(),
getEsmConfig(true) // minified
builds.getUmdConfig(),
builds.getUmdConfig(true), // minified
builds.getCjsConfig(),
builds.getCjsConfig(true) // minified
];
////// tools ESLint Configuration
{
"extends": ["../.eslintrc"],
"parserOptions": {
"ecmaVersion": 2018, // in particular, supports object spread
"sourceType": "module"
},
"rules": {
"no-console": "off"
}
}
//
// NODE SCRIPT: Builds the library.
//
const fs = require('fs');
const path = require('path');
const {spawn} = require('child_process');
const {
RU_FORMAT_CJS,
OUTPUT_DEV,
DIR_DIST_CJS
} = require('../build/rollup-utils');
// get the build configurations used for this component/package
const configFilePath = path.resolve('./rollup.config.js');
const builds = require(configFilePath);
// load the package.json (use path relative to location from which this script
// will be run, which is the repo root)
const pkgFilePath = path.resolve('./package.json');
const pkg = require(pkgFilePath);
// default process close handler
const closeHandler = function(code) {
process.exit(code);
};
// add 'data' and 'close' handlers to a given process
const addProcessHandlers = function(cmd, onClose = closeHandler) {
cmd.stdout.on('data', function(data) {
console.log(data.toString());
});
cmd.stderr.on('data', function(data) {
console.error(data.toString());
});
cmd.on('close', onClose);
};
/**
* Generates the index.js file the package.json points to for CJS builds.
*
* While both paths are optional, at least one must be specified.
*
* @param {string} [devPath] Relative path, from package.json, to the dev build.
* @param {string} [prodPath} Relative path, from package.json, to the prod build.
* @returns {string} Contents to write to the index.js file.
* @throws {Error} If neither path is given.
*/
const generateIndex = function(devPath, prodPath) {
const makeLocal = function(filePath) {
return filePath.replace(DIR_DIST_CJS, '.');
};
if ((devPath && !prodPath) || (!devPath && prodPath)) {
// only one path specified
return `'use strict';
module.exports = require('${makeLocal(devPath || prodPath)}');
`;
} else if (devPath && prodPath) {
return `'use strict';
if (process.env.NODE_ENV === 'production') {
module.exports = require('${makeLocal(prodPath)}');
} else {
module.exports = require('${makeLocal(devPath)}');
}
`;
}
throw new Error(`At least one path must be specified (error from ${configFilePath})!`);
};
if (pkg.main !== `${DIR_DIST_CJS}/index.js`) {
throw new Error(`Main property in ${pkgFilePath} must be set to ${DIR_DIST_CJS}/index.js`);
}
// map of output format -> {dev: string, prod: string} (object with paths
// to dev and prod build output files)
const outputs = {};
// look at all build configurations and find the ones that are CJS, making sure
// they're properly configured to work with the index.js file we're going to
// generate after the build is done
builds.forEach(function(build) {
build.output.forEach(function(out) {
outputs[out.format] = outputs[out.format] || {};
const type = (new RegExp(`\\${OUTPUT_DEV}\\.js$`)).test(out.file) ? 'dev' : 'prod';
if (outputs[out.format][type]) {
throw new Error(`Found more than one ${out.format}/${type} build outputs in ${configFilePath}`);
}
if (out.format === RU_FORMAT_CJS && out.file.indexOf(DIR_DIST_CJS) !== 0) {
throw new Error(
`File output path for ${out.format}/${type} build is not from ${DIR_DIST_CJS} in ${configFilePath}: "${out.file}"`);
}
outputs[out.format][type] = out.file;
});
});
if (!outputs.cjs) {
throw new Error(`Missing ${RU_FORMAT_CJS.toUpperCase()} build output(s) in ${configFilePath}`);
}
// run rollup with the rollup.config.js file in the repo root
const cmd = spawn('rollup', ['-c'], {
env: {
BABEL_ENV: 'build',
...process.env // let item's script override the above default if it wants to
}
});
addProcessHandlers(cmd, function(code) {
if (code !== 0) {
process.exit(code);
}
// generate the index.js file for the CJS build(s)
const indexJs = generateIndex(outputs.cjs.dev, outputs.cjs.prod);
const indexPath = `./${DIR_DIST_CJS}/index.js`;
fs.writeFileSync(indexPath, indexJs); // overwrite if exists
console.log(`Generated ${path.resolve(indexPath)}`);
process.exit(0);
});
////// Rollup Build Configurations
const jsonPlugin = require('rollup-plugin-json');
const resolvePlugin = require('rollup-plugin-node-resolve');
const cjsPlugin = require('rollup-plugin-commonjs');
const babelPlugin = require('rollup-plugin-babel');
const {uglify: uglifyEs5Plugin} = require('rollup-plugin-uglify');
const replacePlugin = require('rollup-plugin-replace');
const {
RU_FORMAT_CJS,
RU_FORMAT_UMD,
OUTPUT_DEV,
DIR_SRC,
DIR_DIST,
DIR_DIST_CJS,
DIR_DIST_UMD
} = require('./rollup-utils');
const pkg = require('../../package.json');
const LIB_NAME = 'rtv';
const banner = `/*!
* ${pkg.name} ${pkg.version}
* @license MIT, https://gitlab.com/stefcameron/rtvjs/blob/master/LICENSE.md
* Parts of Lodash used internally: https://github.com/lodash/lodash/
*/`;
// base config with NO outputs, relative to the repo root
// - isDev: set to true for a development (i.e. non-minified) build
const getBaseConfig = function(options = {
isDev: false
}) {
const {isDev} = options;
const peerDeps = Object.keys(pkg.peerDependencies || {});
return {
input: `${DIR_SRC}/rtv.js`,
output: [],
preserveModules: false, // NOTE: must be false to 'roll-up' all code into one file
external: [...peerDeps],
plugins: [
jsonPlugin(),
resolvePlugin(),
cjsPlugin({
include: 'node_modules/**'
}),
// NOTE: As of Babel 7, this plugin now ensures that Babel helpers are not
// repeated, and are inserted at the top of the generated bundle:
// "This rollup plugin automatically de-duplicates those helpers, keeping
// only one copy of each one used in the output bundle. Rollup will combine
// the helpers in a single block at the top of your bundle."
// @see https://github.com/rollup/rollup-plugin-babel#helpers
babelPlugin({
exclude: 'node_modules/**'
}),
replacePlugin({
DEV_ENV: JSON.stringify(isDev)
})
],
watch: {
include: `${DIR_SRC}/**`,
exclude: ['node_modules/**', `${DIR_DIST}/**`, 'dist_tools/**']
}
};
};
// uglify plugin (ES5 and ES6) configuration
const getUglifyPluginConfig = function() {
return {
output: {
// comments: /^\/\*!/
comments(node, comment) {
const text = comment.value;
const type = comment.type;
if (type === 'comment2') {
// multiline comment: keep if it starts with a bang or contains
// some common preservation keywords
return text.indexOf('!') === 0 ||
(/@preserve|@license|@cc_on/i).test(text);
}
}
}
};
};
// UMD (ES5) build config
const getUmdConfig = function(minified = false) {
const config = getBaseConfig({isDev: !minified});
config.output.push({
file: `${DIR_DIST_UMD}/${LIB_NAME}${minified ? '.js' : `${OUTPUT_DEV}.js`}`,
format: RU_FORMAT_UMD,
name: LIB_NAME,
noConflict: true,
sourcemap: true,
banner
});
if (minified) {
const uglifyConfig = getUglifyPluginConfig();
config.plugins.push(uglifyEs5Plugin(uglifyConfig));
}
return config;
};
// CJS (ES5) build config
const getCjsConfig = function(minified = false) {
const config = getBaseConfig({isDev: !minified});
config.output.push({
file: `${DIR_DIST_CJS}/${LIB_NAME}${minified ? '.js' : `${OUTPUT_DEV}.js`}`,
format: RU_FORMAT_CJS,
sourcemap: true,
banner
});
if (minified) {
const uglifyConfig = getUglifyPluginConfig();
config.plugins.push(uglifyEs5Plugin(uglifyConfig));
}
return config;
};
module.exports = {
getCjsConfig,
getUmdConfig
};
//// Utilities for Rollup Builds
// {string} Rollup CJS output format
const RU_FORMAT_CJS = 'cjs';
// {string} Rollup UMD output format
const RU_FORMAT_UMD = 'umd';
// {string} Sub-extension used in development (i.e. non-minified) builds
const OUTPUT_DEV = '.dev';
// {string} input directory relative path, no trailing slash
const DIR_SRC = 'src';
// {string} output directory relative path, no trailing slash
const DIR_DIST = 'dist';
// {string} CJS builds output directory relative path, no trailing slash
const DIR_DIST_CJS = `${DIR_DIST}/${RU_FORMAT_CJS}`;
// {string} UMD builds output directory relative path, no trailing slash
const DIR_DIST_UMD = `${DIR_DIST}/${RU_FORMAT_UMD}`;
module.exports = {
RU_FORMAT_CJS,
RU_FORMAT_UMD,
OUTPUT_DEV,
DIR_SRC,
DIR_DIST,
DIR_DIST_CJS,
DIR_DIST_UMD
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment