TypeScript with Bundlers (Webpack/Vite)

Bundle and optimize TypeScript applications for production

📦 What are Bundlers?

Bundlers combine multiple TypeScript files into optimized bundles for browsers. Webpack and Vite are popular tools that handle compilation, minification, and asset management, making your applications production-ready and performant.


// Multiple files bundled into one
// src/utils.ts
export const greet = (name: string) => `Hello, ${name}!`;

// src/index.ts
import { greet } from './utils';
console.log(greet('World'));
                                    

Popular Bundlers

📦

Webpack

Powerful, configurable bundler

module.exports = {
  entry: './src/index.ts',
  output: {
    filename: 'bundle.js'
  }
};

Vite

Lightning-fast modern bundler

export default {
  build: {
    outDir: 'dist'
  }
};
🔄

Hot Reload

Instant updates during development

// Changes reflect immediately
const message: string = 'Updated!';
🗜️

Optimization

Minify and compress for production

optimization: {
  minimize: true,
  splitChunks: { chunks: 'all' }
}

🔹 Setting Up Webpack

Install Webpack with TypeScript support:

# Install Webpack and loaders
npm install --save-dev webpack webpack-cli webpack-dev-server
npm install --save-dev ts-loader typescript

Create webpack.config.js :

const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.ts',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  resolve: {
    extensions: ['.ts', '.js'],
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
    ],
  },
  devServer: {
    static: './dist',
    port: 3000,
  },
};

🔹 TypeScript Configuration for Webpack

Update tsconfig.json :

{
  "compilerOptions": {
    "target": "ES6",
    "module": "ES6",
    "moduleResolution": "node",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "sourceMap": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

🔹 Webpack Example Project

Create a simple TypeScript project:

🔸 src/math.ts

export function add(a: number, b: number): number {
  return a + b;
}

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

🔸 src/index.ts

import { add, multiply } from './math';

const result1 = add(5, 3);
const result2 = multiply(4, 7);

console.log(`5 + 3 = ${result1}`);
console.log(`4 × 7 = ${result2}`);

🔸 dist/index.html

<!DOCTYPE html>
<html>
<head>
  <title>TypeScript Webpack App</title>
</head>
<body>
  <h1>Check the console!</h1>
  <script src="bundle.js"></script>
</body>
</html>

🔹 Setting Up Vite

Create a new Vite project with TypeScript:

# Create Vite project
npm create vite@latest my-app -- --template vanilla-ts

# Navigate to project
cd my-app

# Install dependencies
npm install

# Start dev server
npm run dev

🔹 Vite Configuration

Create vite.config.ts :

import { defineConfig } from 'vite';
import path from 'path';

export default defineConfig({
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
  build: {
    outDir: 'dist',
    sourcemap: true,
    minify: 'terser',
  },
  server: {
    port: 3000,
    open: true,
  },
});

🔹 Vite Example Project

Simple Vite TypeScript application:

🔸 src/counter.ts

export class Counter {
  private count: number = 0;

  increment(): void {
    this.count++;
    this.render();
  }

  decrement(): void {
    this.count--;
    this.render();
  }

  render(): void {
    const element = document.getElementById('counter');
    if (element) {
      element.textContent = `Count: ${this.count}`;
    }
  }
}

🔸 src/main.ts

import './style.css';
import { Counter } from './counter';

const counter = new Counter();

document.querySelector<HTMLDivElement>('#app')!.innerHTML = `
  <div>
    <h1>Vite + TypeScript</h1>
    <div id="counter">Count: 0</div>
    <button id="increment">Increment</button>
    <button id="decrement">Decrement</button>
  </div>
`;

document.getElementById('increment')?.addEventListener('click', () => {
  counter.increment();
});

document.getElementById('decrement')?.addEventListener('click', () => {
  counter.decrement();
});

🔹 Production Build

Build optimized bundles for production:

🔸 Webpack Production

// webpack.config.js
module.exports = {
  mode: 'production',
  optimization: {
    minimize: true,
    splitChunks: {
      chunks: 'all',
    },
  },
};
# Build for production
npm run build

🔸 Vite Production

# Build for production
npm run build

# Preview production build
npm run preview

🔹 Package.json Scripts

Common scripts for bundlers:

{
  "scripts": {
    "dev": "webpack serve --mode development",
    "build": "webpack --mode production",
    "dev:vite": "vite",
    "build:vite": "vite build",
    "preview": "vite preview"
  }
}

🔹 Webpack vs Vite Comparison

Webpack:

  • Pros: Highly configurable, mature ecosystem, extensive plugins
  • Cons: Slower build times, complex configuration
  • Best for: Large enterprise applications, custom build requirements

Vite:

  • Pros: Lightning-fast HMR, simple config, modern defaults
  • Cons: Newer ecosystem, fewer plugins than Webpack
  • Best for: Modern web apps, rapid development, smaller projects

🧠 Test Your Knowledge

What is the main advantage of using Vite over Webpack?