UNPKG

@redsift/rollup-bundler

Version:
230 lines (199 loc) 6.76 kB
const path = require('path'); const fs = require('fs'); const merge = require('lodash.merge'); const babel = require('rollup-plugin-babel'); const babelrcBuilder = require('babelrc-rollup').default; const kleur = require('kleur'); const commonjs = require('rollup-plugin-commonjs'); const resolve = require('rollup-plugin-node-resolve'); const progress = require('rollup-plugin-progress'); const cleanup = require('rollup-plugin-cleanup'); const json = require('rollup-plugin-json'); const minify = require('rollup-plugin-babel-minify'); const filesize = require('rollup-plugin-filesize'); const visualizer = require('rollup-plugin-visualizer'); const builtins = require('rollup-plugin-node-builtins'); const zeroConfig = require('../rollup.config.zero'); const cwd = process.cwd(); const _suffixPath = (p, sffx) => { const parts = path.parse(p); parts.name = `${parts.name}.${sffx}`; delete parts.base; return path.format(parts); }; const globalOptions = { output: { exports: 'named', }, }; const babelrcPath = path.join(cwd, '.babelrc'); const babelrcExists = fs.existsSync(babelrcPath); const babelrc = babelrcExists ? babelrcBuilder({ path: babelrcPath, // disable `addModuleOptions` as it passes { modules: false } to ALL presets, // which causes an error e.g. with the `flow` preset, as it does not know the // options and errors out. Make sure to pass `{ modules: false }` to the `env` // plugin to allow tree-shaking. addModuleOptions: false, addExternalHelpersPlugin: false, }) : { presets: [ [ // NOTE: Resolving 'env' in Babel 6 does not always work, depending on the setup. This will be fixed // in Babel 7 (see https://github.com/babel/babel-preset-env/issues/186#issuecomment-297776368). Meanwhile // we load the preset from the calling project as a workaround: // path.join(cwd, 'node_modules', '@babel/preset-env'), '@babel/preset-env', { modules: false, // "targets": { // "browsers": ["last 1 versions"] // } }, ], ], // NOTE: we use babel-plugin-transform-runtime to prevent clashes if you include multiple bundles which // use 'babel-polyfill' in a consuming app/lib. // NOTE: After a lot of frustration and googling this combination of `transform-runtime` and `external-helpers` // is working. Using `transform-runtime` to do the helpers part did not work (resulting in `Error: 'default' i // not exported by node_modules/babel-runtime/helpers/typeof.js`). Therefore helpers are transformed via the // `external-helpers` plugin. plugins: [ '@babel/plugin-proposal-class-properties', '@babel/plugin-transform-runtime', ], exclude: 'node_modules/**', // Therefore runtimeHelpers has to be set: (see https://github.com/rollup/rollup-plugin-babel#helpers) runtimeHelpers: true, babelrc: false, }; if (babelrcExists) { console.log(kleur.gray(`\nUsing ${babelrcPath}`)); } module.exports = function(baseOptions, showConfig = true) { if (!baseOptions) { baseOptions = zeroConfig; } if (!baseOptions.input) { baseOptions.input = zeroConfig.input; } if (!baseOptions.output) { baseOptions.output = zeroConfig.output; } if (!baseOptions.input) { console.log(kleur.red('\n\nConfiguration error:')); console.log(kleur.red('--------------------')); console.log( kleur.red( "\n > You must specify an 'input' field if your entry point is different from './src/index.js'!\n\n" ) ); return; } baseOptions = Object.assign( { output: { file: null, name: null } }, baseOptions ); if (!baseOptions.output.file) { console.log(kleur.red('\n\nConfiguration error:')); console.log(kleur.red('--------------------')); console.log( kleur.red("\n > You have to specify an 'output.file' field!\n\n") ); return; } const { pluginConfigs = {}, output: outputOptions, input: inputOptions, ...restOptions } = baseOptions; const { json: jsonCfg, babel: babelCfg, resolve: resolveCfg, commonjs: commonjsCfg, } = pluginConfigs; let babelConfig = babelCfg ? babelCfg : babelrc; if ( (babelConfig && (babelConfig.plugins.includes('@babel/plugin-transform-runtime') || babelConfig.plugins.includes('@babel/plugin-transform-runtime'))) || !!babelConfig.plugins.find( p => Array.isArray(p) && p.length && (p[0] === '@babel/plugin-transform-runtime' || p[0] === '@babel/plugin-transform-runtime') ) ) { babelConfig = Object.assign(babelConfig, { runtimeHelpers: true }); } if (showConfig) { console.log( kleur.gray( '\nBundler configuration:', JSON.stringify(baseOptions, null, 4) ) ); console.log(kleur.gray('babelrc:', JSON.stringify(babelConfig, null, 4))); } const defaultPlugins = [ // TODO: fix and re-enable // progress(), json(jsonCfg ? jsonCfg : { indent: ' ' }), builtins(), babel(babelConfig), resolve(resolveCfg ? resolveCfg : { jsnext: true, preferBuiltins: false }), commonjs(commonjsCfg ? commonjsCfg : {}), cleanup(), filesize(), ]; // NOTE: delete non-standard field, otherwise rollup will complain: delete baseOptions.pluginConfigs; const configs = []; const outputs = [ { format: 'umd', file: _suffixPath(outputOptions.file, 'umd') }, // NOTE: legacy UMD name for CDN published versions. Codepen.io examples are using // this filename convention when loading the bundle from the CDN: // { format: 'umd', file: _suffixPath(outputOptions.file, 'umd-es2015') }, { format: 'es', file: _suffixPath(outputOptions.file, 'esm') }, ]; outputs.forEach(output => { const options = baseOptions.plugins ? merge( {}, baseOptions, globalOptions, { plugins: baseOptions.plugins }, restOptions, { output, } ) : merge( {}, baseOptions, globalOptions, { plugins: defaultPlugins }, { output, }, restOptions ); configs.push(options); if (options.output.format === 'es') { options.plugins.push(visualizer()); return; } const minOptions = merge({}, options, { output: { file: _suffixPath(output.file, 'min') }, }); minOptions.plugins = minOptions.plugins.slice(0); minOptions.plugins.push(minify()); configs.push(minOptions); }); return configs; };