umi-library
Version:
Library toolkit based on rollup and docz.
181 lines (162 loc) • 4.43 kB
text/typescript
import { existsSync, readdirSync, readFileSync } from 'fs';
import { join } from 'path';
import rimraf from 'rimraf';
import * as assert from 'assert';
import { merge } from 'lodash';
import signale from 'signale';
import chalk from 'chalk';
import { IOpts, IBundleOptions, IBundleTypeOutput, IEsm } from './types';
import babel from './babel';
import rollup from './rollup';
import registerBabel from './registerBabel';
import { getExistFile } from './utils';
import getUserConfig, { CONFIG_FILES } from './getUserConfig';
export function getBundleOpts(opts: IOpts): IBundleOptions {
const { cwd, buildArgs = {} } = opts;
const entry = getExistFile({
cwd,
files: ['src/index.tsx', 'src/index.ts', 'src/index.jsx', 'src/index.js'],
returnRelative: true,
});
const userConfig = getUserConfig({ cwd });
const bundleOpts = merge(
{
entry,
},
userConfig,
buildArgs,
);
// Support config esm: 'rollup' and cjs: 'rollup'
if (typeof bundleOpts.esm === 'string') {
bundleOpts.esm = { type: bundleOpts.esm };
}
if (typeof bundleOpts.cjs === 'string') {
bundleOpts.cjs = { type: bundleOpts.cjs };
}
return bundleOpts;
}
function validateBundleOpts(bundleOpts: IBundleOptions, { cwd }) {
if (bundleOpts.runtimeHelpers) {
const pkgPath = join(cwd, 'package.json');
assert.ok(
existsSync(pkgPath),
`@babel/runtime dependency is required to use runtimeHelpers`,
);
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
assert.ok(
(pkg.dependencies || {})['@babel/runtime'],
`@babel/runtime dependency is required to use runtimeHelpers`,
);
}
if (!bundleOpts.esm && !bundleOpts.cjs && !bundleOpts.umd) {
throw new Error(
`
None format of ${chalk.cyan(
'cjs | esm | umd',
)} is configured, checkout https://github.com/umijs/umi/tree/master/packages/umi-library for usage details.
`.trim(),
);
}
}
interface IExtraBuildOpts {
pkg?: string;
}
export async function build(opts: IOpts, extraOpts: IExtraBuildOpts = {}) {
const { cwd, watch } = opts;
const { pkg } = extraOpts;
// register babel for config files
registerBabel({
cwd,
only: CONFIG_FILES,
});
function log(msg) {
signale.info(`${pkg ? `[${pkg}] ` : ''}${msg}`);
}
// Get user config
const bundleOpts = getBundleOpts(opts);
validateBundleOpts(bundleOpts, { cwd });
// Clean dist
log(`Clean dist directory`);
rimraf.sync(join(cwd, 'dist'));
// Build umd
if (bundleOpts.umd) {
log(`Build umd`);
await rollup({
cwd,
type: 'umd',
entry: bundleOpts.entry,
watch,
bundleOpts,
});
}
// Build cjs
if (bundleOpts.cjs) {
const cjs = bundleOpts.cjs as IBundleTypeOutput;
log(`Build cjs with ${cjs.type}`);
if (cjs.type === 'babel') {
await babel({ cwd, watch, type: 'cjs', bundleOpts });
} else {
await rollup({
cwd,
type: 'cjs',
entry: bundleOpts.entry,
watch,
bundleOpts,
});
}
}
// Build esm
if (bundleOpts.esm) {
const esm = bundleOpts.esm as IEsm;
log(`Build esm with ${esm.type}`);
if (esm && esm.type === 'babel') {
await babel({ cwd, watch, type: 'esm', bundleOpts });
} else {
await rollup({
cwd,
type: 'esm',
entry: bundleOpts.entry,
watch,
bundleOpts,
});
}
}
}
export async function buildForLerna(opts: IOpts) {
const { cwd } = opts;
// register babel for config files
registerBabel({
cwd,
only: CONFIG_FILES,
});
const userConfig = getUserConfig({ cwd });
const pkgs = readdirSync(join(opts.cwd, 'packages'));
for (const pkg of pkgs) {
if (process.env.PACKAGE && pkg !== process.env.PACKAGE) continue;
const pkgPath = join(opts.cwd, 'packages', pkg);
assert.ok(
existsSync(join(pkgPath, 'package.json')),
`package.json not found in packages/${pkg}`,
);
process.chdir(pkgPath);
await build(
{
// eslint-disable-line
...opts,
buildArgs: merge(opts.buildArgs, userConfig),
cwd: pkgPath,
},
{
pkg,
},
);
}
}
export default async function(opts: IOpts) {
const useLerna = existsSync(join(opts.cwd, 'lerna.json'));
if (useLerna && process.env.LERNA !== 'none') {
await buildForLerna(opts);
} else {
await build(opts);
}
}