JavaScript Minification Guide — Terser and Webpack

JavaScript Minification Guide — Terser and Webpack

How JS minification works: Terser setup, Webpack production config, tree-shaking notes, and when an online minifier is enough.

25.10.2025
8 min read
Share this article:
JavaScript
Minification
Performance
Optimization
Tutorial

Why minify your JavaScript?

JavaScript minification removes whitespace and renames symbols to shrink file size before it reaches the browser. This guide covers Terser setup, Webpack production configuration, and how tree shaking complements minification — plus when a quick pass with an online JavaScript minifier is enough for smaller scripts.

60-80% reduction in JavaScript file sizes
200-500ms improvement in First Contentful Paint (FCP)
Significant savings on bandwidth and CDN costs
Better ranking in Google's Core Web Vitals
Optimized user experience, especially on mobile

Real-world performance impact

Concrete performance metrics

Here are real optimization data from an e-commerce project:

Performance dashboard showing before/after JavaScript minification metrics

Before optimization

File size
2.3 MB
Load time
3.2s
Bounce rate
68%
Conversion rate
2.1%

After optimization

File size
580 KB
Load time
1.8s
Bounce rate
42%
Conversion rate
3.7%
SEO impact

Google uses Core Web Vitals as a ranking factor. Minification directly improves these metrics:

LCP (Largest Contentful Paint): -40% on average
FID (First Input Delay): -60% thanks to less parsing
CLS (Cumulative Layout Shift): Reduced reflows
TTI (Time to Interactive): -35% waiting time

Setting up Terser

Basic installation and configuration

Terser is UglifyJS's successor, faster with better ES6+ support.

Installation

npm install --save-dev terser

Basic configuration

const terser = require('terser'); const result = await terser.minify(code, { compress: { drop_console: true, drop_debugger: true, pure_funcs: ['console.log'] }, mangle: { toplevel: true } });

Custom NPM script

// package.json { "scripts": { "build:js": "terser src/js/*.js -o dist/bundle.min.js", "build:prod": "npm run build:js && npm run build:css" } }
Advanced configuration for production

Optimal configuration for production environment with source maps and advanced optimizations.

Terser and webpack configuration visualization with settings controls

Configuration

const terserConfig = { compress: { arguments: true, booleans_as_integers: true, drop_console: true, drop_debugger: true, ecma: 2020, keep_infinity: true, passes: 3, pure_funcs: ['console.log', 'console.info'], unsafe: true, unsafe_arrows: true, unsafe_comps: true, unsafe_math: true }, mangle: { toplevel: true, properties: { regex: /^_/ } }, format: { comments: false, ecma: 2020 }, sourceMap: { filename: 'bundle.min.js', url: 'bundle.min.js.map' } };

Usage

const fs = require('fs'); const terser = require('terser'); async function minifyFile(inputPath, outputPath) { const code = fs.readFileSync(inputPath, 'utf8'); const result = await terser.minify(code, terserConfig); fs.writeFileSync(outputPath, result.code); if (result.map) { fs.writeFileSync(outputPath + '.map', result.map); } console.log(`Minified: ${inputPath} -> ${outputPath}`); console.log(`Size reduction: ${((code.length - result.code.length) / code.length * 100).toFixed(1)}%`); }

Alternative with UglifyJS

Installation and usage

UglifyJS remains a viable option, especially for older projects.

Installation

npm install --save-dev uglify-js

UglifyJS configuration

const UglifyJS = require('uglify-js'); const result = UglifyJS.minify(code, { compress: { drop_console: true, drop_debugger: true, pure_funcs: ['console.log'] }, mangle: true, output: { comments: false } });

Webpack Integration

Webpack configuration with Terser

Professional integration in a modern Webpack workflow.

Configuration Webpack

const TerserPlugin = require('terser-webpack-plugin'); module.exports = { mode: 'production', optimization: { minimize: true, minimizer: [ new TerserPlugin({ terserOptions: { compress: { drop_console: true, drop_debugger: true, pure_funcs: ['console.log'] }, mangle: { toplevel: true } }, extractComments: false }) ] } };

package.json

{ "scripts": { "build": "webpack --mode=production", "build:analyze": "webpack-bundle-analyzer dist/static/js/*.js" }, "devDependencies": { "terser-webpack-plugin": "^5.3.0", "webpack-bundle-analyzer": "^4.9.0" } }

Advanced techniques

Tree Shaking and Dead Code Elimination

Eliminate dead code and optimize imports for maximum minification.

Use specific ES6 imports: `import { specificFunction } from 'library'`
Avoid wildcard imports: `import * as utils from 'utils'`
Configure Webpack for tree shaking
Use pure function annotations
Polyfill optimization

Minimize the impact of polyfills on bundle size.

Before

import 'core-js/stable'; import 'regenerator-runtime/runtime'; // 50KB of loaded polyfills

After

// Conditional polyfills if (!Array.prototype.includes) { // Specific polyfill - 2KB } // On-demand loading

Monitoring and metrics

Measurement tools

Monitor the impact of your optimizations with these tools:

Bundle analyzer treemap visualization showing module sizes and dependencies
Lighthouse: Complete performance audit
WebPageTest: Detailed loading tests
Bundle Analyzer: Bundle size visualization
Core Web Vitals: Real-time Google metrics
Automatic alerts

Set up alerts to maintain performance.

Configuration GitHub Actions

// .github/workflows/performance.yml name: Performance Check on: [push] jobs: lighthouse: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Lighthouse CI run: | npm install -g @lhci/cli lhci autorun --upload.target=temporary-public-storage

Conclusion

JavaScript minification isn't an option, it's a necessity. With the right practices and tools, you can significantly reduce your file sizes while improving user experience and SEO.

Implement Terser in your build workflow
Set up automatic performance alerts
Regularly measure impact on Core Web Vitals
Test on different devices and connections
Document your optimizations for the team
Share this article
Share this article: