From 60ebc66c887fe27dbbc8a353e29fe92a06fd7667 Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Thu, 18 May 2023 21:51:52 -0700 Subject: [PATCH] fix: Manually chunk dependencies for improved load times MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BEFORE: ```txt > open-energy-dashboard@0.8.0 client:build > vite --config ./src/vite.config.js build vite v4.2.2 building for production... ✓ 1357 modules transformed. server/public/index.html 0.89 kB server/public/assets/index-77128f32.css 160.91 kB │ gzip: 24.60 kB server/public/assets/index-a8f247e1.js 4,886.14 kB │ gzip: 1,494.16 kB ``` AFTER: ```txt vite v4.2.2 building for production... ✓ 1357 modules transformed. server/public/index.html 1.49 kB server/public/assets/index-99e4836c.css 6.24 kB │ gzip: 1.61 kB server/public/assets/bootstrap-2823c1df.css 154.67 kB │ gzip: 23.17 kB server/public/assets/react-select-1d923cf1.js 56.04 kB │ gzip: 19.32 kB server/public/assets/moment-fbc5633a.js 59.89 kB │ gzip: 19.37 kB server/public/assets/reactstrap-07f50228.js 72.08 kB │ gzip: 20.20 kB server/public/assets/lodash-42c17880.js 72.53 kB │ gzip: 26.73 kB server/public/assets/react-dom-657fb334.js 119.15 kB │ gzip: 38.50 kB server/public/assets/index-1836615c.js 319.62 kB │ gzip: 67.34 kB server/public/assets/vendor-144eeccd.js 446.03 kB │ gzip: 141.38 kB server/public/assets/plotly.js-e0e78342.js 3,711.26 kB │ gzip: 1,150.87 kB ``` --- src/vite.config.js | 49 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/src/vite.config.js b/src/vite.config.js index 5e4d70c22..fc40a6a54 100644 --- a/src/vite.config.js +++ b/src/vite.config.js @@ -1,14 +1,57 @@ -import { defineConfig } from 'vite' +import { defineConfig, splitVendorChunkPlugin } from 'vite' import react from '@vitejs/plugin-react' import commonjs from 'vite-plugin-commonjs' export default defineConfig({ root: './src', + publicDir: './client/public', + + plugins: [ + react(), + commonjs(), + /** + * splitVendorChunkPlugin automatically creates a vendor chunk for all used node_modules (that are + * not specified in manualChunks() below) + */ + splitVendorChunkPlugin()], build: { outDir: './server/public', + rollupOptions: { + output: { + /** + * Unfortunately, it seems as through the default chunking strategy is no chunking + * strategy: the final build contains a single and massive bundle.js and bundle.css file. + * This is bad for page loads, so manually chunk to fix this. + */ + manualChunks(/** @type {string} */ id) { + const afterNodeModules = id.toString().split('node_modules/')[1] + + /** + * If afterNodeModules is undefined, then the file is not in node_modules - it's + * a local file. For now, don't chunk local files. TODO: route-based chunking + */ + if (!afterNodeModules) return + + const moduleName = afterNodeModules.split('/')[0] + const fileName = afterNodeModules.split('/').reverse()[0] + + // For css, simply make Bootstrap its own bundle + if (fileName.includes('.css')) { + if (/^(bootstrap)$/u.test(moduleName)) { + return moduleName + } + } + + // For js, only make the largest libraries their own chunks (>=50kB) + if (fileName.includes('.js')) { + if(/^(plotly.js|react-dom|reactstrap|lodash|moment|react-select)$/u.test(moduleName)) { + return moduleName + } + } + } + } + } }, - publicDir: './client/public', - plugins: [react(), commonjs()], server: { port: 9229, proxy: {