Imagine paying for a moving truck that's twice as large as you need, then filling half of it with furniture you'll never use in your new home. That's essentially what happens when your website contains unused JavaScript—you're downloading, processing, and storing code that never actually runs.
Unused JavaScript refers to any JavaScript code that's included in your website but never executed during a typical user visit. This includes functions that are never called, conditional code that's never triggered, or entire libraries where only a small fraction of the features are used.
JavaScript is the most expensive asset your website delivers, byte for byte. Unlike images or CSS, JavaScript must be downloaded, parsed, compiled, and executed before it can do its job. Each of these stages impacts performance:
The performance impact is significant. Studies have shown that every 100KB of JavaScript adds approximately 100ms of load time on midrange mobile devices. When you consider that many sites ship over 400KB of JavaScript (with up to 50% being unused), that's potentially adding half a second of delay for your mobile users—just in processing time.
Unused JavaScript accumulates in your codebase through several common pathways:
The problem compounds over time, especially in larger teams or long-running projects where developers may be hesitant to remove code they didn't write or don't fully understand.
A common pattern emerges in many websites: The initial product launches with lean, purpose-built JavaScript. As new features are added and different teams contribute to the codebase, the JavaScript bundle grows. When features are revised or removed, the old code often remains "just in case." After several years of development, it's not uncommon to find that 30-50% of a site's JavaScript is never executed.
Before you can optimize your JavaScript, you need to identify what's going unused. Several tools can help with this analysis:
When performing your analysis, be sure to:
This comprehensive approach will give you a more accurate picture of what JavaScript is truly necessary for your site's functionality.
Tree shaking is a technique that eliminates dead code by only including the parts of your dependencies that are actually used.
Simple fix: Use modern bundlers like Webpack, Rollup, or esbuild that support tree shaking, and ensure your code is using ES modules (import/export syntax) which enables better dead code elimination:
// Bad: Imports entire library
import _ from 'lodash';
// Good: Imports only what you need
import { debounce, throttle } from 'lodash-es';
// Even better: Import specific functions directly
import debounce from 'lodash/debounce';
import throttle from 'lodash/throttle';
Most modern JavaScript bundlers will automatically eliminate unused exports when properly configured, dramatically reducing your final bundle size.
Code splitting breaks your JavaScript into smaller chunks that are loaded only when needed, rather than forcing users to download everything upfront.
Simple fix: Use dynamic imports to load JavaScript on demand:
// Instead of loading everything upfront
import { heavyFeature } from './heavyFeature';
// Load it only when needed
button.addEventListener('click', async () => {
const { heavyFeature } = await import('./heavyFeature');
heavyFeature();
});
For React applications, you can use React.lazy and Suspense for component-level code splitting:
// Before: Importing directly
import HeavyComponent from './HeavyComponent';
// After: Code-split with dynamic import
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));
function MyComponent() {
return (
<React.Suspense fallback={<Spinner />}>
<HeavyComponent />
</React.Suspense>
);
}
Many popular JavaScript libraries have smaller alternatives that provide similar functionality with a fraction of the code.
Simple fix: Consider these lightweight alternatives to common libraries:
// Before: Using Moment.js (329KB)
import moment from 'moment';
const formattedDate = moment(date).format('YYYY-MM-DD');
// After: Using Day.js (2KB)
import dayjs from 'dayjs';
const formattedDate = dayjs(date).format('YYYY-MM-DD');
// Or just use native APIs when possible
const date = new Date();
const formattedDate = date.toISOString().split('T')[0]; // 'YYYY-MM-DD'
Third-party scripts for analytics, advertising, or marketing often add significant JavaScript bloat.
Simple fix: Implement these practices for third-party scripts:
defer
or async
attribute<!-- Before: Render-blocking script -->
<script src="https://third-party.com/analytics.js"></script>
<!-- After: Deferred loading -->
<script defer src="https://third-party.com/analytics.js"></script>
<!-- Even better: Load based on user interaction -->
<script>
// Only load when needed
document.getElementById('consent-button').addEventListener('click', () => {
const script = document.createElement('script');
script.src = 'https://third-party.com/analytics.js';
document.body.appendChild(script);
});
</script>
Modern bundlers have numerous optimization options that can dramatically reduce JavaScript size.
Simple fix: Ensure your Webpack, Rollup, or other bundler configuration is optimized for production:
// Example webpack.config.js optimization
module.exports = {
mode: 'production', // Enables built-in optimizations
optimization: {
usedExports: true, // Enables tree shaking
minimize: true, // Enables minification
splitChunks: { // Extracts common dependencies
chunks: 'all',
maxInitialRequests: 25,
minSize: 20000
}
}
};
Consider modern bundlers like esbuild or SWC which offer similar optimizations with significantly faster build times.
Preventing JavaScript bloat is easier than cleaning it up later. Set clear limits on bundle size and monitor increases over time.
Simple fix: Implement bundle size limits in your build process:
// Example webpack configuration with size limits
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
module.exports = {
plugins: [
new BundleAnalyzerPlugin(), // Visualize bundle size
new webpack.performance.hints('error'), // Fail build on size issues
],
performance: {
maxAssetSize: 200000, // 200KB limit per file
maxEntrypointSize: 250000, // 250KB total entry point size
}
};
You can also use tools like Lighthouse CI to automatically test bundle sizes during your continuous integration process.
When optimizing JavaScript, be aware of these common challenges:
What's happening: Code that appears unused might actually be necessary in certain user flows or scenarios that weren't tested during analysis.
Simple solution: Implement comprehensive testing across all user flows before and after optimization. Consider using feature flags to gradually remove code, allowing for quick rollback if issues are discovered:
// Approach with feature flags
if (featureFlags.useNewImplementation) {
// New optimized code
} else {
// Original code (can be removed after testing)
}
What's happening: Some JavaScript might be dynamically generated or evaluated at runtime, making it difficult for static analysis tools to determine if it's used.
Simple solution: Minimize the use of dynamic code generation (eval, new Function(), etc.) when possible. For necessary dynamic code, keep it separate from your main bundles to ensure optimization tools don't incorrectly remove dependencies.
What's happening: Tree shaking might remove code that has important side effects (like polyfills or self-registering modules).
Simple solution: Mark modules with side effects in your package.json to prevent them from being incorrectly tree-shaken:
// In package.json
{
"name": "your-package",
"sideEffects": [
"./src/polyfills.js",
"*.css"
]
}
What's happening: Frameworks like React, Angular, or Vue may have specific patterns that complicate dead code elimination.
Simple solution: Use framework-specific optimization tools and patterns:
The benefits of optimizing JavaScript can be substantial:
Metric | Before Optimization | After Optimization | Improvement |
---|---|---|---|
JavaScript Bundle Size | 450KB | 185KB | 59% reduction |
JavaScript Parse Time | 590ms | 240ms | 59% faster |
Time to Interactive | 4.8 seconds | 2.3 seconds | 2.5 seconds faster |
First Input Delay | 230ms | 85ms | 63% improvement |
Lighthouse Performance Score | 63 | 87 | 24 point increase |
These improvements are particularly significant on mobile devices and slower connections, where JavaScript processing can be the dominant performance bottleneck. By reducing unused JavaScript, you're not just saving bandwidth—you're freeing up CPU time that can be used to make your site more responsive to user interactions.
Companies across various industries have seen remarkable improvements from optimizing their JavaScript:
These examples demonstrate that JavaScript optimization can have a direct impact on key business metrics, not just technical performance scores. The less time users spend waiting for JavaScript to download and execute, the more time they spend engaging with your content and converting into customers.
Unused JavaScript is the silent performance killer that affects countless websites. Like carrying unnecessary weight on a long journey, it slows down every step of your users' experience—from initial loading to interactions throughout their visit.
The good news is that the tools and techniques for identifying and eliminating unused JavaScript have never been more accessible. Modern bundlers, frameworks, and development practices make it possible to deliver only the code that's actually needed, significantly improving performance without compromising functionality.
What makes JavaScript optimization particularly valuable is its compounding effect. When you reduce JavaScript payload, you're not just saving download time—you're also reducing parse time, compilation time, execution time, and memory usage. This creates a cascade of performance improvements that benefit every user, but especially those on mobile devices or slower connections.
Remember that JavaScript optimization isn't a one-time effort but an ongoing practice. As your website evolves, regularly audit your JavaScript to ensure you're not accumulating new sources of bloat. With thoughtful attention to your site's JavaScript footprint, you can deliver experiences that feel instantaneous rather than sluggish.
Greadme's easy-to-use tools can help you identify unused JavaScript on your website and provide simple, step-by-step instructions for optimization—even if you're not technically minded.
Optimize Your JavaScript Today