const fs = require('fs');
const path = require('path');
const rollup = require('rollup');
const argParser = require('mri');
const commonjs = require('rollup-plugin-commonjs');
const progress = require('rollup-plugin-progress');
const filesize = require('rollup-plugin-filesize');
const resolve = require('rollup-plugin-node-resolve');
const terser = require('rollup-plugin-terser');
const babel = require('rollup-plugin-babel');
const json = require('rollup-plugin-json');
const builtinModules = require('builtin-modules');
function prettierPlugin() {
return {
name: 'rollup-plugin-prettier-bundle',
generateBundle(output) {},
};
}
async function createConfig(input, options) {
const opts = Object.assign({}, options);
const extMap = {
es: '.mjs',
cjs: '.js',
};
const destMap = {
es: 'module',
cjs: 'main',
};
const cwd = process.cwd();
const outDir = (x) => opts.outDir || path.join(cwd, 'dist', destMap[x]);
const outFile = (x) => path.join(outDir(x), `index${extMap[x]}`);
const join = (...x) => path.join(cwd, ...x);
const pkg = require(join('package.json'));
const exts = arrayify(opts.extensions);
const extensions =
exts.length > 0 ? exts : ['.js', '.jsx', '.mjs', '.ts', '.tsx'];
const possibleInputs = [
input,
join('index.js'),
join('src', 'index.js'),
join('src', 'index.mjs'),
join('src', 'index.ts'),
];
// first existing, for now
const [inputFile] = possibleInputs.filter((x) => fs.existsSync(x));
const license = `/** Released under the ${opts.license ||
pkg.license} License. See LICENSE file. */`;
const outMap = {
cjs: {
exports: 'named',
banner: license,
file: outFile('cjs'),
format: 'cjs',
preferConst: true,
// don't break oldschool/classic/normal node.js
outro: 'module.exports = exports.default || exports;',
},
es: {
exports: 'named',
banner: license,
file: outFile('es'),
format: 'es',
preferConst: true,
},
};
outMap.esm = outMap.es;
let formats = arrayify(opts.format)
.reduce((acc, x) => acc.concat(x.indexOf(',') > -1 ? x.split(',') : x), [])
.filter(Boolean);
let output = null;
if (formats.length === 0) {
formats = ['cjs', 'es'];
}
if (formats.length === 1) {
output = outMap[formats[0]];
} else {
output = formats.map((x) => outMap[x]);
}
return {
input: inputFile,
output,
external: builtinModules,
inlineDynamicImports: true,
experimentalTopLevelAwait: true,
plugins: [
progress(),
resolve({
preferBuiltins: true,
module: true,
jsnext: true,
main: true,
}),
json({ preferConst: true }),
babel({
exclude: 'node_modules/**',
externalHelpers: true,
extensions,
}),
commonjs({
extensions,
}),
opts.minify && terser.terser(),
filesize({
showBrotliSize: true,
showGzippedSize: true,
showMinifiedSize: true,
}),
],
};
}
const argv = argParser(process.argv.slice(2), {
alias: {
i: 'input',
d: ['out-dir', 'outdir', 'outDir'],
f: 'format',
m: 'minify',
x: ['ext', 'extensions'],
l: ['license'],
},
});
let ROLLUP_CACHE = null;
createConfig(argv.input || argv._[0], argv)
.then(async (cfg) => {
const bundle = await rollup.rollup(
Object.assign({}, cfg, { cache: ROLLUP_CACHE }),
);
ROLLUP_CACHE = bundle.cache;
arrayify(cfg.output).map(async (outputOptions) => {
await bundle.write(outputOptions);
});
})
.catch(console.error);
function arrayify(val) {
if (!val) return [];
if (Array.isArray(val)) return val;
return [val];
}
node rolldown.js [src/index.js]
run with
by defaults tries
index.js,src/index.js,src/index.mjsandsrc/index.ts, works with TypeScript out of the box and generates CJS and ESM bundles with bundled deps.