171 lines
5.8 KiB
JavaScript
171 lines
5.8 KiB
JavaScript
// @cerxes
|
|
import { host, Host } from "@cerxes/host";
|
|
|
|
// Rollup and plugins
|
|
import babel from 'rollup-plugin-babel';
|
|
import resolve from 'rollup-plugin-node-resolve';
|
|
import { terser } from 'rollup-plugin-terser';
|
|
|
|
// Proc args (this is weird to be here, but it is the same for build/watch, and should be kept in sync as much as possible
|
|
import process from "process";
|
|
import * as rollup from "rollup";
|
|
import { logBundle } from "./log-bundle";
|
|
let args = process.argv.slice(2);
|
|
const runArgSeperator = args.indexOf('--');
|
|
export let buildTargets = ['lib-es', 'lib-cjs', 'dist-es', 'dist-es-min', 'dist-cjs', 'dist-cjs-min'];
|
|
if (runArgSeperator >= 0) {
|
|
buildTargets = args.slice(runArgSeperator + 1);
|
|
args = args.slice(0, runArgSeperator);
|
|
}
|
|
|
|
export class CsxConfig {
|
|
constructor({
|
|
src,
|
|
dist,
|
|
root,
|
|
opts
|
|
} = {}) {
|
|
const { watch } = opts || {};
|
|
|
|
this.root = root ? host.from(root) : host.from('.');// (This host.from('.') would not've been necessary if @cerxes/host did not have a bug on this one)
|
|
this.src = this.root.from(src || 'src');
|
|
this.dist = this.root.from(dist || 'dist');
|
|
this.lib = this.root.from(dist || 'lib');
|
|
}
|
|
|
|
/** @type {Host} */
|
|
src;
|
|
/**
|
|
* Directory to use for dist output (single bundle)
|
|
* @type {Host} */
|
|
dist;
|
|
/**
|
|
* Directory to use for library output (transpiled, file by file)
|
|
* @type {Host} */
|
|
lib;
|
|
|
|
/** @type {string} */
|
|
sourceGlob = "**/*.@(*.js|js)";
|
|
|
|
/**
|
|
* Get rollup-config to compile a source file
|
|
* @param {string} file
|
|
* @param {string} out
|
|
* @param {object} [opts]
|
|
* @param {boolean} [opts.es] - Export in es6 format (or cjs when false)
|
|
* @param {boolean} [opts.single] - Compile single file (e.g. don't follow imports)
|
|
* @param {boolean} [opts.sourcemap] - Include sourcemaps
|
|
* @param {boolean} [opts.minified] - Minify the output (e.g. Terser-plugin)
|
|
* @returns {{output: {file: string, sourcemap: boolean, plugins: Array<Object>, format: string}, input: string, plugins: ...*[]}}
|
|
*/
|
|
srcCfg = (file, out = undefined, opts) => {
|
|
let inputFile = this.src.resolve(file);
|
|
let outputFile = this.dist.resolve(out || file);
|
|
return ({
|
|
// Compile the actual app
|
|
input: inputFile,
|
|
output: {
|
|
file: outputFile,
|
|
format: opts?.es? 'es' : 'cjs', // NodeJS
|
|
sourcemap: opts?.sourcemap ?? true,
|
|
},
|
|
external: (id, parentId, isResolved) => {
|
|
if (!id || id[0] === '\0') return false;// Special cases
|
|
else {
|
|
let split = (id || "").split('/');
|
|
let first = id[0] === '@' ? split.slice(0, 2).join('/') : split[0];
|
|
let absId = first === '..' || first === '.' ? this.src.resolve(parentId, id) : id;
|
|
if (absId) {
|
|
if(absId.indexOf(this.src.workingDirectory) >= 0 && opts?.single) return true; // Own source-file => external when single mode enabled
|
|
}
|
|
// Any other unresolved identifier(which should be resolved further)
|
|
return false; // The light, inline them
|
|
}
|
|
},
|
|
treeshake: !opts?.single,
|
|
plugins: [
|
|
// babel
|
|
babel({
|
|
babelrc: true,
|
|
}),
|
|
// NodeJS-style resolving (Its a shame this is not a Rollup-default, we need this for index.js files to work!)
|
|
resolve({
|
|
extensions: ['.mjs', '.js', '.jsx', '.json'],
|
|
preferBuiltins: true, mainFields: ['browser']
|
|
}),
|
|
opts?.minified ? terser() : null
|
|
].filter(t=>t)
|
|
})
|
|
};
|
|
|
|
/**
|
|
* @param {string} sources
|
|
* @returns {TargetConfig[]}
|
|
*/
|
|
configureTargets = (sources)=>{
|
|
return buildTargets.map(target=>{
|
|
let {lib,dist,root} = this;
|
|
let [type, format, minified] = target.split("-");
|
|
let inputs = type==='lib'? sources : ['index.js'];
|
|
let srcOpts = {
|
|
es: format==='es',
|
|
single: type==='lib',
|
|
sourcemap: true,// Just always there for now
|
|
minified: !!minified
|
|
};
|
|
let outDir = type==='lib'? lib : dist;
|
|
|
|
return new TargetConfig({
|
|
target,
|
|
sources: inputs.map(input=>{
|
|
let outName = input.replace(
|
|
/\.js$/,
|
|
`.${[
|
|
type==='dist'? srcOpts.es?'es':'cjs' : null,
|
|
srcOpts.minified?'min':null,
|
|
'js'
|
|
].filter(x=>x).join('.')}`);
|
|
if(type==='lib') outName = [srcOpts.es?'es':'cjs',outName].join('/');
|
|
|
|
return new SourceConfig({
|
|
source: input,
|
|
config: this.srcCfg(input, outDir.resolve(outName), srcOpts)
|
|
});
|
|
})
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Configure a source-file for build (single target)
|
|
*/
|
|
export class SourceConfig{
|
|
/** @param {SourceConfig} c */
|
|
constructor(c){
|
|
this.source = c.source;
|
|
this.config = c.config;
|
|
}
|
|
/** @type {string} */
|
|
source;
|
|
|
|
/** @type {RollupOptions} */
|
|
config;
|
|
}
|
|
|
|
/**
|
|
* Represent the configuration for a specific build target (e.g. lib-es, dist-cjs, ...)
|
|
*/
|
|
export class TargetConfig{
|
|
/** @param {TargetConfig} c */
|
|
constructor(c){
|
|
this.target = c.target;
|
|
this.sources = c.sources;
|
|
}
|
|
/** @type {string} */
|
|
target;
|
|
|
|
/** @type {SourceConfig[]} */
|
|
sources;
|
|
}
|