ci: improved size report (#8992)

This commit is contained in:
三咲智子 Kevin Deng 2023-08-21 11:33:51 +08:00 committed by GitHub
parent bd08f057fc
commit 1b56405299
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 443 additions and 124 deletions

View File

@ -74,12 +74,7 @@ module.exports = {
}, },
// Node scripts // Node scripts
{ {
files: [ files: ['scripts/**', '*.{js,ts}', 'packages/**/index.js'],
'scripts/**',
'*.{js,ts}',
'packages/**/index.js',
'packages/size-check/**'
],
rules: { rules: {
'no-restricted-globals': 'off', 'no-restricted-globals': 'off',
'no-restricted-syntax': 'off' 'no-restricted-syntax': 'off'

View File

@ -248,8 +248,6 @@ This repository employs a [monorepo](https://en.wikipedia.org/wiki/Monorepo) set
- `template-explorer`: A development tool for debugging compiler output, continuously deployed at https://template-explorer.vuejs.org/. To run it locally, run [`nr dev-compiler`](#nr-dev-compiler). - `template-explorer`: A development tool for debugging compiler output, continuously deployed at https://template-explorer.vuejs.org/. To run it locally, run [`nr dev-compiler`](#nr-dev-compiler).
- `size-check`: Used for checking built bundle sizes on CI.
### Importing Packages ### Importing Packages
The packages can import each other directly using their package names. Note that when importing a package, the name listed in its `package.json` should be used. Most of the time the `@vue/` prefix is needed: The packages can import each other directly using their package names. Note that when importing a package, the name listed in its `package.json` should be used. Most of the time the `@vue/` prefix is needed:

View File

@ -114,23 +114,3 @@ jobs:
- name: Run type declaration tests - name: Run type declaration tests
run: pnpm run test-dts run: pnpm run test-dts
size:
runs-on: ubuntu-latest
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
env:
CI_JOB_NUMBER: 1
steps:
- uses: actions/checkout@v3
- name: Install pnpm
uses: pnpm/action-setup@v2
- name: Set node version to 18
uses: actions/setup-node@v3
with:
node-version: 18
cache: 'pnpm'
- run: PUPPETEER_SKIP_DOWNLOAD=1 pnpm install
- run: pnpm run size

61
.github/workflows/size-report.yml vendored Normal file
View File

@ -0,0 +1,61 @@
name: size report
on:
pull_request:
branches:
- main
permissions:
contents: read
pull-requests: write
jobs:
size:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install pnpm
uses: pnpm/action-setup@v2
- name: Set node version to LTS
uses: actions/setup-node@v3
with:
node-version: lts/*
cache: pnpm
- run: PUPPETEER_SKIP_DOWNLOAD=1 pnpm install
- run: pnpm run size
- name: Download Previous Size Report
id: download-artifact
uses: dawidd6/action-download-artifact@v2
with:
branch: main
name: size-report
path: temp/size-prev
if_no_artifact_found: warn
- name: Upload Size Report
uses: actions/upload-artifact@v3
with:
name: size-report
path: temp/size
- name: Compare size
run: pnpm tsx scripts/size-report.ts > size.md
- name: Read Size Markdown
id: size-markdown
uses: juliangruber/read-file-action@v1
with:
path: ./size.md
- name: Create Comment
uses: actions-cool/maintain-one-comment@v3
with:
body: |
${{steps.size-markdown.outputs.content}}
<!-- VUE_CORE_SIZE -->
body-include: '<!-- VUE_CORE_SIZE -->'

View File

@ -7,9 +7,10 @@
"dev": "node scripts/dev.js", "dev": "node scripts/dev.js",
"build": "node scripts/build.js", "build": "node scripts/build.js",
"build-dts": "tsc -p tsconfig.build.json && rollup -c rollup.dts.config.js", "build-dts": "tsc -p tsconfig.build.json && rollup -c rollup.dts.config.js",
"size": "run-s size-global size-baseline", "size": "run-s \"size-*\" && tsx scripts/usage-size.ts",
"size-global": "node scripts/build.js vue runtime-dom -f global -p", "size-global": "node scripts/build.js vue runtime-dom -f global -p --size",
"size-baseline": "node scripts/build.js vue -f esm-bundler-runtime && node scripts/build.js runtime-dom runtime-core reactivity shared -f esm-bundler && cd packages/size-check && vite build && node brotli", "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",
"check": "tsc --incremental --noEmit", "check": "tsc --incremental --noEmit",
"lint": "eslint --cache --ext .ts packages/*/{src,__tests__}/**.ts", "lint": "eslint --cache --ext .ts packages/*/{src,__tests__}/**.ts",
"format": "prettier --write --cache \"**/*.[tj]s?(x)\"", "format": "prettier --write --cache \"**/*.[tj]s?(x)\"",
@ -81,10 +82,12 @@
"lint-staged": "^10.2.10", "lint-staged": "^10.2.10",
"lodash": "^4.17.15", "lodash": "^4.17.15",
"magic-string": "^0.30.0", "magic-string": "^0.30.0",
"markdown-table": "^3.0.3",
"marked": "^4.0.10", "marked": "^4.0.10",
"minimist": "^1.2.0", "minimist": "^1.2.0",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "^3.0.1", "prettier": "^3.0.1",
"pretty-bytes": "^6.1.1",
"pug": "^3.0.1", "pug": "^3.0.1",
"puppeteer": "~19.6.0", "puppeteer": "~19.6.0",
"rollup": "^3.26.0", "rollup": "^3.26.0",
@ -94,9 +97,10 @@
"semver": "^7.3.2", "semver": "^7.3.2",
"serve": "^12.0.0", "serve": "^12.0.0",
"simple-git-hooks": "^2.8.1", "simple-git-hooks": "^2.8.1",
"terser": "^5.15.1", "terser": "^5.19.2",
"todomvc-app-css": "^2.3.0", "todomvc-app-css": "^2.3.0",
"tslib": "^2.5.0", "tslib": "^2.5.0",
"tsx": "^3.12.7",
"typescript": "^5.1.6", "typescript": "^5.1.6",
"vite": "^4.3.0", "vite": "^4.3.0",
"vitest": "^0.30.1" "vitest": "^0.30.1"

View File

@ -1,3 +0,0 @@
# Size Check
This package is private and is used for checking the baseline runtime size after tree-shaking (with only the bare minimal code required to render something to the screen).

View File

@ -1,6 +0,0 @@
const { brotliCompressSync } = require('zlib')
const file = require('fs').readFileSync('dist/index.js')
const compressed = brotliCompressSync(file)
const compressedSize = (compressed.length / 1024).toFixed(2) + 'kb'
console.log(`brotli: ${compressedSize}`)

View File

@ -1,11 +0,0 @@
{
"name": "@vue/size-check",
"version": "3.3.4",
"private": true,
"scripts": {
"build": "vite build"
},
"dependencies": {
"vue": "workspace:*"
}
}

View File

@ -1,6 +0,0 @@
import { h, createApp } from 'vue'
// The bare minimum code required for rendering something to the screen
createApp({
render: () => h('div', 'hello world!')
}).mount('#app')

View File

@ -1,15 +0,0 @@
export default {
define: {
__VUE_PROD_DEVTOOLS__: false,
__VUE_OPTIONS_API__: true
},
build: {
rollupOptions: {
input: ['src/index.ts'],
output: {
entryFileNames: `[name].js`
}
},
minify: 'terser'
}
}

View File

@ -86,6 +86,9 @@ importers:
magic-string: magic-string:
specifier: ^0.30.0 specifier: ^0.30.0
version: 0.30.0 version: 0.30.0
markdown-table:
specifier: ^3.0.3
version: 3.0.3
marked: marked:
specifier: ^4.0.10 specifier: ^4.0.10
version: 4.3.0 version: 4.3.0
@ -98,6 +101,9 @@ importers:
prettier: prettier:
specifier: ^3.0.1 specifier: ^3.0.1
version: 3.0.1 version: 3.0.1
pretty-bytes:
specifier: ^6.1.1
version: 6.1.1
pug: pug:
specifier: ^3.0.1 specifier: ^3.0.1
version: 3.0.2 version: 3.0.2
@ -126,23 +132,26 @@ importers:
specifier: ^2.8.1 specifier: ^2.8.1
version: 2.8.1 version: 2.8.1
terser: terser:
specifier: ^5.15.1 specifier: ^5.19.2
version: 5.18.2 version: 5.19.2
todomvc-app-css: todomvc-app-css:
specifier: ^2.3.0 specifier: ^2.3.0
version: 2.4.2 version: 2.4.2
tslib: tslib:
specifier: ^2.5.0 specifier: ^2.5.0
version: 2.6.0 version: 2.6.0
tsx:
specifier: ^3.12.7
version: 3.12.7
typescript: typescript:
specifier: ^5.1.6 specifier: ^5.1.6
version: 5.1.6 version: 5.1.6
vite: vite:
specifier: ^4.3.0 specifier: ^4.3.0
version: 4.3.1(@types/node@16.18.38)(terser@5.18.2) version: 4.3.1(@types/node@16.18.38)(terser@5.19.2)
vitest: vitest:
specifier: ^0.30.1 specifier: ^0.30.1
version: 0.30.1(jsdom@21.1.0)(terser@5.18.2) version: 0.30.1(jsdom@21.1.0)(terser@5.19.2)
packages/compiler-core: packages/compiler-core:
dependencies: dependencies:
@ -354,12 +363,6 @@ importers:
packages/shared: {} packages/shared: {}
packages/size-check:
dependencies:
vue:
specifier: workspace:*
version: link:../vue
packages/template-explorer: packages/template-explorer:
dependencies: dependencies:
monaco-editor: monaco-editor:
@ -422,11 +425,12 @@ packages:
'@babel/highlight': 7.22.5 '@babel/highlight': 7.22.5
dev: true dev: true
/@babel/code-frame@7.22.5: /@babel/code-frame@7.22.10:
resolution: {integrity: sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==} resolution: {integrity: sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/highlight': 7.22.5 '@babel/highlight': 7.22.10
chalk: 2.4.2
dev: true dev: true
/@babel/compat-data@7.21.0: /@babel/compat-data@7.21.0:
@ -567,6 +571,15 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@babel/highlight@7.22.10:
resolution: {integrity: sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-validator-identifier': 7.22.5
chalk: 2.4.2
js-tokens: 4.0.0
dev: true
/@babel/highlight@7.22.5: /@babel/highlight@7.22.5:
resolution: {integrity: sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==} resolution: {integrity: sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
@ -587,7 +600,7 @@ packages:
resolution: {integrity: sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==} resolution: {integrity: sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/code-frame': 7.18.6 '@babel/code-frame': 7.22.10
'@babel/parser': 7.21.3 '@babel/parser': 7.21.3
'@babel/types': 7.21.3 '@babel/types': 7.21.3
dev: true dev: true
@ -596,7 +609,7 @@ packages:
resolution: {integrity: sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==} resolution: {integrity: sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/code-frame': 7.22.5 '@babel/code-frame': 7.22.10
'@babel/generator': 7.21.3 '@babel/generator': 7.21.3
'@babel/helper-environment-visitor': 7.18.9 '@babel/helper-environment-visitor': 7.18.9
'@babel/helper-function-name': 7.21.0 '@babel/helper-function-name': 7.21.0
@ -618,6 +631,27 @@ packages:
'@babel/helper-validator-identifier': 7.19.1 '@babel/helper-validator-identifier': 7.19.1
to-fast-properties: 2.0.0 to-fast-properties: 2.0.0
/@esbuild-kit/cjs-loader@2.4.2:
resolution: {integrity: sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==}
dependencies:
'@esbuild-kit/core-utils': 3.1.0
get-tsconfig: 4.7.0
dev: true
/@esbuild-kit/core-utils@3.1.0:
resolution: {integrity: sha512-Uuk8RpCg/7fdHSceR1M6XbSZFSuMrxcePFuGgyvsBn+u339dk5OeL4jv2EojwTN2st/unJGsVm4qHWjWNmJ/tw==}
dependencies:
esbuild: 0.17.19
source-map-support: 0.5.21
dev: true
/@esbuild-kit/esm-loader@2.5.5:
resolution: {integrity: sha512-Qwfvj/qoPbClxCRNuac1Du01r9gvNOT+pMYtJDapfB1eoGN1YlJ1BixLyL9WVENRx5RXgNLdfYdx/CuswlGhMw==}
dependencies:
'@esbuild-kit/core-utils': 3.1.0
get-tsconfig: 4.7.0
dev: true
/@esbuild/android-arm64@0.17.19: /@esbuild/android-arm64@0.17.19:
resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -1078,11 +1112,25 @@ packages:
'@jridgewell/trace-mapping': 0.3.17 '@jridgewell/trace-mapping': 0.3.17
dev: true dev: true
/@jridgewell/gen-mapping@0.3.3:
resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
engines: {node: '>=6.0.0'}
dependencies:
'@jridgewell/set-array': 1.1.2
'@jridgewell/sourcemap-codec': 1.4.15
'@jridgewell/trace-mapping': 0.3.19
dev: true
/@jridgewell/resolve-uri@3.1.0: /@jridgewell/resolve-uri@3.1.0:
resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==}
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
dev: true dev: true
/@jridgewell/resolve-uri@3.1.1:
resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==}
engines: {node: '>=6.0.0'}
dev: true
/@jridgewell/set-array@1.1.2: /@jridgewell/set-array@1.1.2:
resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
@ -1091,13 +1139,17 @@ packages:
/@jridgewell/source-map@0.3.5: /@jridgewell/source-map@0.3.5:
resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==} resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==}
dependencies: dependencies:
'@jridgewell/gen-mapping': 0.3.2 '@jridgewell/gen-mapping': 0.3.3
'@jridgewell/trace-mapping': 0.3.17 '@jridgewell/trace-mapping': 0.3.19
dev: true dev: true
/@jridgewell/sourcemap-codec@1.4.14: /@jridgewell/sourcemap-codec@1.4.14:
resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==}
/@jridgewell/sourcemap-codec@1.4.15:
resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
dev: true
/@jridgewell/trace-mapping@0.3.17: /@jridgewell/trace-mapping@0.3.17:
resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==} resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==}
dependencies: dependencies:
@ -1105,6 +1157,13 @@ packages:
'@jridgewell/sourcemap-codec': 1.4.14 '@jridgewell/sourcemap-codec': 1.4.14
dev: true dev: true
/@jridgewell/trace-mapping@0.3.19:
resolution: {integrity: sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==}
dependencies:
'@jridgewell/resolve-uri': 3.1.1
'@jridgewell/sourcemap-codec': 1.4.15
dev: true
/@jspm/core@2.0.1: /@jspm/core@2.0.1:
resolution: {integrity: sha512-Lg3PnLp0QXpxwLIAuuJboLeRaIhrgJjeuh797QADg3xz8wGLugQOS5DpsE8A6i6Adgzf+bacllkKZG3J0tGfDw==} resolution: {integrity: sha512-Lg3PnLp0QXpxwLIAuuJboLeRaIhrgJjeuh797QADg3xz8wGLugQOS5DpsE8A6i6Adgzf+bacllkKZG3J0tGfDw==}
dev: true dev: true
@ -1233,7 +1292,7 @@ packages:
rollup: 3.26.2 rollup: 3.26.2
serialize-javascript: 6.0.1 serialize-javascript: 6.0.1
smob: 0.0.6 smob: 0.0.6
terser: 5.18.2 terser: 5.19.2
dev: true dev: true
/@rollup/pluginutils@5.0.2(rollup@3.26.2): /@rollup/pluginutils@5.0.2(rollup@3.26.2):
@ -1464,7 +1523,7 @@ packages:
istanbul-lib-source-maps: 4.0.1 istanbul-lib-source-maps: 4.0.1
istanbul-reports: 3.1.5 istanbul-reports: 3.1.5
test-exclude: 6.0.0 test-exclude: 6.0.0
vitest: 0.30.1(jsdom@21.1.0)(terser@5.18.2) vitest: 0.30.1(jsdom@21.1.0)(terser@5.19.2)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: true dev: true
@ -1568,6 +1627,12 @@ packages:
hasBin: true hasBin: true
dev: true dev: true
/acorn@8.10.0:
resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==}
engines: {node: '>=0.4.0'}
hasBin: true
dev: true
/acorn@8.8.2: /acorn@8.8.2:
resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==}
engines: {node: '>=0.4.0'} engines: {node: '>=0.4.0'}
@ -3066,6 +3131,12 @@ packages:
get-intrinsic: 1.2.0 get-intrinsic: 1.2.0
dev: true dev: true
/get-tsconfig@4.7.0:
resolution: {integrity: sha512-pmjiZ7xtB8URYm74PlGJozDNyhvsVLUcpBa8DZBG3bWHwaHa9bPiRpiSfovw+fjhwONSCWKRyk+JQHEGZmMrzw==}
dependencies:
resolve-pkg-maps: 1.0.0
dev: true
/git-raw-commits@2.0.11: /git-raw-commits@2.0.11:
resolution: {integrity: sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==} resolution: {integrity: sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -3991,6 +4062,10 @@ packages:
engines: {node: '>=8'} engines: {node: '>=8'}
dev: true dev: true
/markdown-table@3.0.3:
resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==}
dev: true
/marked@4.3.0: /marked@4.3.0:
resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==}
engines: {node: '>= 12'} engines: {node: '>= 12'}
@ -4414,7 +4489,7 @@ packages:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'} engines: {node: '>=8'}
dependencies: dependencies:
'@babel/code-frame': 7.22.5 '@babel/code-frame': 7.22.10
error-ex: 1.3.2 error-ex: 1.3.2
json-parse-even-better-errors: 2.3.1 json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.2.4 lines-and-columns: 1.2.4
@ -4627,6 +4702,11 @@ packages:
hasBin: true hasBin: true
dev: true dev: true
/pretty-bytes@6.1.1:
resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==}
engines: {node: ^14.13.1 || >=16.0.0}
dev: true
/pretty-format@27.5.1: /pretty-format@27.5.1:
resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
@ -4963,6 +5043,10 @@ packages:
engines: {node: '>=4'} engines: {node: '>=4'}
dev: true dev: true
/resolve-pkg-maps@1.0.0:
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
dev: true
/resolve@1.22.1: /resolve@1.22.1:
resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==}
hasBin: true hasBin: true
@ -5007,7 +5091,7 @@ packages:
rollup: 3.26.2 rollup: 3.26.2
typescript: 5.1.6 typescript: 5.1.6
optionalDependencies: optionalDependencies:
'@babel/code-frame': 7.22.5 '@babel/code-frame': 7.22.10
dev: true dev: true
/rollup-plugin-esbuild@5.0.0(esbuild@0.17.19)(rollup@3.26.2): /rollup-plugin-esbuild@5.0.0(esbuild@0.17.19)(rollup@3.26.2):
@ -5492,6 +5576,17 @@ packages:
source-map-support: 0.5.21 source-map-support: 0.5.21
dev: true dev: true
/terser@5.19.2:
resolution: {integrity: sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==}
engines: {node: '>=10'}
hasBin: true
dependencies:
'@jridgewell/source-map': 0.3.5
acorn: 8.10.0
commander: 2.20.3
source-map-support: 0.5.21
dev: true
/test-exclude@6.0.0: /test-exclude@6.0.0:
resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -5609,6 +5704,17 @@ packages:
typescript: 5.1.6 typescript: 5.1.6
dev: true dev: true
/tsx@3.12.7:
resolution: {integrity: sha512-C2Ip+jPmqKd1GWVQDvz/Eyc6QJbGfE7NrR3fx5BpEHMZsEHoIxHL1j+lKdGobr8ovEyqeNkPLSKp6SCSOt7gmw==}
hasBin: true
dependencies:
'@esbuild-kit/cjs-loader': 2.4.2
'@esbuild-kit/core-utils': 3.1.0
'@esbuild-kit/esm-loader': 2.5.5
optionalDependencies:
fsevents: 2.3.2
dev: true
/type-check@0.3.2: /type-check@0.3.2:
resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
@ -5758,7 +5864,7 @@ packages:
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
dev: true dev: true
/vite-node@0.30.1(@types/node@16.18.38)(terser@5.18.2): /vite-node@0.30.1(@types/node@16.18.38)(terser@5.19.2):
resolution: {integrity: sha512-vTikpU/J7e6LU/8iM3dzBo8ZhEiKZEKRznEMm+mJh95XhWaPrJQraT/QsT2NWmuEf+zgAoMe64PKT7hfZ1Njmg==} resolution: {integrity: sha512-vTikpU/J7e6LU/8iM3dzBo8ZhEiKZEKRznEMm+mJh95XhWaPrJQraT/QsT2NWmuEf+zgAoMe64PKT7hfZ1Njmg==}
engines: {node: '>=v14.18.0'} engines: {node: '>=v14.18.0'}
hasBin: true hasBin: true
@ -5768,7 +5874,7 @@ packages:
mlly: 1.2.0 mlly: 1.2.0
pathe: 1.1.0 pathe: 1.1.0
picocolors: 1.0.0 picocolors: 1.0.0
vite: 4.3.1(@types/node@16.18.38)(terser@5.18.2) vite: 4.3.1(@types/node@16.18.38)(terser@5.19.2)
transitivePeerDependencies: transitivePeerDependencies:
- '@types/node' - '@types/node'
- less - less
@ -5779,7 +5885,7 @@ packages:
- terser - terser
dev: true dev: true
/vite@4.3.1(@types/node@16.18.38)(terser@5.18.2): /vite@4.3.1(@types/node@16.18.38)(terser@5.19.2):
resolution: {integrity: sha512-EPmfPLAI79Z/RofuMvkIS0Yr091T2ReUoXQqc5ppBX/sjFRhHKiPPF/R46cTdoci/XgeQpB23diiJxq5w30vdg==} resolution: {integrity: sha512-EPmfPLAI79Z/RofuMvkIS0Yr091T2ReUoXQqc5ppBX/sjFRhHKiPPF/R46cTdoci/XgeQpB23diiJxq5w30vdg==}
engines: {node: ^14.18.0 || >=16.0.0} engines: {node: ^14.18.0 || >=16.0.0}
hasBin: true hasBin: true
@ -5808,7 +5914,7 @@ packages:
esbuild: 0.17.19 esbuild: 0.17.19
postcss: 8.4.21 postcss: 8.4.21
rollup: 3.26.2 rollup: 3.26.2
terser: 5.18.2 terser: 5.19.2
optionalDependencies: optionalDependencies:
fsevents: 2.3.2 fsevents: 2.3.2
dev: true dev: true
@ -5850,7 +5956,7 @@ packages:
fsevents: 2.3.2 fsevents: 2.3.2
dev: true dev: true
/vitest@0.30.1(jsdom@21.1.0)(terser@5.18.2): /vitest@0.30.1(jsdom@21.1.0)(terser@5.19.2):
resolution: {integrity: sha512-y35WTrSTlTxfMLttgQk4rHcaDkbHQwDP++SNwPb+7H8yb13Q3cu2EixrtHzF27iZ8v0XCciSsLg00RkPAzB/aA==} resolution: {integrity: sha512-y35WTrSTlTxfMLttgQk4rHcaDkbHQwDP++SNwPb+7H8yb13Q3cu2EixrtHzF27iZ8v0XCciSsLg00RkPAzB/aA==}
engines: {node: '>=v14.18.0'} engines: {node: '>=v14.18.0'}
hasBin: true hasBin: true
@ -5905,8 +6011,8 @@ packages:
strip-literal: 1.0.1 strip-literal: 1.0.1
tinybench: 2.4.0 tinybench: 2.4.0
tinypool: 0.4.0 tinypool: 0.4.0
vite: 4.3.1(@types/node@16.18.38)(terser@5.18.2) vite: 4.3.1(@types/node@16.18.38)(terser@5.19.2)
vite-node: 0.30.1(@types/node@16.18.38)(terser@5.18.2) vite-node: 0.30.1(@types/node@16.18.38)(terser@5.19.2)
why-is-node-running: 2.2.2 why-is-node-running: 2.2.2
transitivePeerDependencies: transitivePeerDependencies:
- less - less

View File

@ -19,12 +19,7 @@ const entries = {
'@vue/compat': resolveEntryForPkg('vue-compat') '@vue/compat': resolveEntryForPkg('vue-compat')
} }
const nonSrcPackages = [ const nonSrcPackages = ['sfc-playground', 'template-explorer', 'dts-test']
'sfc-playground',
'size-check',
'template-explorer',
'dts-test'
]
for (const dir of dirs) { for (const dir of dirs) {
const key = `@vue/${dir}` const key = `@vue/${dir}`

View File

@ -27,6 +27,7 @@ import { cpus } from 'node:os'
import { createRequire } from 'node:module' import { createRequire } from 'node:module'
import { targets as allTargets, fuzzyMatchTarget } from './utils.js' import { targets as allTargets, fuzzyMatchTarget } from './utils.js'
import { scanEnums } from './const-enum.js' import { scanEnums } from './const-enum.js'
import prettyBytes from 'pretty-bytes'
const require = createRequire(import.meta.url) const require = createRequire(import.meta.url)
const args = minimist(process.argv.slice(2)) const args = minimist(process.argv.slice(2))
@ -38,18 +39,22 @@ const buildTypes = args.withTypes || args.t
const sourceMap = args.sourcemap || args.s const sourceMap = args.sourcemap || args.s
const isRelease = args.release const isRelease = args.release
const buildAllMatching = args.all || args.a const buildAllMatching = args.all || args.a
const writeSize = args.size
const commit = execa.sync('git', ['rev-parse', 'HEAD']).stdout.slice(0, 7) const commit = execa.sync('git', ['rev-parse', 'HEAD']).stdout.slice(0, 7)
const sizeDir = path.resolve('temp/size')
run() run()
async function run() { async function run() {
if (writeSize) await fs.mkdir(sizeDir, { recursive: true })
const removeCache = scanEnums() const removeCache = scanEnums()
try { try {
const resolvedTargets = targets.length const resolvedTargets = targets.length
? fuzzyMatchTarget(targets, buildAllMatching) ? fuzzyMatchTarget(targets, buildAllMatching)
: allTargets : allTargets
await buildAll(resolvedTargets) await buildAll(resolvedTargets)
checkAllSizes(resolvedTargets) await checkAllSizes(resolvedTargets)
if (buildTypes) { if (buildTypes) {
await execa( await execa(
'pnpm', 'pnpm',
@ -129,39 +134,52 @@ async function build(target) {
) )
} }
function checkAllSizes(targets) { async function checkAllSizes(targets) {
if (devOnly || (formats && !formats.includes('global'))) { if (devOnly || (formats && !formats.includes('global'))) {
return return
} }
console.log() console.log()
for (const target of targets) { for (const target of targets) {
checkSize(target) await checkSize(target)
} }
console.log() console.log()
} }
function checkSize(target) { async function checkSize(target) {
const pkgDir = path.resolve(`packages/${target}`) const pkgDir = path.resolve(`packages/${target}`)
checkFileSize(`${pkgDir}/dist/${target}.global.prod.js`) await checkFileSize(`${pkgDir}/dist/${target}.global.prod.js`)
if (!formats || formats.includes('global-runtime')) { if (!formats || formats.includes('global-runtime')) {
checkFileSize(`${pkgDir}/dist/${target}.runtime.global.prod.js`) await checkFileSize(`${pkgDir}/dist/${target}.runtime.global.prod.js`)
} }
} }
function checkFileSize(filePath) { async function checkFileSize(filePath) {
if (!existsSync(filePath)) { if (!existsSync(filePath)) {
return return
} }
const file = readFileSync(filePath) const file = await fs.readFile(filePath)
const minSize = (file.length / 1024).toFixed(2) + 'kb' const fileName = path.basename(filePath)
const gzipped = gzipSync(file) const gzipped = gzipSync(file)
const gzippedSize = (gzipped.length / 1024).toFixed(2) + 'kb' const brotli = brotliCompressSync(file)
const compressed = brotliCompressSync(file)
// @ts-ignore
const compressedSize = (compressed.length / 1024).toFixed(2) + 'kb'
console.log( console.log(
`${chalk.gray( `${chalk.gray(chalk.bold(fileName))} min:${prettyBytes(
chalk.bold(path.basename(filePath)) file.length
)} min:${minSize} / gzip:${gzippedSize} / brotli:${compressedSize}` )} / gzip:${prettyBytes(gzipped.length)} / brotli:${prettyBytes(
brotli.length
)}`
) )
if (writeSize)
await fs.writeFile(
path.resolve(sizeDir, `${fileName}.json`),
JSON.stringify({
file: fileName,
size: file.length,
gzip: gzipped.length,
brotli: brotli.length
}),
'utf-8'
)
} }

105
scripts/size-report.ts Normal file
View File

@ -0,0 +1,105 @@
import path from 'node:path'
import { markdownTable } from 'markdown-table'
import prettyBytes from 'pretty-bytes'
import { readdir } from 'node:fs/promises'
import { existsSync } from 'node:fs'
interface SizeResult {
size: number
gzip: number
brotli: number
}
interface BundleResult extends SizeResult {
file: string
}
type UsageResult = Record<string, SizeResult & { name: string }>
const currDir = path.resolve('temp/size')
const prevDir = path.resolve('temp/size-prev')
let output = '## Size Report\n\n'
const sizeHeaders = ['Size', 'Gzip', 'Brotli']
run()
async function run() {
await renderFiles()
await renderUsages()
process.stdout.write(output)
}
async function renderFiles() {
const filterFiles = (files: string[]) =>
files.filter(file => !file.startsWith('_'))
const curr = filterFiles(await readdir(currDir))
const prev = existsSync(prevDir) ? filterFiles(await readdir(prevDir)) : []
const fileList = new Set([...curr, ...prev])
const rows: string[][] = []
for (const file of fileList) {
const currPath = path.resolve(currDir, file)
const prevPath = path.resolve(prevDir, file)
const curr = await importJSON<BundleResult>(currPath)
const prev = await importJSON<BundleResult>(prevPath)
const fileName = curr?.file || prev?.file || ''
if (!curr) {
rows.push([`~~${fileName}~~`])
} else
rows.push([
fileName,
`${prettyBytes(curr.size)}${getDiff(curr.size, prev?.size)}`,
`${prettyBytes(curr.gzip)}${getDiff(curr.gzip, prev?.gzip)}`,
`${prettyBytes(curr.brotli)}${getDiff(curr.brotli, prev?.brotli)}`
])
}
output += '### Bundles\n\n'
output += markdownTable([['File', ...sizeHeaders], ...rows])
output += '\n\n'
}
async function renderUsages() {
const curr = (await importJSON<UsageResult>(
path.resolve(currDir, '_usages.json')
))!
const prev = await importJSON<UsageResult>(
path.resolve(prevDir, '_usages.json')
)
output += '\n### Usages\n\n'
const data = Object.values(curr)
.map(usage => {
const prevUsage = prev?.[usage.name]
const diffSize = getDiff(usage.size, prevUsage?.size)
const diffGzipped = getDiff(usage.gzip, prevUsage?.gzip)
const diffBrotli = getDiff(usage.brotli, prevUsage?.brotli)
return [
usage.name,
`${prettyBytes(usage.size)}${diffSize}`,
`${prettyBytes(usage.gzip)}${diffGzipped}`,
`${prettyBytes(usage.brotli)}${diffBrotli}`
]
})
.filter((usage): usage is string[] => !!usage)
output += `${markdownTable([['Name', ...sizeHeaders], ...data])}\n\n`
}
async function importJSON<T>(path: string): Promise<T | undefined> {
if (!existsSync(path)) return undefined
return (await import(path, { assert: { type: 'json' } })).default
}
function getDiff(curr: number, prev?: number) {
if (prev === undefined) return ''
const diff = curr - prev
if (diff === 0) return ''
const sign = diff > 0 ? '+' : ''
return ` (**${sign}${prettyBytes(diff)}**)`
}

99
scripts/usage-size.ts Normal file
View File

@ -0,0 +1,99 @@
import { mkdir, writeFile } from 'fs/promises'
import path from 'node:path'
import { rollup } from 'rollup'
import nodeResolve from '@rollup/plugin-node-resolve'
import { minify } from 'terser'
import replace from '@rollup/plugin-replace'
import { brotliCompressSync, gzipSync } from 'node:zlib'
const sizeDir = path.resolve('temp/size')
const entry = path.resolve('./packages/vue/dist/vue.runtime.esm-bundler.js')
interface Preset {
name: string
imports: string[]
}
const presets: Preset[] = [
{ name: 'createApp', imports: ['createApp'] },
{ name: 'createSSRApp', imports: ['createSSRApp'] },
{ name: 'defineCustomElement', imports: ['defineCustomElement'] },
{
name: 'overall',
imports: [
'createApp',
'ref',
'watch',
'Transition',
'KeepAlive',
'Suspense'
]
}
]
main()
async function main() {
const tasks: ReturnType<typeof generateBundle>[] = []
for (const preset of presets) {
tasks.push(generateBundle(preset))
}
const results = Object.fromEntries(
(await Promise.all(tasks)).map(r => [r.name, r])
)
await mkdir(sizeDir, { recursive: true })
await writeFile(
path.resolve(sizeDir, '_usages.json'),
JSON.stringify(results),
'utf-8'
)
}
async function generateBundle(preset: Preset) {
const id = 'virtual:entry'
const content = `export { ${preset.imports.join(', ')} } from '${entry}'`
const result = await rollup({
input: id,
plugins: [
{
name: 'usage-size-plugin',
resolveId(_id) {
if (_id === id) return id
return null
},
load(_id) {
if (_id === id) return content
}
},
nodeResolve(),
replace({
'process.env.NODE_ENV': '"production"',
__VUE_PROD_DEVTOOLS__: 'false',
__VUE_OPTIONS_API__: 'true',
preventAssignment: true
})
]
})
const generated = await result.generate({})
const bundled = generated.output[0].code
const minified = (
await minify(bundled, {
module: true,
toplevel: true
})
).code!
const size = minified.length
const gzip = gzipSync(minified).length
const brotli = brotliCompressSync(minified).length
return {
name: preset.name,
size,
gzip,
brotli
}
}

View File

@ -9,7 +9,6 @@
"packages/runtime-test", "packages/runtime-test",
"packages/template-explorer", "packages/template-explorer",
"packages/sfc-playground", "packages/sfc-playground",
"packages/size-check",
"packages/dts-test" "packages/dts-test"
] ]
} }