2018-09-20 00:21:00 +08:00
|
|
|
/*
|
2019-10-05 22:23:05 +08:00
|
|
|
Produces production builds and stitches together d.ts files.
|
2018-09-20 00:21:00 +08:00
|
|
|
|
2019-10-05 22:23:05 +08:00
|
|
|
To specify the package to build, simply pass its name and the desired build
|
2018-09-20 00:21:00 +08:00
|
|
|
formats to output (defaults to `buildOptions.formats` specified in that package,
|
|
|
|
or "esm,cjs"):
|
|
|
|
|
|
|
|
```
|
|
|
|
# name supports fuzzy match. will build all packages with name containing "dom":
|
|
|
|
yarn build dom
|
|
|
|
|
|
|
|
# specify the format to output
|
|
|
|
yarn build core --formats cjs
|
|
|
|
```
|
|
|
|
*/
|
|
|
|
|
2018-09-19 23:35:38 +08:00
|
|
|
const fs = require('fs-extra')
|
|
|
|
const path = require('path')
|
|
|
|
const chalk = require('chalk')
|
|
|
|
const execa = require('execa')
|
2019-10-04 21:57:32 +08:00
|
|
|
const { gzipSync } = require('zlib')
|
2019-10-02 04:55:04 +08:00
|
|
|
const { compress } = require('brotli')
|
2019-10-02 23:19:30 +08:00
|
|
|
const { targets: allTargets, fuzzyMatchTarget } = require('./utils')
|
2018-09-19 23:35:38 +08:00
|
|
|
|
2018-09-20 00:21:00 +08:00
|
|
|
const args = require('minimist')(process.argv.slice(2))
|
2019-10-02 23:19:30 +08:00
|
|
|
const targets = args._
|
2018-09-20 00:21:00 +08:00
|
|
|
const formats = args.formats || args.f
|
2019-10-02 23:19:30 +08:00
|
|
|
const devOnly = args.devOnly || args.d
|
|
|
|
const prodOnly = !devOnly && (args.prodOnly || args.p)
|
2020-01-28 23:28:40 +08:00
|
|
|
const sourceMap = args.sourcemap || args.s
|
2019-12-11 11:14:02 +08:00
|
|
|
const isRelease = args.release
|
|
|
|
const buildTypes = args.t || args.types || isRelease
|
2018-10-23 23:58:37 +08:00
|
|
|
const buildAllMatching = args.all || args.a
|
2019-10-05 10:40:54 +08:00
|
|
|
const commit = execa.sync('git', ['rev-parse', 'HEAD']).stdout.slice(0, 7)
|
2019-10-14 13:08:00 +08:00
|
|
|
|
|
|
|
run()
|
|
|
|
|
|
|
|
async function run() {
|
2020-07-15 22:47:57 +08:00
|
|
|
if (isRelease) {
|
|
|
|
// remove build cache for release builds to avoid outdated enum values
|
|
|
|
await fs.remove(path.resolve(__dirname, '../node_modules/.rts2_cache'))
|
|
|
|
}
|
2019-10-02 23:19:30 +08:00
|
|
|
if (!targets.length) {
|
|
|
|
await buildAll(allTargets)
|
|
|
|
checkAllSizes(allTargets)
|
2018-09-19 23:35:38 +08:00
|
|
|
} else {
|
2019-10-02 23:19:30 +08:00
|
|
|
await buildAll(fuzzyMatchTarget(targets, buildAllMatching))
|
|
|
|
checkAllSizes(fuzzyMatchTarget(targets, buildAllMatching))
|
2018-09-19 23:35:38 +08:00
|
|
|
}
|
2019-10-14 13:08:00 +08:00
|
|
|
}
|
2018-09-19 23:35:38 +08:00
|
|
|
|
2018-09-20 00:21:00 +08:00
|
|
|
async function buildAll(targets) {
|
2020-12-04 02:22:28 +08:00
|
|
|
await runParallel(require('os').cpus().length, targets, build)
|
|
|
|
}
|
|
|
|
|
|
|
|
async function runParallel(maxConcurrency, source, iteratorFn) {
|
|
|
|
const ret = []
|
|
|
|
const executing = []
|
|
|
|
for (const item of source) {
|
|
|
|
const p = Promise.resolve().then(() => iteratorFn(item, source))
|
|
|
|
ret.push(p)
|
|
|
|
|
|
|
|
if (maxConcurrency <= source.length) {
|
|
|
|
const e = p.then(() => executing.splice(executing.indexOf(e), 1))
|
|
|
|
executing.push(e)
|
|
|
|
if (executing.length >= maxConcurrency) {
|
|
|
|
await Promise.race(executing)
|
|
|
|
}
|
|
|
|
}
|
2018-09-19 23:35:38 +08:00
|
|
|
}
|
2020-12-04 02:22:28 +08:00
|
|
|
return Promise.all(ret)
|
2018-09-19 23:35:38 +08:00
|
|
|
}
|
|
|
|
|
2018-09-20 00:21:00 +08:00
|
|
|
async function build(target) {
|
2018-09-19 23:35:38 +08:00
|
|
|
const pkgDir = path.resolve(`packages/${target}`)
|
2018-10-17 05:41:59 +08:00
|
|
|
const pkg = require(`${pkgDir}/package.json`)
|
2018-09-19 23:35:38 +08:00
|
|
|
|
2019-12-11 11:14:02 +08:00
|
|
|
// only build published packages for release
|
|
|
|
if (isRelease && pkg.private) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-11-07 04:23:50 +08:00
|
|
|
// if building a specific format, do not remove dist.
|
|
|
|
if (!formats) {
|
|
|
|
await fs.remove(`${pkgDir}/dist`)
|
|
|
|
}
|
2018-09-19 23:35:38 +08:00
|
|
|
|
2019-10-05 01:08:06 +08:00
|
|
|
const env =
|
|
|
|
(pkg.buildOptions && pkg.buildOptions.env) ||
|
|
|
|
(devOnly ? 'development' : 'production')
|
2018-09-20 00:21:00 +08:00
|
|
|
await execa(
|
|
|
|
'rollup',
|
|
|
|
[
|
|
|
|
'-c',
|
|
|
|
'--environment',
|
2019-10-05 10:40:54 +08:00
|
|
|
[
|
|
|
|
`COMMIT:${commit}`,
|
|
|
|
`NODE_ENV:${env}`,
|
|
|
|
`TARGET:${target}`,
|
|
|
|
formats ? `FORMATS:${formats}` : ``,
|
2019-11-01 23:32:53 +08:00
|
|
|
buildTypes ? `TYPES:true` : ``,
|
2019-10-14 13:08:00 +08:00
|
|
|
prodOnly ? `PROD_ONLY:true` : ``,
|
2020-01-28 23:28:40 +08:00
|
|
|
sourceMap ? `SOURCE_MAP:true` : ``
|
2019-10-05 10:40:54 +08:00
|
|
|
]
|
2019-10-12 22:55:35 +08:00
|
|
|
.filter(Boolean)
|
2019-10-05 10:40:54 +08:00
|
|
|
.join(',')
|
2018-09-20 00:21:00 +08:00
|
|
|
],
|
|
|
|
{ stdio: 'inherit' }
|
|
|
|
)
|
2018-09-19 23:35:38 +08:00
|
|
|
|
2019-11-01 23:32:53 +08:00
|
|
|
if (buildTypes && pkg.types) {
|
2018-10-17 05:41:59 +08:00
|
|
|
console.log()
|
|
|
|
console.log(
|
2019-09-04 00:16:22 +08:00
|
|
|
chalk.bold(chalk.yellow(`Rolling up type definitions for ${target}...`))
|
|
|
|
)
|
|
|
|
|
|
|
|
// build types
|
|
|
|
const { Extractor, ExtractorConfig } = require('@microsoft/api-extractor')
|
|
|
|
|
|
|
|
const extractorConfigPath = path.resolve(pkgDir, `api-extractor.json`)
|
|
|
|
const extractorConfig = ExtractorConfig.loadFileAndPrepare(
|
|
|
|
extractorConfigPath
|
2018-10-17 05:41:59 +08:00
|
|
|
)
|
2020-05-01 02:49:58 +08:00
|
|
|
const extractorResult = Extractor.invoke(extractorConfig, {
|
2019-09-04 00:16:22 +08:00
|
|
|
localBuild: true,
|
|
|
|
showVerboseMessages: true
|
|
|
|
})
|
|
|
|
|
2020-05-01 02:49:58 +08:00
|
|
|
if (extractorResult.succeeded) {
|
2020-05-02 04:14:30 +08:00
|
|
|
// concat additional d.ts to rolled-up dts
|
|
|
|
const typesDir = path.resolve(pkgDir, 'types')
|
|
|
|
if (await fs.exists(typesDir)) {
|
2019-11-01 23:32:53 +08:00
|
|
|
const dtsPath = path.resolve(pkgDir, pkg.types)
|
|
|
|
const existing = await fs.readFile(dtsPath, 'utf-8')
|
2020-05-02 04:14:30 +08:00
|
|
|
const typeFiles = await fs.readdir(typesDir)
|
2019-11-01 23:32:53 +08:00
|
|
|
const toAdd = await Promise.all(
|
2020-05-02 04:14:30 +08:00
|
|
|
typeFiles.map(file => {
|
|
|
|
return fs.readFile(path.resolve(typesDir, file), 'utf-8')
|
2019-11-01 23:32:53 +08:00
|
|
|
})
|
|
|
|
)
|
|
|
|
await fs.writeFile(dtsPath, existing + '\n' + toAdd.join('\n'))
|
|
|
|
}
|
2019-09-04 00:16:22 +08:00
|
|
|
console.log(
|
|
|
|
chalk.bold(chalk.green(`API Extractor completed successfully.`))
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
console.error(
|
|
|
|
`API Extractor completed with ${extractorResult.errorCount} errors` +
|
|
|
|
` and ${extractorResult.warningCount} warnings`
|
|
|
|
)
|
|
|
|
process.exitCode = 1
|
|
|
|
}
|
2018-09-19 23:35:38 +08:00
|
|
|
|
2018-10-17 05:41:59 +08:00
|
|
|
await fs.remove(`${pkgDir}/dist/packages`)
|
|
|
|
}
|
2018-09-19 23:35:38 +08:00
|
|
|
}
|
|
|
|
|
2018-09-20 00:21:00 +08:00
|
|
|
function checkAllSizes(targets) {
|
2019-12-03 07:18:02 +08:00
|
|
|
if (devOnly) {
|
|
|
|
return
|
|
|
|
}
|
2018-09-19 23:35:38 +08:00
|
|
|
console.log()
|
|
|
|
for (const target of targets) {
|
|
|
|
checkSize(target)
|
|
|
|
}
|
|
|
|
console.log()
|
|
|
|
}
|
|
|
|
|
2018-09-20 00:21:00 +08:00
|
|
|
function checkSize(target) {
|
2018-09-19 23:35:38 +08:00
|
|
|
const pkgDir = path.resolve(`packages/${target}`)
|
2020-03-24 03:09:29 +08:00
|
|
|
checkFileSize(`${pkgDir}/dist/${target}.global.prod.js`)
|
2021-04-08 00:24:35 +08:00
|
|
|
checkFileSize(`${pkgDir}/dist/${target}.runtime.global.prod.js`)
|
2020-03-24 03:09:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
function checkFileSize(filePath) {
|
|
|
|
if (!fs.existsSync(filePath)) {
|
|
|
|
return
|
2018-09-19 23:35:38 +08:00
|
|
|
}
|
2020-03-24 03:09:29 +08:00
|
|
|
const file = fs.readFileSync(filePath)
|
|
|
|
const minSize = (file.length / 1024).toFixed(2) + 'kb'
|
|
|
|
const gzipped = gzipSync(file)
|
|
|
|
const gzippedSize = (gzipped.length / 1024).toFixed(2) + 'kb'
|
|
|
|
const compressed = compress(file)
|
|
|
|
const compressedSize = (compressed.length / 1024).toFixed(2) + 'kb'
|
|
|
|
console.log(
|
|
|
|
`${chalk.gray(
|
|
|
|
chalk.bold(path.basename(filePath))
|
|
|
|
)} min:${minSize} / gzip:${gzippedSize} / brotli:${compressedSize}`
|
|
|
|
)
|
2018-09-19 23:35:38 +08:00
|
|
|
}
|