vue3-core/scripts/build.js

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

243 lines
5.9 KiB
JavaScript
Raw Permalink Normal View History

// @ts-check
2018-09-20 00:21:00 +08:00
/*
Produces production builds and stitches together d.ts files.
2018-09-20 00:21:00 +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":
2021-10-09 02:23:30 +08:00
nr build dom
2018-09-20 00:21:00 +08:00
# specify the format to output
2021-10-09 02:23:30 +08:00
nr build core --formats cjs
2018-09-20 00:21:00 +08:00
```
*/
2024-11-08 19:55:14 +08:00
import { rolldown } from 'rolldown'
import fs from 'node:fs'
import { parseArgs } from 'node:util'
import { existsSync, readFileSync } from 'node:fs'
2023-01-26 14:24:49 +08:00
import path from 'node:path'
import { brotliCompressSync, gzipSync } from 'node:zlib'
2023-10-20 10:23:18 +08:00
import pico from 'picocolors'
2024-11-14 20:57:59 +08:00
import { targets as allTargets, fuzzyMatchTarget } from './utils.js'
2023-08-21 11:33:51 +08:00
import prettyBytes from 'pretty-bytes'
import { spawnSync } from 'node:child_process'
2024-11-14 20:57:59 +08:00
import { createConfigsForPackage } from './create-rolldown-config.js'
import { scanEnums } from './inline-enums.js'
import { fileURLToPath } from 'node:url'
2024-11-14 20:57:59 +08:00
const __dirname = fileURLToPath(new URL('.', import.meta.url))
const privatePackages = fs.readdirSync('packages-private')
const commit = spawnSync('git', ['rev-parse', '--short=7', 'HEAD'])
.stdout.toString()
.trim()
const { values, positionals: targets } = parseArgs({
allowPositionals: true,
options: {
formats: {
type: 'string',
short: 'f',
},
devOnly: {
type: 'boolean',
short: 'd',
},
prodOnly: {
type: 'boolean',
short: 'p',
},
withTypes: {
type: 'boolean',
short: 't',
},
sourceMap: {
type: 'boolean',
short: 's',
},
release: {
type: 'boolean',
},
all: {
type: 'boolean',
short: 'a',
},
size: {
type: 'boolean',
},
},
})
const {
2024-11-14 20:57:59 +08:00
formats: rawFormats,
all: buildAllMatching,
devOnly,
prodOnly,
withTypes: buildTypes,
sourceMap,
release: isRelease,
2024-11-14 20:57:59 +08:00
size,
} = values
2024-11-14 20:57:59 +08:00
const formats = rawFormats?.split(',')
2023-08-21 11:33:51 +08:00
const sizeDir = path.resolve('temp/size')
run()
async function run() {
2024-11-14 20:57:59 +08:00
if (size) fs.mkdirSync(sizeDir, { recursive: true })
const removeCache = scanEnums()
try {
const resolvedTargets = targets.length
? fuzzyMatchTarget(targets, buildAllMatching)
: allTargets
await buildAll(resolvedTargets)
2024-11-14 20:57:59 +08:00
if (size) await checkAllSizes(resolvedTargets)
if (buildTypes) {
2024-11-14 20:57:59 +08:00
await import('./build-types.js')
}
} finally {
removeCache()
2018-09-19 23:35:38 +08:00
}
}
2018-09-19 23:35:38 +08:00
/**
* Builds all the targets in parallel.
* @param {Array<string>} targets - An array of targets to build.
* @returns {Promise<void>} - A promise representing the build process.
*/
2018-09-20 00:21:00 +08:00
async function buildAll(targets) {
2024-11-14 20:57:59 +08:00
const start = performance.now()
const all = []
let count = 0
for (const t of targets) {
const configs = createConfigsForTarget(t)
if (configs) {
all.push(
Promise.all(
configs.map(c =>
rolldown(c).then(bundle => {
return bundle.write(c.output).then(() => {
// @ts-expect-error
2024-11-08 19:58:25 +08:00
return path.join('packages', t, 'dist', c.output.file)
2024-11-14 20:57:59 +08:00
})
}),
),
).then(files => {
files.forEach(f => {
count++
console.log(pico.gray('built: ') + pico.green(f))
})
}),
)
}
2018-09-19 23:35:38 +08:00
}
2024-11-14 20:57:59 +08:00
await Promise.all(all)
console.log(
`\n${count} files built in ${(performance.now() - start).toFixed(2)}ms.`,
)
2018-09-19 23:35:38 +08:00
}
/**
* Builds the target.
* @param {string} target - The target to build.
2024-11-14 20:57:59 +08:00
* @returns {import('rolldown').RolldownOptions[] | void} - A promise representing the build process.
*/
2024-11-14 20:57:59 +08:00
function createConfigsForTarget(target) {
const pkgBase = privatePackages.includes(target)
? `packages-private`
: `packages`
2024-11-14 20:57:59 +08:00
const pkgDir = path.resolve(__dirname, `../${pkgBase}/${target}`)
const pkg = JSON.parse(readFileSync(`${pkgDir}/package.json`, 'utf-8'))
2018-09-19 23:35:38 +08:00
// if this is a full build (no specific targets), ignore private packages
if ((isRelease || !targets.length) && pkg.private) {
2019-12-11 11:14:02 +08:00
return
}
// if building a specific format, do not remove dist.
2023-01-26 16:11:24 +08:00
if (!formats && existsSync(`${pkgDir}/dist`)) {
fs.rmSync(`${pkgDir}/dist`, { recursive: true })
}
2018-09-19 23:35:38 +08:00
2024-11-14 20:57:59 +08:00
return createConfigsForPackage({
target,
commit,
// @ts-expect-error
formats,
prodOnly,
devOnly:
(pkg.buildOptions && pkg.buildOptions.env === 'development') || devOnly,
sourceMap,
})
2018-09-19 23:35:38 +08:00
}
/**
* Checks the sizes of all targets.
* @param {string[]} targets - The targets to check sizes for.
* @returns {Promise<void>}
*/
2023-08-21 11:33:51 +08:00
async function checkAllSizes(targets) {
2021-09-24 02:46:16 +08:00
if (devOnly || (formats && !formats.includes('global'))) {
2019-12-03 07:18:02 +08:00
return
}
2018-09-19 23:35:38 +08:00
console.log()
for (const target of targets) {
2023-08-21 11:33:51 +08:00
await checkSize(target)
2018-09-19 23:35:38 +08:00
}
console.log()
}
/**
* Checks the size of a target.
* @param {string} target - The target to check the size for.
* @returns {Promise<void>}
*/
2023-08-21 11:33:51 +08:00
async function checkSize(target) {
2024-11-14 20:57:59 +08:00
const pkgDir = path.resolve(__dirname, `../packages/${target}`)
2023-08-21 11:33:51 +08:00
await checkFileSize(`${pkgDir}/dist/${target}.global.prod.js`)
2021-09-24 02:46:16 +08:00
if (!formats || formats.includes('global-runtime')) {
2023-08-21 11:33:51 +08:00
await checkFileSize(`${pkgDir}/dist/${target}.runtime.global.prod.js`)
2021-09-24 02:46:16 +08:00
}
}
/**
* Checks the file size.
* @param {string} filePath - The path of the file to check the size for.
* @returns {Promise<void>}
*/
2023-08-21 11:33:51 +08:00
async function checkFileSize(filePath) {
2023-01-26 14:24:49 +08:00
if (!existsSync(filePath)) {
return
2018-09-19 23:35:38 +08:00
}
const file = fs.readFileSync(filePath)
2023-08-21 11:33:51 +08:00
const fileName = path.basename(filePath)
const gzipped = gzipSync(file)
2023-08-21 11:33:51 +08:00
const brotli = brotliCompressSync(file)
console.log(
2023-10-20 10:23:18 +08:00
`${pico.gray(pico.bold(fileName))} min:${prettyBytes(
2023-08-21 11:33:51 +08:00
file.length,
)} / gzip:${prettyBytes(gzipped.length)} / brotli:${prettyBytes(
brotli.length,
)}`,
)
2023-08-21 11:33:51 +08:00
2024-11-14 20:57:59 +08:00
if (size)
fs.writeFileSync(
2023-08-21 11:33:51 +08:00
path.resolve(sizeDir, `${fileName}.json`),
JSON.stringify({
file: fileName,
size: file.length,
gzip: gzipped.length,
brotli: brotli.length,
}),
'utf-8',
)
2018-09-19 23:35:38 +08:00
}