},
// Node scripts
{
- files: [
- 'scripts/**',
- '*.{js,ts}',
- 'packages/**/index.js',
- 'packages/size-check/**'
- ],
+ files: ['scripts/**', '*.{js,ts}', 'packages/**/index.js'],
rules: {
'no-restricted-globals': 'off',
'no-restricted-syntax': 'off'
- `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
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:
- name: Run type declaration tests
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
--- /dev/null
+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 -->'
"dev": "node scripts/dev.js",
"build": "node scripts/build.js",
"build-dts": "tsc -p tsconfig.build.json && rollup -c rollup.dts.config.js",
- "size": "run-s size-global size-baseline",
- "size-global": "node scripts/build.js vue runtime-dom -f global -p",
- "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": "run-s \"size-*\" && tsx scripts/usage-size.ts",
+ "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": "node scripts/build.js runtime-dom runtime-core reactivity shared -f esm-bundler",
"check": "tsc --incremental --noEmit",
"lint": "eslint --cache --ext .ts packages/*/{src,__tests__}/**.ts",
"format": "prettier --write --cache \"**/*.[tj]s?(x)\"",
"lint-staged": "^10.2.10",
"lodash": "^4.17.15",
"magic-string": "^0.30.0",
+ "markdown-table": "^3.0.3",
"marked": "^4.0.10",
"minimist": "^1.2.0",
"npm-run-all": "^4.1.5",
"prettier": "^3.0.1",
+ "pretty-bytes": "^6.1.1",
"pug": "^3.0.1",
"puppeteer": "~19.6.0",
"rollup": "^3.26.0",
"semver": "^7.3.2",
"serve": "^12.0.0",
"simple-git-hooks": "^2.8.1",
- "terser": "^5.15.1",
+ "terser": "^5.19.2",
"todomvc-app-css": "^2.3.0",
"tslib": "^2.5.0",
+ "tsx": "^3.12.7",
"typescript": "^5.1.6",
"vite": "^4.3.0",
"vitest": "^0.30.1"
+++ /dev/null
-# 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).
+++ /dev/null
-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}`)
+++ /dev/null
-{
- "name": "@vue/size-check",
- "version": "3.3.4",
- "private": true,
- "scripts": {
- "build": "vite build"
- },
- "dependencies": {
- "vue": "workspace:*"
- }
-}
+++ /dev/null
-import { h, createApp } from 'vue'
-
-// The bare minimum code required for rendering something to the screen
-createApp({
- render: () => h('div', 'hello world!')
-}).mount('#app')
+++ /dev/null
-export default {
- define: {
- __VUE_PROD_DEVTOOLS__: false,
- __VUE_OPTIONS_API__: true
- },
- build: {
- rollupOptions: {
- input: ['src/index.ts'],
- output: {
- entryFileNames: `[name].js`
- }
- },
- minify: 'terser'
- }
-}
magic-string:
specifier: ^0.30.0
version: 0.30.0
+ markdown-table:
+ specifier: ^3.0.3
+ version: 3.0.3
marked:
specifier: ^4.0.10
version: 4.3.0
prettier:
specifier: ^3.0.1
version: 3.0.1
+ pretty-bytes:
+ specifier: ^6.1.1
+ version: 6.1.1
pug:
specifier: ^3.0.1
version: 3.0.2
specifier: ^2.8.1
version: 2.8.1
terser:
- specifier: ^5.15.1
- version: 5.18.2
+ specifier: ^5.19.2
+ version: 5.19.2
todomvc-app-css:
specifier: ^2.3.0
version: 2.4.2
tslib:
specifier: ^2.5.0
version: 2.6.0
+ tsx:
+ specifier: ^3.12.7
+ version: 3.12.7
typescript:
specifier: ^5.1.6
version: 5.1.6
vite:
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:
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:
dependencies:
packages/shared: {}
- packages/size-check:
- dependencies:
- vue:
- specifier: workspace:*
- version: link:../vue
-
packages/template-explorer:
dependencies:
monaco-editor:
'@babel/highlight': 7.22.5
dev: true
- /@babel/code-frame@7.22.5:
- resolution: {integrity: sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==}
+ /@babel/code-frame@7.22.10:
+ resolution: {integrity: sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==}
engines: {node: '>=6.9.0'}
dependencies:
- '@babel/highlight': 7.22.5
+ '@babel/highlight': 7.22.10
+ chalk: 2.4.2
dev: true
/@babel/compat-data@7.21.0:
- supports-color
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:
resolution: {integrity: sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==}
engines: {node: '>=6.9.0'}
resolution: {integrity: sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==}
engines: {node: '>=6.9.0'}
dependencies:
- '@babel/code-frame': 7.18.6
+ '@babel/code-frame': 7.22.10
'@babel/parser': 7.21.3
'@babel/types': 7.21.3
dev: true
resolution: {integrity: sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==}
engines: {node: '>=6.9.0'}
dependencies:
- '@babel/code-frame': 7.22.5
+ '@babel/code-frame': 7.22.10
'@babel/generator': 7.21.3
'@babel/helper-environment-visitor': 7.18.9
'@babel/helper-function-name': 7.21.0
'@babel/helper-validator-identifier': 7.19.1
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:
resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==}
engines: {node: '>=12'}
'@jridgewell/trace-mapping': 0.3.17
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:
resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==}
engines: {node: '>=6.0.0'}
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:
resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
engines: {node: '>=6.0.0'}
/@jridgewell/source-map@0.3.5:
resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==}
dependencies:
- '@jridgewell/gen-mapping': 0.3.2
- '@jridgewell/trace-mapping': 0.3.17
+ '@jridgewell/gen-mapping': 0.3.3
+ '@jridgewell/trace-mapping': 0.3.19
dev: true
/@jridgewell/sourcemap-codec@1.4.14:
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:
resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==}
dependencies:
'@jridgewell/sourcemap-codec': 1.4.14
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:
resolution: {integrity: sha512-Lg3PnLp0QXpxwLIAuuJboLeRaIhrgJjeuh797QADg3xz8wGLugQOS5DpsE8A6i6Adgzf+bacllkKZG3J0tGfDw==}
dev: true
rollup: 3.26.2
serialize-javascript: 6.0.1
smob: 0.0.6
- terser: 5.18.2
+ terser: 5.19.2
dev: true
/@rollup/pluginutils@5.0.2(rollup@3.26.2):
istanbul-lib-source-maps: 4.0.1
istanbul-reports: 3.1.5
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:
- supports-color
dev: true
hasBin: 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:
resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==}
engines: {node: '>=0.4.0'}
get-intrinsic: 1.2.0
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:
resolution: {integrity: sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==}
engines: {node: '>=10'}
engines: {node: '>=8'}
dev: true
+ /markdown-table@3.0.3:
+ resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==}
+ dev: true
+
/marked@4.3.0:
resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==}
engines: {node: '>= 12'}
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'}
dependencies:
- '@babel/code-frame': 7.22.5
+ '@babel/code-frame': 7.22.10
error-ex: 1.3.2
json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.2.4
hasBin: 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:
resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
engines: {node: '>=4'}
dev: true
+ /resolve-pkg-maps@1.0.0:
+ resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
+ dev: true
+
/resolve@1.22.1:
resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==}
hasBin: true
rollup: 3.26.2
typescript: 5.1.6
optionalDependencies:
- '@babel/code-frame': 7.22.5
+ '@babel/code-frame': 7.22.10
dev: true
/rollup-plugin-esbuild@5.0.0(esbuild@0.17.19)(rollup@3.26.2):
source-map-support: 0.5.21
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:
resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==}
engines: {node: '>=8'}
typescript: 5.1.6
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:
resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==}
engines: {node: '>= 0.8.0'}
engines: {node: '>= 0.8'}
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==}
engines: {node: '>=v14.18.0'}
hasBin: true
mlly: 1.2.0
pathe: 1.1.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:
- '@types/node'
- less
- terser
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==}
engines: {node: ^14.18.0 || >=16.0.0}
hasBin: true
esbuild: 0.17.19
postcss: 8.4.21
rollup: 3.26.2
- terser: 5.18.2
+ terser: 5.19.2
optionalDependencies:
fsevents: 2.3.2
dev: true
fsevents: 2.3.2
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==}
engines: {node: '>=v14.18.0'}
hasBin: true
strip-literal: 1.0.1
tinybench: 2.4.0
tinypool: 0.4.0
- vite: 4.3.1(@types/node@16.18.38)(terser@5.18.2)
- vite-node: 0.30.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.19.2)
why-is-node-running: 2.2.2
transitivePeerDependencies:
- less
'@vue/compat': resolveEntryForPkg('vue-compat')
}
-const nonSrcPackages = [
- 'sfc-playground',
- 'size-check',
- 'template-explorer',
- 'dts-test'
-]
+const nonSrcPackages = ['sfc-playground', 'template-explorer', 'dts-test']
for (const dir of dirs) {
const key = `@vue/${dir}`
import { createRequire } from 'node:module'
import { targets as allTargets, fuzzyMatchTarget } from './utils.js'
import { scanEnums } from './const-enum.js'
+import prettyBytes from 'pretty-bytes'
const require = createRequire(import.meta.url)
const args = minimist(process.argv.slice(2))
const sourceMap = args.sourcemap || args.s
const isRelease = args.release
const buildAllMatching = args.all || args.a
+const writeSize = args.size
const commit = execa.sync('git', ['rev-parse', 'HEAD']).stdout.slice(0, 7)
+const sizeDir = path.resolve('temp/size')
+
run()
async function run() {
+ if (writeSize) await fs.mkdir(sizeDir, { recursive: true })
const removeCache = scanEnums()
try {
const resolvedTargets = targets.length
? fuzzyMatchTarget(targets, buildAllMatching)
: allTargets
await buildAll(resolvedTargets)
- checkAllSizes(resolvedTargets)
+ await checkAllSizes(resolvedTargets)
if (buildTypes) {
await execa(
'pnpm',
)
}
-function checkAllSizes(targets) {
+async function checkAllSizes(targets) {
if (devOnly || (formats && !formats.includes('global'))) {
return
}
console.log()
for (const target of targets) {
- checkSize(target)
+ await checkSize(target)
}
console.log()
}
-function checkSize(target) {
+async function checkSize(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')) {
- 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)) {
return
}
- const file = readFileSync(filePath)
- const minSize = (file.length / 1024).toFixed(2) + 'kb'
+ const file = await fs.readFile(filePath)
+ const fileName = path.basename(filePath)
+
const gzipped = gzipSync(file)
- const gzippedSize = (gzipped.length / 1024).toFixed(2) + 'kb'
- const compressed = brotliCompressSync(file)
- // @ts-ignore
- const compressedSize = (compressed.length / 1024).toFixed(2) + 'kb'
+ const brotli = brotliCompressSync(file)
+
console.log(
- `${chalk.gray(
- chalk.bold(path.basename(filePath))
- )} min:${minSize} / gzip:${gzippedSize} / brotli:${compressedSize}`
+ `${chalk.gray(chalk.bold(fileName))} min:${prettyBytes(
+ file.length
+ )} / 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'
+ )
}
--- /dev/null
+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)}**)`
+}
--- /dev/null
+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
+ }
+}
"packages/runtime-test",
"packages/template-explorer",
"packages/sfc-playground",
- "packages/size-check",
"packages/dts-test"
]
}