From 2b316de17e95b83e489b19c2c49ada4329a5b5d8 Mon Sep 17 00:00:00 2001 From: denis0001-dev Date: Sun, 2 Nov 2025 16:52:29 +0300 Subject: [PATCH] Optimize production build Change Vite cache dir Change Vite cache dir Optimize bundle size Fix Babel large file warning --- frontend/electron/main.ts | 2 +- frontend/plugins/optimizeCssModules.ts | 71 ++++++++++++++++++++++++++ frontend/src/utils/material.tsx | 6 +-- frontend/vite.config.ts | 23 +++++++-- 4 files changed, 92 insertions(+), 10 deletions(-) create mode 100644 frontend/plugins/optimizeCssModules.ts diff --git a/frontend/electron/main.ts b/frontend/electron/main.ts index 021b217..dc58b07 100644 --- a/frontend/electron/main.ts +++ b/frontend/electron/main.ts @@ -1,5 +1,5 @@ import { app, BrowserWindow, Notification, ipcMain } from 'electron'; -import path from "node:path"; +import path from "path"; import type { NotificationShowOptions } from '../electron.d.ts'; let mainWindow: BrowserWindow | null = null; diff --git a/frontend/plugins/optimizeCssModules.ts b/frontend/plugins/optimizeCssModules.ts new file mode 100644 index 0000000..2aa2a88 --- /dev/null +++ b/frontend/plugins/optimizeCssModules.ts @@ -0,0 +1,71 @@ +import type { Plugin, UserConfig } from 'vite'; + +const DEFAULT_DICTIONARY = '_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + +function counter(dictionary: string = DEFAULT_DICTIONARY) { + const sequence: string[] = [dictionary[0]]; + return () => { + const str = sequence.join(''); + let carry = 0; + for (let i = 0; i < sequence.length; i++) { + const index = dictionary.indexOf(sequence[i]) + carry + 1; + if (index < dictionary.length) { + sequence[i] = dictionary[index]; + /** + * Make sure the following rules are not violated: + * 1. The first character cannot be a number + * 2. The second character cannot be a number if the first is a dash + * 3. The dash cannot be the only character + * + * https://www.w3.org/TR/CSS21/syndata.html#characters + */ + const [c1, c2] = sequence; + if ( + (c1 >= '0' && c1 <= '9') || + (c1 === '-' && (c2 >= '0' && c2 <= '9')) || + (c1 === '-' && sequence.length === 1) + ) { + i--; + continue; + } + carry = 0; + break; + } else { + sequence[i] = dictionary[0]; + carry = 1; + } + } + if (carry) { + sequence.push(dictionary[0]); + } + return str; + }; +}; + +export interface OptimizeCssModuleOptions { + dictionary?: string; +} + +export function optimizeCssModules(options?: OptimizeCssModuleOptions): Plugin { + const next = counter(options?.dictionary); + const map: Map = new Map(); + + return { + name: 'optimize-css-modules', + apply: 'build', + config: () => ({ + css: { + modules: { + generateScopedName: (name: string, fileName: string) => { + const key = fileName + name; + let hash = map.get(key); + if (!hash) { + map.set(key, (hash = next())); + } + return hash; + } + } + } + }) + }; +}; \ No newline at end of file diff --git a/frontend/src/utils/material.tsx b/frontend/src/utils/material.tsx index 2341733..bd698fc 100644 --- a/frontend/src/utils/material.tsx +++ b/frontend/src/utils/material.tsx @@ -13,18 +13,16 @@ import 'mdui/components/list-item'; import 'mdui/components/bottom-app-bar'; import 'mdui/components/button-icon'; import 'mdui/components/fab'; -import 'mdui/components/dialog'; import 'mdui/components/button'; import 'mdui/components/text-field'; import 'mdui/components/button-icon'; -import 'mdui/components/top-app-bar'; -import 'mdui/components/top-app-bar-title'; import 'mdui/components/switch'; import 'mdui/components/chip'; +import 'mdui/components/badge'; import "mdui/mdui.css"; import 'mdui/components/circular-progress'; -import { setColorScheme } from 'mdui/functions/setColorScheme.js'; +import { setColorScheme } from 'mdui/functions/setColorScheme'; import type { ChangeEventHandler, ComponentProps, ComponentPropsWithoutRef, FormEventHandler, Ref } from 'react'; import type { TextField } from 'mdui/components/text-field'; import type { Switch } from 'mdui/components/switch'; diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index ad375a1..ab5318a 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -6,14 +6,21 @@ import react from "@vitejs/plugin-react"; import path from "path"; import { visualizer } from 'rollup-plugin-visualizer'; import sassDts from 'vite-plugin-sass-dts'; +import { optimizeCssModules } from './plugins/optimizeCssModules'; -const outDir = process.env.VITE_ELECTRON ? "build/electron" : "build/normal"; +const currentDir = path.resolve(__dirname); +const outDir = process.env.VITE_ELECTRON ? `${currentDir}/build/electron` : `${currentDir}/build/normal`; const plugins: PluginOption[] = [ - react(), + react({ + babel: { + compact: false + } + }), sassDts({ enabledMode: ['development', 'production'] }), + optimizeCssModules(), createHtmlPlugin({ minify: { collapseWhitespace: true, @@ -40,7 +47,7 @@ if (process.env.VITE_ELECTRON) { entry: "electron/main.ts", vite: { build: { - outDir: "build/electron/core" + outDir: `${outDir}/core` } } }, @@ -48,7 +55,7 @@ if (process.env.VITE_ELECTRON) { input: "frontend/electron/preload.ts", vite: { build: { - outDir: "build/electron/core" + outDir: `${outDir}/core` } } }, @@ -79,6 +86,11 @@ export default defineConfig({ allowedHosts: ["beta.fromchat.ru"] }, appType: "spa", + optimizeDeps: { + esbuildOptions: { + target: "es2022" + } + }, css: { postcss: { plugins: [autoprefixer()] @@ -99,5 +111,6 @@ export default defineConfig({ assetsInlineLimit: 0, outDir: `${outDir}/dist`, chunkSizeWarningLimit: 1024 - } + }, + cacheDir: `${currentDir}/build/cache` }); \ No newline at end of file