The problem
A React dashboard was shipping 8.4MB of JavaScript to users, causing 15-second load times on mobile networks. Chrome DevTools showed the main bundle at 8.4MB uncompressed, with 2.1MB gzipped. Lighthouse performance score was 12/100. The app imported entire libraries for single functions and loaded every possible component upfront. Mobile users experienced a 83% bounce rate due to the massive download.
How AI created this issue
Developers had been asking ChatGPT for React component examples. ChatGPT consistently imported entire libraries without considering bundle impact:
// ChatGPT's typical imports - bringing in everything
import * as _ from 'lodash';
import moment from 'moment';
import * as Icons from '@mui/icons-material';
import { Chart } from 'chart.js';
import * as d3 from 'd3';
import * as antd from 'antd';
import 'antd/dist/antd.css'; // 60KB just for styles
const Dashboard = () => {
// Using one function from 600KB lodash
const sortedData = _.orderBy(data, ['date'], ['desc']);
// Using one icon from 5MB icon set
const icon = ;
// Importing all of moment.js for simple date formatting
const formatted = moment(date).format('MMM DD');
// Loading all chart types when using only line charts
const chart = new Chart(ctx, { type: 'line', data });
// Every possible component loaded upfront
return (
{/* User might never visit most of these */}
);
};
ChatGPT never mentioned bundle size implications, tree shaking, or code splitting. It imported entire libraries for convenience, treating bundle size as irrelevant. The AI's examples worked perfectly in development but created a terrible user experience in production.
The solution
- Bundle analysis and targeted imports: Identified and fixed wasteful imports:
// Before: 600KB for one function import * as _ from 'lodash'; const sorted = _.orderBy(data, ['date'], ['desc']); // After: 2KB for just what we need import orderBy from 'lodash/orderBy'; const sorted = orderBy(data, ['date'], ['desc']); // Or native alternative: 0KB const sorted = [...data].sort((a, b) => new Date(b.date) - new Date(a.date) ); // Icon optimization // Before: 5MB of icons import * as Icons from '@mui/icons-material'; // After: 3KB for specific icon import DashboardIcon from '@mui/icons-material/Dashboard'; // Date handling // Before: 67KB moment.js import moment from 'moment'; // After: 2KB date-fns function import { format } from 'date-fns'; const formatted = format(date, 'MMM dd');
- Route-based code splitting: Lazy load components based on routes:
// Optimized with React.lazy and Suspense import { lazy, Suspense } from 'react'; import { Routes, Route } from 'react-router-dom'; // Only load components when needed const UserDashboard = lazy(() => import('./UserDashboard')); const AdminPanel = lazy(() => import('./AdminPanel')); const Analytics = lazy(() => import('./Analytics')); const Reports = lazy(() => import('./Reports')); const App = () => { return (
}> } /> } /> } /> } /> - Webpack optimization: Configured proper tree shaking and splitting:
// webpack.config.js optimizations module.exports = { optimization: { usedExports: true, sideEffects: false, splitChunks: { chunks: 'all', cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendors', priority: 10, }, common: { minChunks: 2, priority: 5, reuseExistingChunk: true, }, }, }, }, // Analyze bundle plugins: [ new BundleAnalyzerPlugin({ analyzerMode: 'static', openAnalyzer: false, }), ], };
- Component-level code splitting: Split heavy components that aren't always used
- Image optimization: Lazy loaded images and used next-gen formats
The results
- Bundle size reduced from 8.4MB to 1.8MB (79% reduction)
- Initial load: 2.1MB → 340KB (84% smaller)
- Time to Interactive: 15s → 2.8s on 3G
- Lighthouse score: 12 → 94
- Mobile bounce rate: 83% → 24%
- Load time on slow 3G: 45s → 7s
The team learned that AI examples optimize for clarity, not production performance. They now review all imports for bundle impact, use bundle analyzers religiously, and prefer native solutions over large libraries. Code that looks clean in development can be a disaster for users on real networks.
Ready to fix your codebase?
Let us analyze your application and resolve these issues before they impact your users.
Get Diagnostic Assessment →