From 05a26faa654759df21d5533ac61921e68f325fb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Fern=C3=A1ndez?= Date: Fri, 25 Oct 2024 09:34:12 +0000 Subject: [PATCH] feat(build): add size report --- frontend/vite.config.ts | 7 ++-- package-lock.json | 14 +++++++ packages/configs/eslint/index.ts | 1 + packages/vite-plugins/eslint.config.ts | 4 +- packages/vite-plugins/index.ts | 57 +++++++++++++++++++++++--- packages/vite-plugins/package.json | 1 + 6 files changed, 74 insertions(+), 10 deletions(-) diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 22bbbff5cba..eee8a41bddc 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -19,7 +19,7 @@ import { defineConfig } from 'vite'; * TODO: Replace with @jellyfin-vue/vite-plugins after https://github.com/vitejs/vite/issues/5370 * is fixed */ -import { JellyfinVueAnalysis, JellyfinVueChunking } from '../packages/vite-plugins'; +import { BundleAnalysis, BundleChunking, BundleSizeReport } from '../packages/vite-plugins'; import { entrypoints, localeFilesFolder, srcRoot } from './scripts/paths'; import virtualModules from './scripts/virtual-modules'; @@ -28,8 +28,9 @@ export default defineConfig({ base: './', cacheDir: '../node_modules/.cache/vite', plugins: [ - JellyfinVueAnalysis(), - JellyfinVueChunking(), + BundleAnalysis(), + BundleChunking(), + BundleSizeReport(), Virtual(virtualModules), VueRouter({ dts: './types/global/routes.d.ts', diff --git a/package-lock.json b/package-lock.json index 858292f8ccc..04089ab6a3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7504,6 +7504,19 @@ "node": ">= 0.8.0" } }, + "node_modules/pretty-bytes": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz", + "integrity": "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -10137,6 +10150,7 @@ "version": "0.0.1", "devDependencies": { "@jellyfin-vue/configs": "*", + "pretty-bytes": "6.1.1", "rollup-plugin-visualizer": "5.12.0", "vite": "5.4.9" } diff --git a/packages/configs/eslint/index.ts b/packages/configs/eslint/index.ts index 6002a81ab6b..cbbf2321226 100644 --- a/packages/configs/eslint/index.ts +++ b/packages/configs/eslint/index.ts @@ -4,3 +4,4 @@ export { getTSVueConfig } from './rules/typescript-vue'; export { json } from './rules/json'; export { getNodeFiles, getWorkerFiles } from './rules/env'; export { i18n } from './rules/i18n'; +export * from './shared'; diff --git a/packages/vite-plugins/eslint.config.ts b/packages/vite-plugins/eslint.config.ts index 096918e62d5..46b5079af20 100644 --- a/packages/vite-plugins/eslint.config.ts +++ b/packages/vite-plugins/eslint.config.ts @@ -1,8 +1,8 @@ import type { Linter } from 'eslint'; -import { getBaseConfig, getTSVueConfig, getNodeFiles } from '@jellyfin-vue/configs/eslint'; +import { getBaseConfig, getTSVueConfig, getNodeFiles, tsFiles } from '@jellyfin-vue/configs/eslint'; export default [ ...getBaseConfig('@jellyfin-vue/vite-plugins'), ...getTSVueConfig(false, import.meta.dirname), - ...getNodeFiles() + ...getNodeFiles(tsFiles) ] satisfies Linter.Config[]; diff --git a/packages/vite-plugins/index.ts b/packages/vite-plugins/index.ts index 6469bdc42dd..b6cdf42be2a 100644 --- a/packages/vite-plugins/index.ts +++ b/packages/vite-plugins/index.ts @@ -1,15 +1,18 @@ +import { basename } from 'node:path'; +import { glob, lstat } from 'node:fs/promises'; +import prettyBytes from 'pretty-bytes'; import { visualizer } from 'rollup-plugin-visualizer'; +import { normalizePath, type Plugin } from 'vite'; import type { RollupLog } from 'rollup'; -import type { Plugin } from 'vite'; /** * This plugin extracts the logic for the analyze commands, so the main Vite config is cleaner. */ -export function JellyfinVueAnalysis(): Plugin { +export function BundleAnalysis(): Plugin { const warnings: RollupLog[] = []; return { - name: 'Jellyfin_Vue:analysis', + name: 'Jellyfin_Vue:bundle_analysis', enforce: 'post', config: (_, env) => { if (env.mode === 'analyze:bundle') { @@ -54,9 +57,9 @@ export function JellyfinVueAnalysis(): Plugin { /** * Creates the Rollup's chunking strategy of the application (for code-splitting) */ -export function JellyfinVueChunking(): Plugin { +export function BundleChunking(): Plugin { return { - name: 'Jellyfin_Vue:chunking', + name: 'Jellyfin_Vue:bundle_chunking', config: () => ({ build: { rollupOptions: { @@ -93,3 +96,47 @@ export function JellyfinVueChunking(): Plugin { }) }; } + +/** + * Reports the total siz and also per file type + */ +export function BundleSizeReport(): Plugin { + const files = new Map(); + const sizes = new Map(); + let outDir: string; + let totalSize = 0; + const convert = (bytes: number) => prettyBytes(bytes, { minimumFractionDigits: 2 }); + + return { + name: 'Jellyfin_Vue:bundle_size_report', + apply: 'build', + closeBundle: async () => { + for await (const file of glob(`${outDir}/**/**`)) { + const stat = await lstat(file); + + if (stat.isFile()) { + const extension = basename(file).split('.').at(-1); + const filenum = files.get(extension!) ?? 0; + const size = sizes.get(extension!) ?? 0; + + files.set(extension!, filenum + 1); + sizes.set(extension!, size + stat.size); + totalSize += stat.size; + } + } + + for (const [key, val] of sizes) { + const num = files.get(key)!; + + console.info( + `There are ${num} ${key} ${num > 1 ? 'files' : 'file'} (${convert(val)})` + ); + } + + console.info(`Total size of the bundle: ${convert(totalSize)}`); + }, + configResolved: (config) => { + outDir = normalizePath(config.build.outDir); + } + }; +} diff --git a/packages/vite-plugins/package.json b/packages/vite-plugins/package.json index 3867489f289..43e6a6a7e8f 100644 --- a/packages/vite-plugins/package.json +++ b/packages/vite-plugins/package.json @@ -11,6 +11,7 @@ }, "devDependencies": { "@jellyfin-vue/configs": "*", + "pretty-bytes": "6.1.1", "rollup-plugin-visualizer": "5.12.0", "vite": "5.4.9" }