chore: refactor scripts to js, remove need for tsx

This commit is contained in:
Evan You 2024-09-10 19:13:42 +08:00
parent 91212fa408
commit f599321a65
No known key found for this signature in database
GPG Key ID: 00E9AB7A6704CE0A
5 changed files with 91 additions and 62 deletions

View File

@ -66,7 +66,7 @@ jobs:
if_no_artifact_found: warn if_no_artifact_found: warn
- name: Prepare report - name: Prepare report
run: pnpm tsx scripts/size-report.ts > size-report.md run: node scripts/size-report.js > size-report.md
- name: Read Size Report - name: Read Size Report
id: size-report id: size-report

View File

@ -8,7 +8,7 @@
"build": "node scripts/build.js", "build": "node scripts/build.js",
"build-dts": "tsc -p tsconfig.build.json --noCheck && rollup -c rollup.dts.config.js", "build-dts": "tsc -p tsconfig.build.json --noCheck && rollup -c rollup.dts.config.js",
"clean": "rimraf --glob packages/*/dist temp .eslintcache", "clean": "rimraf --glob packages/*/dist temp .eslintcache",
"size": "run-s \"size-*\" && tsx scripts/usage-size.ts", "size": "run-s \"size-*\" && node scripts/usage-size.js",
"size-global": "node scripts/build.js vue runtime-dom -f global -p --size", "size-global": "node scripts/build.js vue runtime-dom -f global -p --size",
"size-esm-runtime": "node scripts/build.js vue -f esm-bundler-runtime", "size-esm-runtime": "node scripts/build.js vue -f esm-bundler-runtime",
"size-esm": "node scripts/build.js runtime-dom runtime-core reactivity shared -f esm-bundler", "size-esm": "node scripts/build.js runtime-dom runtime-core reactivity shared -f esm-bundler",
@ -104,7 +104,6 @@
"simple-git-hooks": "^2.11.1", "simple-git-hooks": "^2.11.1",
"todomvc-app-css": "^2.4.3", "todomvc-app-css": "^2.4.3",
"tslib": "^2.7.0", "tslib": "^2.7.0",
"tsx": "^4.19.0",
"typescript": "~5.6.2", "typescript": "~5.6.2",
"typescript-eslint": "^8.4.0", "typescript-eslint": "^8.4.0",
"vite": "catalog:", "vite": "catalog:",

View File

@ -167,9 +167,6 @@ importers:
tslib: tslib:
specifier: ^2.7.0 specifier: ^2.7.0
version: 2.7.0 version: 2.7.0
tsx:
specifier: ^4.19.0
version: 4.19.0
typescript: typescript:
specifier: ~5.6.2 specifier: ~5.6.2
version: 5.6.2 version: 5.6.2
@ -3224,11 +3221,6 @@ packages:
tslib@2.7.0: tslib@2.7.0:
resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==}
tsx@4.19.0:
resolution: {integrity: sha512-bV30kM7bsLZKZIOCHeMNVMJ32/LuJzLVajkQI/qf92J2Qr08ueLQvW00PUZGiuLPP760UINwupgUj8qrSCPUKg==}
engines: {node: '>=18.0.0'}
hasBin: true
type-check@0.4.0: type-check@0.4.0:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
@ -6253,13 +6245,6 @@ snapshots:
tslib@2.7.0: {} tslib@2.7.0: {}
tsx@4.19.0:
dependencies:
esbuild: 0.23.1
get-tsconfig: 4.7.6
optionalDependencies:
fsevents: 2.3.3
type-check@0.4.0: type-check@0.4.0:
dependencies: dependencies:
prelude-ls: 1.2.1 prelude-ls: 1.2.1

View File

@ -1,20 +1,24 @@
// @ts-check
import path from 'node:path' import path from 'node:path'
import { markdownTable } from 'markdown-table' import { markdownTable } from 'markdown-table'
import prettyBytes from 'pretty-bytes' import prettyBytes from 'pretty-bytes'
import { readdir } from 'node:fs/promises' import { readdir } from 'node:fs/promises'
import { existsSync } from 'node:fs' import { existsSync } from 'node:fs'
interface SizeResult { /**
size: number * @typedef {Object} SizeResult
gzip: number * @property {number} size
brotli: number * @property {number} gzip
} * @property {number} brotli
*/
interface BundleResult extends SizeResult { /**
file: string * @typedef {SizeResult & { file: string }} BundleResult
} */
type UsageResult = Record<string, SizeResult & { name: string }> /**
* @typedef {Record<string, SizeResult & { name: string }>} UsageResult
*/
const currDir = path.resolve('temp/size') const currDir = path.resolve('temp/size')
const prevDir = path.resolve('temp/size-prev') const prevDir = path.resolve('temp/size-prev')
@ -23,6 +27,9 @@ const sizeHeaders = ['Size', 'Gzip', 'Brotli']
run() run()
/**
* Runs the main process of rendering file and usage data
*/
async function run() { async function run() {
await renderFiles() await renderFiles()
await renderUsages() await renderUsages()
@ -30,26 +37,29 @@ async function run() {
process.stdout.write(output) process.stdout.write(output)
} }
/**
* Renders file sizes and diffs between current and previous versions
*/
async function renderFiles() { async function renderFiles() {
const filterFiles = (files: string[]) => const filterFiles = files =>
files.filter(file => file[0] !== '_' && !file.endsWith('.txt')) files.filter(file => file[0] !== '_' && !file.endsWith('.txt'))
const curr = filterFiles(await readdir(currDir)) const curr = filterFiles(await readdir(currDir))
const prev = existsSync(prevDir) ? filterFiles(await readdir(prevDir)) : [] const prev = existsSync(prevDir) ? filterFiles(await readdir(prevDir)) : []
const fileList = new Set([...curr, ...prev]) const fileList = new Set([...curr, ...prev])
const rows: string[][] = [] const rows = []
for (const file of fileList) { for (const file of fileList) {
const currPath = path.resolve(currDir, file) const currPath = path.resolve(currDir, file)
const prevPath = path.resolve(prevDir, file) const prevPath = path.resolve(prevDir, file)
const curr = await importJSON<BundleResult>(currPath) const curr = await importJSON(currPath)
const prev = await importJSON<BundleResult>(prevPath) const prev = await importJSON(prevPath)
const fileName = curr?.file || prev?.file || '' const fileName = curr?.file || prev?.file || ''
if (!curr) { if (!curr) {
rows.push([`~~${fileName}~~`]) rows.push([`~~${fileName}~~`])
} else } else {
rows.push([ rows.push([
fileName, fileName,
`${prettyBytes(curr.size)}${getDiff(curr.size, prev?.size)}`, `${prettyBytes(curr.size)}${getDiff(curr.size, prev?.size)}`,
@ -57,19 +67,20 @@ async function renderFiles() {
`${prettyBytes(curr.brotli)}${getDiff(curr.brotli, prev?.brotli)}`, `${prettyBytes(curr.brotli)}${getDiff(curr.brotli, prev?.brotli)}`,
]) ])
} }
}
output += '### Bundles\n\n' output += '### Bundles\n\n'
output += markdownTable([['File', ...sizeHeaders], ...rows]) output += markdownTable([['File', ...sizeHeaders], ...rows])
output += '\n\n' output += '\n\n'
} }
/**
* Renders usage data comparing current and previous usage results
*/
async function renderUsages() { async function renderUsages() {
const curr = (await importJSON<UsageResult>( const curr = await importJSON(path.resolve(currDir, '_usages.json'))
path.resolve(currDir, '_usages.json'), const prev = await importJSON(path.resolve(prevDir, '_usages.json'))
))!
const prev = await importJSON<UsageResult>(
path.resolve(prevDir, '_usages.json'),
)
output += '\n### Usages\n\n' output += '\n### Usages\n\n'
const data = Object.values(curr) const data = Object.values(curr)
@ -86,17 +97,31 @@ async function renderUsages() {
`${prettyBytes(usage.brotli)}${diffBrotli}`, `${prettyBytes(usage.brotli)}${diffBrotli}`,
] ]
}) })
.filter((usage): usage is string[] => !!usage) .filter(usage => !!usage)
output += `${markdownTable([['Name', ...sizeHeaders], ...data])}\n\n` output += `${markdownTable([['Name', ...sizeHeaders], ...data])}\n\n`
} }
async function importJSON<T>(path: string): Promise<T | undefined> { /**
if (!existsSync(path)) return undefined * Imports JSON data from a specified path
return (await import(path, { assert: { type: 'json' } })).default *
* @template T
* @param {string} filePath - Path to the JSON file
* @returns {Promise<T | undefined>} The JSON content or undefined if the file does not exist
*/
async function importJSON(filePath) {
if (!existsSync(filePath)) return undefined
return (await import(filePath, { assert: { type: 'json' } })).default
} }
function getDiff(curr: number, prev?: number) { /**
* Calculates the difference between the current and previous sizes
*
* @param {number} curr - The current size
* @param {number} [prev] - The previous size
* @returns {string} The difference in pretty format
*/
function getDiff(curr, prev) {
if (prev === undefined) return '' if (prev === undefined) return ''
const diff = curr - prev const diff = curr - prev
if (diff === 0) return '' if (diff === 0) return ''

View File

@ -1,3 +1,4 @@
// @ts-check
import { mkdir, writeFile } from 'node:fs/promises' import { mkdir, writeFile } from 'node:fs/promises'
import path from 'node:path' import path from 'node:path'
import { rollup } from 'rollup' import { rollup } from 'rollup'
@ -23,12 +24,20 @@ const {
const sizeDir = path.resolve('temp/size') const sizeDir = path.resolve('temp/size')
const entry = path.resolve('./packages/vue/dist/vue.runtime.esm-bundler.js') const entry = path.resolve('./packages/vue/dist/vue.runtime.esm-bundler.js')
interface Preset { /**
name: string * @typedef {Object} Preset
imports: string[] * @property {string} name - The name of the preset
} * @property {string[]} imports - The imports that are part of this preset
* @property {Record<string, string>} [replace]
*/
const presets: Preset[] = [ /** @type {Preset[]} */
const presets = [
{
name: 'createApp (CAPI only)',
imports: ['createApp'],
replace: { __VUE_OPTIONS_API__: 'false' },
},
{ name: 'createApp', imports: ['createApp'] }, { name: 'createApp', imports: ['createApp'] },
{ name: 'createSSRApp', imports: ['createSSRApp'] }, { name: 'createSSRApp', imports: ['createSSRApp'] },
{ name: 'defineCustomElement', imports: ['defineCustomElement'] }, { name: 'defineCustomElement', imports: ['defineCustomElement'] },
@ -47,28 +56,45 @@ const presets: Preset[] = [
main() main()
/**
* Main function that initiates the bundling process for the presets
*/
async function main() { async function main() {
console.log() console.log()
const tasks: ReturnType<typeof generateBundle>[] = [] /** @type {Promise<{name: string, size: number, gzip: number, brotli: number}>[]} */
const tasks = []
for (const preset of presets) { for (const preset of presets) {
tasks.push(generateBundle(preset)) tasks.push(generateBundle(preset))
} }
const results = await Promise.all(tasks)
const results = Object.fromEntries( for (const r of results) {
(await Promise.all(tasks)).map(r => [r.name, r]), console.log(
`${pico.green(pico.bold(r.name))} - ` +
`min:${prettyBytes(r.size, { minimumFractionDigits: 3 })} / ` +
`gzip:${prettyBytes(r.gzip, { minimumFractionDigits: 3 })} / ` +
`brotli:${prettyBytes(r.brotli, { minimumFractionDigits: 3 })}`,
) )
}
await mkdir(sizeDir, { recursive: true }) await mkdir(sizeDir, { recursive: true })
await writeFile( await writeFile(
path.resolve(sizeDir, '_usages.json'), path.resolve(sizeDir, '_usages.json'),
JSON.stringify(results, null, 2), JSON.stringify(Object.fromEntries(results.map(r => [r.name, r])), null, 2),
'utf-8', 'utf-8',
) )
} }
async function generateBundle(preset: Preset) { /**
* Generates a bundle for a given preset
*
* @param {Preset} preset - The preset to generate the bundle for
* @returns {Promise<{name: string, size: number, gzip: number, brotli: number}>} - The result of the bundling process
*/
async function generateBundle(preset) {
const id = 'virtual:entry' const id = 'virtual:entry'
const content = `export { ${preset.imports.join(', ')} } from '${entry}'` const content = `export { ${preset.imports.join(', ')} } from '${entry}'`
const result = await rollup({ const result = await rollup({
input: id, input: id,
plugins: [ plugins: [
@ -89,6 +115,7 @@ async function generateBundle(preset: Preset) {
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'false', __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'false',
__VUE_OPTIONS_API__: 'true', __VUE_OPTIONS_API__: 'true',
preventAssignment: true, preventAssignment: true,
...preset.replace,
}), }),
], ],
}) })
@ -100,7 +127,7 @@ async function generateBundle(preset: Preset) {
module: true, module: true,
toplevel: true, toplevel: true,
}) })
).code! ).code
const size = minified.length const size = minified.length
const gzip = gzipSync(minified).length const gzip = gzipSync(minified).length
@ -110,13 +137,6 @@ async function generateBundle(preset: Preset) {
await writeFile(path.resolve(sizeDir, preset.name + '.js'), bundled) await writeFile(path.resolve(sizeDir, preset.name + '.js'), bundled)
} }
console.log(
`${pico.green(pico.bold(preset.name))} - ` +
`min:${prettyBytes(size, { minimumFractionDigits: 3 })} / ` +
`gzip:${prettyBytes(gzip, { minimumFractionDigits: 3 })} / ` +
`brotli:${prettyBytes(brotli, { minimumFractionDigits: 3 })}`,
)
return { return {
name: preset.name, name: preset.name,
size, size,