usage-size.ts 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import { mkdir, writeFile } from 'node:fs/promises'
  2. import path from 'node:path'
  3. import { rollup } from 'rollup'
  4. import nodeResolve from '@rollup/plugin-node-resolve'
  5. import { minify } from 'terser'
  6. import replace from '@rollup/plugin-replace'
  7. import { brotliCompressSync, gzipSync } from 'node:zlib'
  8. const sizeDir = path.resolve('temp/size')
  9. const entry = path.resolve('./packages/vue/dist/vue.runtime.esm-bundler.js')
  10. interface Preset {
  11. name: string
  12. imports: string[]
  13. }
  14. const presets: Preset[] = [
  15. { name: 'createApp', imports: ['createApp'] },
  16. { name: 'createSSRApp', imports: ['createSSRApp'] },
  17. { name: 'defineCustomElement', imports: ['defineCustomElement'] },
  18. {
  19. name: 'overall',
  20. imports: [
  21. 'createApp',
  22. 'ref',
  23. 'watch',
  24. 'Transition',
  25. 'KeepAlive',
  26. 'Suspense',
  27. ],
  28. },
  29. ]
  30. main()
  31. async function main() {
  32. const tasks: ReturnType<typeof generateBundle>[] = []
  33. for (const preset of presets) {
  34. tasks.push(generateBundle(preset))
  35. }
  36. const results = Object.fromEntries(
  37. (await Promise.all(tasks)).map(r => [r.name, r]),
  38. )
  39. await mkdir(sizeDir, { recursive: true })
  40. await writeFile(
  41. path.resolve(sizeDir, '_usages.json'),
  42. JSON.stringify(results),
  43. 'utf-8',
  44. )
  45. }
  46. async function generateBundle(preset: Preset) {
  47. const id = 'virtual:entry'
  48. const content = `export { ${preset.imports.join(', ')} } from '${entry}'`
  49. const result = await rollup({
  50. input: id,
  51. plugins: [
  52. {
  53. name: 'usage-size-plugin',
  54. resolveId(_id) {
  55. if (_id === id) return id
  56. return null
  57. },
  58. load(_id) {
  59. if (_id === id) return content
  60. },
  61. },
  62. nodeResolve(),
  63. replace({
  64. 'process.env.NODE_ENV': '"production"',
  65. __VUE_PROD_DEVTOOLS__: 'false',
  66. __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'false',
  67. __VUE_OPTIONS_API__: 'true',
  68. preventAssignment: true,
  69. }),
  70. ],
  71. })
  72. const generated = await result.generate({})
  73. const bundled = generated.output[0].code
  74. const minified = (
  75. await minify(bundled, {
  76. module: true,
  77. toplevel: true,
  78. })
  79. ).code!
  80. const size = minified.length
  81. const gzip = gzipSync(minified).length
  82. const brotli = brotliCompressSync(minified).length
  83. return {
  84. name: preset.name,
  85. size,
  86. gzip,
  87. brotli,
  88. }
  89. }