Skip to main content

πŸ“¦ What is a Bundler?

πŸ“– Definition​

A Bundler is a tool that combines multiple files and modules into one or a few files. It optimizes various resources such as JavaScript, CSS, and images, and transforms them to be efficiently loaded in browsers. Representative examples include Webpack, Vite, Rollup, and Parcel.

🎯 Understanding Through Analogies​

Moving Company Analogy​

Comparing a bundler to a moving company:

Before Moving (Before Bundling)
Household Items:
β”œβ”€ Living Room: Sofa, TV, Table (JavaScript files)
β”œβ”€ Bedroom: Bed, Desk, Wardrobe (CSS files)
β”œβ”€ Kitchen: Refrigerator, Dishes (Image files)
└─ Bathroom: Sink, Towels (Font files)

Problems:
- Moving items one by one = Inefficient
- Unorganized = Hard to find
- Waste of space = Slow

Moving Company (Bundler):
1. Categorize items
2. Pack in boxes
3. Label
4. Efficient arrangement
5. Load on truck

After Moving (After Bundling):
πŸ“¦ Box 1: Furniture (main.js)
πŸ“¦ Box 2: Kitchen items (styles.css)
πŸ“¦ Box 3: Small items (assets)

Advantages:
- Transport all at once = Fast
- Organized = Easy to find
- Space efficient = Optimized

Library Analogy​

Scattered Books (Before Bundling)
- 1000 books scattered on the floor
- Hard to find
- Waste of space
- Dust accumulation

Library System (Bundler)
1. Categorize by subject
2. Organize on shelves
3. Create index
4. Apply labels

Organized Library (After Bundling)
- Shelves by category
- Fast search
- Space efficiency
- Clean management

Cooking Preparation Analogy​

Before Preparing Ingredients (Before Bundling)
Entire Refrigerator:
- 20 types of vegetables
- 5 types of meat
- 30 types of seasonings
- All in different locations

Chef (Bundler):
1. Check today's menu
2. Select only necessary ingredients
3. Prepare
4. Arrange in cooking order

Mise en Place (After Bundling)
- Only necessary ingredients organized
- Ready to cook immediately
- Efficient
- Time-saving

βš™οΈ How It Works​

1. Need for Module System​

// Problem: Global pollution
// Loading multiple scripts in HTML
<!DOCTYPE html>
<html>
<head>
<script src="utils.js"></script>
<script src="math.js"></script>
<script src="app.js"></script>
</head>
</html>

// utils.js
var name = 'Utils';
function log(msg) {
console.log(msg);
}

// math.js
var name = 'Math'; // ❌ Conflict! Overwrites name from utils.js
function add(a, b) {
return a + b;
}

// app.js
console.log(name); // 'Math' is printed (expected: 'Utils')
log('Hello'); // Works but unclear where the function comes from

// Problems:
// 1. Variable name conflicts
// 2. Dependency order matters
// 3. Global namespace pollution
// 4. Many HTTP requests for many files
// 5. Loads unused code

2. Module System​

// βœ… ES6 Modules (ESM)
// utils.js
export const name = 'Utils';
export function log(msg) {
console.log(msg);
}

// math.js
export const name = 'Math';
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}

// app.js
import { log } from './utils.js';
import { add, subtract } from './math.js';

log('Hello'); // Clear!
console.log(add(1, 2)); // 3

// Advantages:
// - Namespace isolation
// - Explicit dependencies
// - Tree Shaking possible
// - Easy to reuse

// But problems:
// 1. Not supported in older browsers
// 2. Still many HTTP requests
// 3. Slow module resolution

// β†’ Bundler needed!

3. Bundler Operation Process​

// Step 1: Entry Point
// webpack.config.js
module.exports = {
entry: './src/index.js' // Starting point
};

// Step 2: Dependency Graph
// index.js
import { render } from './render.js';
import './styles.css';
import logo from './logo.png';

// render.js
import { createElement } from './dom.js';
import { formatDate } from './utils.js';

// dom.js
import { debounce } from './helpers.js';

// Dependency Tree:
index.js
β”œβ”€ render.js
β”‚ β”œβ”€ dom.js
β”‚ β”‚ └─ helpers.js
β”‚ └─ utils.js
β”œβ”€ styles.css
└─ logo.png

// Step 3: Loaders (Transformation)
// - CSS β†’ JavaScript
// - SCSS β†’ CSS β†’ JavaScript
// - Images β†’ Base64 or file
// - TypeScript β†’ JavaScript
// - JSX β†’ JavaScript

// Step 4: Plugins (Additional tasks)
// - HTML generation
// - Code minification
// - Environment variable injection
// - Sourcemap generation

// Step 5: Output
// dist/
// β”œβ”€ bundle.js (all JS combined)
// β”œβ”€ styles.css (extracted CSS)
// └─ logo.abc123.png (hash added)

// Result:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="dist/styles.css">
</head>
<body>
<script src="dist/bundle.js"></script>
<!-- One file! -->
</body>
</html>

4. Tree Shaking​

// math.js
export function add(a, b) {
return a + b;
}

export function subtract(a, b) {
return a - b;
}

export function multiply(a, b) {
return a * b;
}

export function divide(a, b) {
return a / b;
}

// app.js
import { add, subtract } from './math.js';

console.log(add(1, 2)); // Used
console.log(subtract(5, 3)); // Used

// multiply and divide are not used!

// Bundler (After Tree Shaking)
// bundle.js
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
console.log(add(1, 2));
console.log(subtract(5, 3));

// multiply and divide are removed!
// Bundle size reduced!

// Tree Shaking Requirements:
// 1. Use ES6 Modules
// 2. Code without side effects
// 3. Production mode

5. Code Splitting​

// Code Splitting

// ❌ All code in one bundle
import Home from './pages/Home';
import About from './pages/About';
import Dashboard from './pages/Dashboard';
import Admin from './pages/Admin';

// bundle.js (2MB) - Too large!

// βœ… Split with dynamic import
// app.js
const routes = {
'/': () => import('./pages/Home'),
'/about': () => import('./pages/About'),
'/dashboard': () => import('./pages/Dashboard'),
'/admin': () => import('./pages/Admin')
};

// Router
async function navigate(path) {
const loadPage = routes[path];
if (loadPage) {
const module = await loadPage();
module.default.render();
}
}

// Result:
// bundle.js (100KB) - Base code
// home.chunk.js (50KB) - Home page only
// about.chunk.js (30KB) - About page only
// dashboard.chunk.js (200KB) - Dashboard only
// admin.chunk.js (500KB) - Admin only

// Advantages:
// - Fast initial loading
// - Load only when needed
// - Users feel it's faster

// Code Splitting in React
import { lazy, Suspense } from 'react';

const Dashboard = lazy(() => import('./pages/Dashboard'));

function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Dashboard />
</Suspense>
);
}

πŸ’‘ Real Examples​

Webpack Configuration​

// webpack.config.js (basic)
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
// 1. Entry point
entry: './src/index.js',

// 2. Output
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.[contenthash].js', // Hash for cache invalidation
clean: true // Clean dist folder before build
},

// 3. Mode
mode: 'production', // or 'development'

// 4. Loaders (file transformation)
module: {
rules: [
// JavaScript (Babel)
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
}
},

// CSS
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader, // Extract CSS file
'css-loader' // CSS β†’ JS
]
},

// SCSS
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader' // SCSS β†’ CSS
]
},

// Images
{
test: /\.(png|jpg|gif|svg)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024 // Inline as Base64 if under 8KB
}
}
},

// Fonts
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
type: 'asset/resource'
}
]
},

// 5. Plugins (additional features)
plugins: [
// HTML generation
new HtmlWebpackPlugin({
template: './src/index.html',
minify: true
}),

// CSS file extraction
new MiniCssExtractPlugin({
filename: 'styles.[contenthash].css'
})
],

// 6. Dev server
devServer: {
static: './dist',
port: 3000,
hot: true, // Hot Module Replacement
open: true
},

// 7. Sourcemap (debugging)
devtool: 'source-map',

// 8. Optimization
optimization: {
splitChunks: {
chunks: 'all', // Code splitting
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 10
}
}
}
}
};

// package.json
{
"scripts": {
"dev": "webpack serve --mode development",
"build": "webpack --mode production"
}
}

// Usage:
// npm run dev - Run development server
// npm run build - Production build

Vite Configuration​

// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';

export default defineConfig({
// 1. Plugins
plugins: [react()],

// 2. Aliases
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@components': path.resolve(__dirname, './src/components'),
'@utils': path.resolve(__dirname, './src/utils')
}
},

// 3. Dev server
server: {
port: 3000,
open: true,
cors: true,
proxy: {
// API proxy
'/api': {
target: 'http://localhost:5000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
},

// 4. Build
build: {
outDir: 'dist',
assetsDir: 'assets',
sourcemap: true,

// Chunk size limit
chunkSizeWarningLimit: 1000,

// Rollup options
rollupOptions: {
output: {
// Manual chunk splitting
manualChunks: {
'react-vendor': ['react', 'react-dom'],
'router': ['react-router-dom'],
'ui': ['@mui/material']
}
}
},

// Minification
minify: 'terser',
terserOptions: {
compress: {
drop_console: true // Remove console.log
}
}
},

// 5. CSS
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/variables.scss";`
}
},
modules: {
localsConvention: 'camelCase'
}
},

// 6. Environment variables
define: {
__APP_VERSION__: JSON.stringify('1.0.0')
}
});

// package.json
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
}
}

// Vite's advantages:
// 1. Very fast dev server (uses ESM)
// 2. Instant start (no bundling)
// 3. Ultra-fast HMR
// 4. Simple configuration
// 5. Modern defaults

Rollup Configuration (for libraries)​

// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import babel from '@rollup/plugin-babel';
import { terser } from 'rollup-plugin-terser';
import pkg from './package.json';

export default {
// Entry point
input: 'src/index.js',

// Multiple outputs (multiple formats)
output: [
// CommonJS (Node.js)
{
file: pkg.main,
format: 'cjs',
sourcemap: true
},

// ES Module (for bundlers)
{
file: pkg.module,
format: 'esm',
sourcemap: true
},

// UMD (for browsers)
{
file: pkg.browser,
format: 'umd',
name: 'MyLibrary',
sourcemap: true,
globals: {
react: 'React'
}
}
],

// External dependencies (not included in bundle)
external: ['react', 'react-dom'],

// Plugins
plugins: [
// Resolve Node modules
resolve({
extensions: ['.js', '.jsx']
}),

// CommonJS β†’ ESM
commonjs(),

// Babel transformation
babel({
exclude: 'node_modules/**',
babelHelpers: 'bundled',
presets: ['@babel/preset-env', '@babel/preset-react']
}),

// Minification
terser()
]
};

// package.json
{
"name": "my-library",
"version": "1.0.0",
"main": "dist/index.cjs.js", // CommonJS
"module": "dist/index.esm.js", // ES Module
"browser": "dist/index.umd.js", // UMD
"scripts": {
"build": "rollup -c"
}
}

// Rollup's advantages:
// 1. Excellent Tree Shaking
// 2. Smaller bundle size
// 3. Optimal for library development
// 4. Multiple format outputs

Parcel (zero config)​

// package.json (no config file needed!)
{
"name": "my-app",
"scripts": {
"dev": "parcel src/index.html",
"build": "parcel build src/index.html"
}
}

// src/index.html
<!DOCTYPE html>
<html>
<head>
<title>Parcel App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="./index.js"></script>
</body>
</html>

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './styles.css';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));

// src/styles.css
body {
margin: 0;
font-family: sans-serif;
}

// src/App.jsx
import React from 'react';

function App() {
return <h1>Hello Parcel!</h1>;
}

export default App;

// Just run!
// npm run dev

// Parcel automatically:
// - Babel transformation
// - CSS processing
// - Image optimization
// - HMR setup
// - Code splitting

// Parcel's advantages:
// 1. Zero configuration
// 2. Fast start
// 3. Automatic optimization
// 4. Beginner-friendly

// Disadvantages:
// 1. Difficult fine control
// 2. Smaller plugin ecosystem

Real Project Structure​

# Create React App (Webpack)
my-app/
β”œβ”€β”€ node_modules/
β”œβ”€β”€ public/
β”‚ β”œβ”€β”€ index.html
β”‚ └── favicon.ico
β”œβ”€β”€ src/
β”‚ β”œβ”€β”€ components/
β”‚ β”‚ β”œβ”€β”€ Header.js
β”‚ β”‚ └── Footer.js
β”‚ β”œβ”€β”€ App.js
β”‚ β”œβ”€β”€ App.css
β”‚ └── index.js
β”œβ”€β”€ package.json
└── README.md

# Vite
my-vite-app/
β”œβ”€β”€ node_modules/
β”œβ”€β”€ public/
β”‚ └── vite.svg
β”œβ”€β”€ src/
β”‚ β”œβ”€β”€ assets/
β”‚ β”œβ”€β”€ components/
β”‚ β”œβ”€β”€ App.jsx
β”‚ β”œβ”€β”€ App.css
β”‚ └── main.jsx
β”œβ”€β”€ index.html # In root!
β”œβ”€β”€ vite.config.js
└── package.json

# Next.js (Webpack + SWC)
my-next-app/
β”œβ”€β”€ node_modules/
β”œβ”€β”€ pages/
β”‚ β”œβ”€β”€ api/
β”‚ β”œβ”€β”€ _app.js
β”‚ β”œβ”€β”€ _document.js
β”‚ └── index.js
β”œβ”€β”€ public/
β”œβ”€β”€ styles/
β”œβ”€β”€ next.config.js
└── package.json

Performance Optimization Example​

// webpack.config.js (production optimization)

const webpack = require('webpack');
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

module.exports = {
mode: 'production',

optimization: {
// 1. Code minification
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
compress: {
drop_console: true, // Remove console.log
drop_debugger: true, // Remove debugger
pure_funcs: ['console.log']
}
}
}),
new CssMinimizerPlugin()
],

// 2. Code splitting
splitChunks: {
chunks: 'all',
minSize: 20000,
maxSize: 244000,
cacheGroups: {
// React libraries
react: {
test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
name: 'react',
priority: 20
},
// Other libraries
vendors: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 10
},
// Common code
common: {
minChunks: 2,
name: 'common',
priority: 5,
reuseExistingChunk: true
}
}
},

// 3. Runtime chunk separation
runtimeChunk: 'single',

// 4. Module ID stabilization
moduleIds: 'deterministic'
},

plugins: [
// 5. Gzip compression
new CompressionPlugin({
filename: '[path][base].gz',
algorithm: 'gzip',
test: /\.(js|css|html|svg)$/,
threshold: 10240,
minRatio: 0.8
}),

// 6. Bundle analysis
new BundleAnalyzerPlugin({
analyzerMode: 'static',
openAnalyzer: false,
reportFilename: 'bundle-report.html'
}),

// 7. Environment variables
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
})
],

// 8. Caching
cache: {
type: 'filesystem',
buildDependencies: {
config: [__filename]
}
},

// 9. Performance hints
performance: {
hints: 'warning',
maxEntrypointSize: 512000,
maxAssetSize: 512000
}
};

// Results:
// Before: bundle.js (2.5MB)
// After:
// react.js (140KB)
// vendors.js (300KB)
// common.js (50KB)
// main.js (100KB)
// Total: 590KB (76% reduction!)

Environment-specific Configuration​

// webpack.common.js (common)
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
]
};

// webpack.dev.js (development)
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
mode: 'development',
devtool: 'eval-source-map', // Fast sourcemap
devServer: {
hot: true,
port: 3000
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader'] // Inline CSS in JS
}
]
}
});

// webpack.prod.js (production)
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = merge(common, {
mode: 'production',
devtool: 'source-map', // Accurate sourcemap
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader, // Extract CSS file
'css-loader'
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css'
})
]
});

// package.json
{
"scripts": {
"dev": "webpack serve --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
}
}

πŸ€” Frequently Asked Questions​

Q1. Webpack vs Vite, which should I choose?​

A: Choose based on your project characteristics:

// When to choose Webpack
const webpackUseCases = {
suitable_for: [
'Complex build requirements',
'Fine-grained control needed',
'Many plugins needed',
'Legacy projects',
'Older browser support'
],
advantages: [
'Mature ecosystem',
'Rich plugin collection',
'Complete control',
'Proven for large-scale projects'
],
disadvantages: [
'Slow dev server',
'Complex configuration',
'High learning curve'
]
};

// When to choose Vite
const viteUseCases = {
suitable_for: [
'New projects',
'Want fast development experience',
'Modern browsers only',
'Prefer simple configuration'
],
advantages: [
'Ultra-fast dev server',
'Instant start',
'Simple configuration',
'Modern defaults',
'Very fast HMR'
],
disadvantages: [
'Relatively smaller ecosystem',
'Some issues with legacy libraries',
'Production builds use Rollup'
]
};

// Speed comparison:
// Dev server start:
// Webpack: 10-60s
// Vite: 0.5-2s (20-100x faster!)

// HMR (Hot Module Replacement):
// Webpack: 0.5-2s
// Vite: 50-200ms (10x faster!)

// Production build:
// Webpack: Similar
// Vite: Similar (both fast enough)

// Recommendations:
// - New projects: Vite
// - Existing projects: Keep Webpack
// - Migration: Consider carefully

Q2. How to reduce bundle size?​

A: Use various optimization techniques:

// 1. Tree Shaking (remove unused code)

// ❌ Bad example (full import)
import _ from 'lodash'; // Entire library (70KB)
_.debounce(fn, 100);

// βœ… Good example (only what's needed)
import debounce from 'lodash/debounce'; // Only 2KB
debounce(fn, 100);

// Even better (lodash-es)
import { debounce } from 'lodash-es'; // Tree Shaking possible

// 2. Code Splitting
// Split by route
const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));

// Conditional loading
if (user.isAdmin) {
const AdminPanel = await import('./AdminPanel');
AdminPanel.render();
}

// 3. Dynamic Import
button.addEventListener('click', async () => {
const module = await import('./heavyFeature.js');
module.doSomething();
});

// 4. Use external CDN
// webpack.config.js
module.exports = {
externals: {
react: 'React',
'react-dom': 'ReactDOM'
}
};

// index.html
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>

// 5. Image optimization
// - Use WebP format
// - Resize to appropriate size
// - Lazy Loading

// webpack.config.js
{
test: /\.(png|jpg|jpeg)$/,
use: [
{
loader: 'image-webpack-loader',
options: {
mozjpeg: { quality: 75 },
pngquant: { quality: [0.65, 0.9] }
}
}
]
}

// 6. Compression
// Gzip, Brotli
new CompressionPlugin({
algorithm: 'brotliCompress',
test: /\.(js|css|html|svg)$/
});

// 7. Bundle Analysis
npm install --save-dev webpack-bundle-analyzer

// webpack.config.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

plugins: [
new BundleAnalyzerPlugin()
]

// 8. Replace Moment.js
// ❌ Moment.js (70KB)
import moment from 'moment';

// βœ… date-fns (2-5KB)
import { format } from 'date-fns';

// βœ… Day.js (2KB)
import dayjs from 'dayjs';

// Results:
// Before: 2.5MB
// After: 500KB (80% reduction!)

Q3. The dev server is slow, what should I do?​

A: There are several optimization methods:

// webpack.config.js (dev server optimization)

module.exports = {
// 1. Enable caching
cache: {
type: 'filesystem',
buildDependencies: {
config: [__filename]
}
},

// 2. Optimize sourcemap
devtool: 'eval-cheap-module-source-map', // Fast!
// 'eval-source-map' - Medium
// 'source-map' - Slow (for production)

// 3. Babel caching
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true // Enable cache
}
}
}
]
},

// 4. Resolve optimization
resolve: {
// Extension order
extensions: ['.js', '.jsx'], // Only what's needed

// Aliases
alias: {
'@': path.resolve(__dirname, 'src')
},

// Module paths
modules: ['node_modules'] // Explicit
},

// 5. Dev server settings
devServer: {
hot: true, // HMR
liveReload: false, // Unnecessary with HMR
client: {
overlay: {
errors: true,
warnings: false // Warnings only in console
}
}
},

// 6. Disable performance hints (during development)
performance: {
hints: false
},

// 7. Minimize stats
stats: 'errors-warnings'
};

// Or migrate to Vite!
// Webpack: 30s startup
// Vite: 1s startup (30x faster!)

Q4. Can I develop without a bundler?​

A: Modern browsers support ES Modules, but there are limitations:

<!-- Without bundler (using ESM) -->
<!DOCTYPE html>
<html>
<head>
<title>No Bundler</title>
</head>
<body>
<div id="app"></div>

<!-- type="module" required -->
<script type="module">
import { render } from './render.js';
import { utils } from './utils.js';

render();
</script>
</body>
</html>

<!-- render.js -->
<script type="module">
export function render() {
document.getElementById('app').innerHTML = '<h1>Hello!</h1>';
}
</script>

<!-- Advantages: -->
- No configuration needed
- Instant start
- Simple

<!-- Disadvantages: -->
- HTTP/2 needed (many requests)
- No node_modules support
- No TypeScript transformation
- Can't use JSX
- Difficult to handle images/CSS
- Difficult to optimize for production
- No older browser support

<!-- Import Maps (experimental) -->
<script type="importmap">
{
"imports": {
"react": "https://esm.sh/react@18",
"react-dom": "https://esm.sh/react-dom@18"
}
}
</script>

<script type="module">
import React from 'react';
import ReactDOM from 'react-dom';

// Loaded directly from CDN!
</script>

<!-- Conclusion: -->
<!-- Small prototypes: Possible without bundler -->
<!-- Real projects: Bundler required! -->

Q5. How to use TypeScript with bundlers?​

A: Most bundlers support TypeScript:

// Webpack + TypeScript
// webpack.config.js
module.exports = {
entry: './src/index.tsx',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
}
};

// tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"jsx": "react",
"moduleResolution": "node",
"esModuleInterop": true,
"strict": true,
"skipLibCheck": true
},
"include": ["src"]
}

// Vite + TypeScript (automatic support!)
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
plugins: [react()]
});

// Just write .tsx files!
// src/App.tsx
import React from 'react';

interface Props {
name: string;
age: number;
}

const App: React.FC<Props> = ({ name, age }) => {
return (
<div>
<h1>Hello, {name}!</h1>
<p>Age: {age}</p>
</div>
);
};

export default App;

// esbuild (ultra-fast)
// build.js
const esbuild = require('esbuild');

esbuild.build({
entryPoints: ['src/index.tsx'],
bundle: true,
outfile: 'dist/bundle.js',
loader: { '.tsx': 'tsx' },
minify: true
});

// SWC (Next.js default)
// .swcrc
{
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": true
},
"target": "es2020"
}
}

// Speed comparison:
// tsc (TypeScript): Slow
// Babel: Medium
// esbuild: 10-100x faster
// SWC: 20-70x faster

// Recommendations:
// - Vite: esbuild built-in
// - Next.js: SWC default
// - Webpack: ts-loader or babel-loader

πŸŽ“ Next Steps​

Now that you understand bundlers, learn more about:

  1. What is Node.js? (document to be written) - Bundler execution environment
  2. What is Git? (document to be written) - Version control for safe development
  3. What is CI/CD? - Automated build and deployment

🎬 Conclusion​

Bundlers are essential tools for modern web development:

  • Webpack: Powerful and mature, complex configuration
  • Vite: Ultra-fast development experience, modern
  • Rollup: Library development, excellent Tree Shaking
  • Parcel: Zero configuration, beginner-friendly

Choose the right bundler for your project and optimize it to build fast web applications!