Chunks we may build react app locally with npm run build and check sizes of bundled chunks in general application is broken into numerous tiny files which are being loaded in parallel and big blocking files are not good vite-bundle-visualizer we may check the content of bundled chunks with vite-bundle-visualizer package no need even to install it into a project, just run npx vite-bundle-visualizer we may see that all purple area is one blocking gzipped 1.3mb file manualChunks we may break the file into multiple chunks manually and they will load by browser in parallel can be done in vite's configuration by adding the property manualChunks to rollup bundler settings /// <reference types="vitest" /> /// <reference types="vite/client" /> import { defineConfig, loadEnv } from 'vite' import react from '@vitejs/plugin-react' import tsconfigPaths from 'vite-tsconfig-paths' import basicSsl from '@vitejs/plugin-basic-ssl' // https://vitejs.dev/config/ export default defineConfig({ base: './', server: { host: 'local.q.com', port: 8443, // https: true }, plugins: [ react({ // to show readable class names in styled components with vite // https://github.com/styled-components/babel-plugin-styled-components/issues/350#issuecomment-979873241 jsxImportSource: '@emotion/react', babel: { plugins: [ [ // 'babel-plugin-styled-components', '@emotion/babel-plugin', { displayName: true, fileName: true, }, ], // https://github.com/preactjs/signals/tree/main/packages/react#react-integration ["module:@preact/signals-react-transform"], ], }, }), // https://github.com/aleclarson/vite-tsconfig-paths tsconfigPaths(), basicSsl() ], build: { target: 'esnext', outDir: 'build', rollupOptions: { output: { // https://rollupjs.org/configuration-options/#output-manualchunks manualChunks: (id) => { if (id.includes('node_modules/@ag-grid-community')) return '@ag-grid-community' if (id.includes('node_modules/@ag-grid-enterprise')) return '@ag-grid-enterprise' if (id.includes('node_modules/@heeros')) return 'heeros' if (id.includes('node_modules/@mui')) return 'mui' if (id.includes('node_modules/@tanstack')) return 'tanstack' if (id.includes('node_modules/@aws')) return '@aws' if (id.includes('node_modules/mixpanel')) return 'mixpanel' if (id.includes('node_modules/pdfjs')) return 'pdfjs' if (id.includes('node_modules/framer-motion')) return 'framer-motion' if (id.includes('node_modules/i18n')) return 'i18n' } } } }, // 'pdfjs-dist' throws an error // https://github.com/storybookjs/storybook/issues/22223 // ERROR: Top-level await is not available in the configured target environment optimizeDeps: { esbuildOptions: { target: "esnext", }, }, test: { environment: "jsdom" }, }) id parameter is the folder path in your project and we can group modules in separate files by returning chunk name and eventually get smaller chunks More advanced logic we may also apply some custom automatic logic for manual splitting import fs from 'fs'; export default { input: 'src/index.js', output: { dir: 'dist', format: 'es', manualChunks: (id) => { // Estimate the size of the module based on the size of the file const fileSize = fs.statSync(id).size; // Get the size of the file in bytes const estimatedSizeInKB = fileSize / 1024; // Convert bytes to KB if (estimatedSizeInKB <= 500) { return null; // Keep in the main bundle } else { // Split into a separate chunk return `chunk-${id}`; } }, }, };