Prerequisites
- Basic understanding of JavaScript ๐
- TypeScript installation โก
- VS Code or preferred IDE ๐ป
What you'll learn
- Understand the concept fundamentals ๐ฏ
- Apply the concept in real projects ๐๏ธ
- Debug common issues ๐
- Write type-safe code โจ
๐ฏ Introduction
Welcome to the world of lightning-fast development with Vite! ๐ In this guide, weโll explore how Vite revolutionizes TypeScript development with its blazing-fast hot module replacement and modern build system.
Youโll discover how Vite can transform your TypeScript development experience from sluggish rebuilds to instant updates. Whether youโre building React apps ๐, Vue projects ๐ฅ๏ธ, or vanilla TypeScript libraries ๐, understanding Vite is essential for modern development workflows.
By the end of this tutorial, youโll feel confident setting up and optimizing Vite for your TypeScript projects! Letโs dive in! ๐โโ๏ธ
๐ Understanding Vite
๐ค What is Vite?
Vite is like a lightning-fast sports car ๐๏ธ compared to traditional bundlers that feel like old trucks. Think of it as a development server that starts instantly and updates your code changes in milliseconds, not seconds.
In TypeScript terms, Vite leverages ES modules and esbuild for blazing-fast builds โก. This means you can:
- โจ Start development server in under 100ms
- ๐ See changes instantly with Hot Module Replacement (HMR)
- ๐ก๏ธ Get TypeScript type checking without blocking dev server
- ๐ฏ Bundle efficiently for production
๐ก Why Use Vite?
Hereโs why developers love Vite:
- Instant Server Start โก: No more waiting for bundling
- Lightning Fast HMR ๐ฅ: Changes appear instantly
- Native ES Modules ๐ฆ: Modern JavaScript approach
- Rich Plugin Ecosystem ๐งฉ: Extend functionality easily
- Optimized Production Builds ๐๏ธ: Rollup-powered bundling
Real-world example: Imagine building a TypeScript dashboard ๐. With Vite, you can see component updates instantly instead of waiting 5-10 seconds for webpack rebuilds!
๐ง Basic Syntax and Usage
๐ Simple Setup
Letโs start with a basic Vite + TypeScript project:
# ๐ Create a new Vite project
npm create vite@latest my-ts-app -- --template vanilla-ts
cd my-ts-app
npm install
// ๐ vite.config.ts - Your Vite configuration
import { defineConfig } from 'vite';
export default defineConfig({
// ๐ฏ Basic configuration
server: {
port: 3000, // ๐ Development server port
open: true, // ๐ Auto-open browser
hmr: {
overlay: false // ๐จ Customize HMR overlay
}
},
// ๐๏ธ Build configuration
build: {
target: 'es2020', // โก Modern JavaScript output
outDir: 'dist', // ๐ฆ Output directory
sourcemap: true // ๐ Enable source maps
}
});
๐ก Explanation: The defineConfig
function provides TypeScript autocomplete for your Vite configuration!
๐ฏ TypeScript Integration
Hereโs how Vite works seamlessly with TypeScript:
// ๐ src/main.ts - Entry point
import './style.css';
// ๐จ Define types for our app
interface User {
id: number;
name: string;
email: string;
isOnline: boolean;
}
// ๐ Vite provides fast TypeScript compilation
const users: User[] = [
{ id: 1, name: "Alice", email: "[email protected]", isOnline: true },
{ id: 2, name: "Bob", email: "[email protected]", isOnline: false }
];
// ๐ฏ Type-safe DOM manipulation
const app = document.querySelector<HTMLDivElement>('#app')!;
function renderUsers(users: User[]): void {
app.innerHTML = `
<h1>๐ฅ User Dashboard</h1>
<div class="users">
${users.map(user => `
<div class="user ${user.isOnline ? 'online' : 'offline'}">
<h3>${user.name} ${user.isOnline ? '๐ข' : '๐ด'}</h3>
<p>๐ง ${user.email}</p>
</div>
`).join('')}
</div>
`;
}
// โก Instant updates with HMR
renderUsers(users);
// ๐ฅ Vite HMR API for advanced usage
if (import.meta.hot) {
import.meta.hot.accept(); // ๐ Enable HMR for this module
}
๐ก Practical Examples
๐ Example 1: E-commerce Product Configurator
Letโs build a type-safe product configurator with instant updates:
// ๐๏ธ types/products.ts
export interface Product {
id: string;
name: string;
basePrice: number;
category: 'electronics' | 'clothing' | 'books';
emoji: string;
variants: ProductVariant[];
}
export interface ProductVariant {
name: string;
priceModifier: number;
available: boolean;
}
export interface CartItem {
product: Product;
variant: ProductVariant;
quantity: number;
}
// ๐ฎ src/product-configurator.ts
import type { Product, ProductVariant, CartItem } from './types/products';
class ProductConfigurator {
private products: Product[] = [
{
id: '1',
name: 'TypeScript Laptop',
basePrice: 999.99,
category: 'electronics',
emoji: '๐ป',
variants: [
{ name: '16GB RAM', priceModifier: 200, available: true },
{ name: '32GB RAM', priceModifier: 500, available: true },
{ name: '64GB RAM', priceModifier: 1000, available: false }
]
},
{
id: '2',
name: 'Developer Hoodie',
basePrice: 49.99,
category: 'clothing',
emoji: '๐',
variants: [
{ name: 'Small', priceModifier: 0, available: true },
{ name: 'Medium', priceModifier: 0, available: true },
{ name: 'Large', priceModifier: 5, available: true }
]
}
];
private cart: CartItem[] = [];
// ๐ฏ Render product configurator
renderConfigurator(containerId: string): void {
const container = document.getElementById(containerId);
if (!container) return;
container.innerHTML = `
<div class="configurator">
<h2>๐ Product Configurator</h2>
${this.products.map(product => this.renderProduct(product)).join('')}
<div class="cart-summary">
<h3>๐๏ธ Cart (${this.cart.length} items)</h3>
<p>๐ฐ Total: $${this.getCartTotal().toFixed(2)}</p>
</div>
</div>
`;
// ๐ฎ Add event listeners
this.attachEventListeners();
}
// ๐จ Render individual product
private renderProduct(product: Product): string {
return `
<div class="product" data-product-id="${product.id}">
<h3>${product.emoji} ${product.name}</h3>
<p class="base-price">Base: $${product.basePrice}</p>
<div class="variants">
${product.variants.map(variant => `
<button
class="variant-btn ${variant.available ? 'available' : 'unavailable'}"
data-variant="${variant.name}"
${!variant.available ? 'disabled' : ''}
>
${variant.name} ${variant.priceModifier > 0 ? `+$${variant.priceModifier}` : ''}
${variant.available ? 'โ
' : 'โ'}
</button>
`).join('')}
</div>
</div>
`;
}
// ๐ Attach event listeners with type safety
private attachEventListeners(): void {
document.querySelectorAll('.variant-btn').forEach(button => {
button.addEventListener('click', (e) => {
const target = e.target as HTMLButtonElement;
const productId = target.closest('.product')?.getAttribute('data-product-id');
const variantName = target.getAttribute('data-variant');
if (productId && variantName) {
this.addToCart(productId, variantName);
}
});
});
}
// โ Add item to cart
private addToCart(productId: string, variantName: string): void {
const product = this.products.find(p => p.id === productId);
const variant = product?.variants.find(v => v.name === variantName);
if (product && variant && variant.available) {
const existingItem = this.cart.find(
item => item.product.id === productId && item.variant.name === variantName
);
if (existingItem) {
existingItem.quantity++;
} else {
this.cart.push({ product, variant, quantity: 1 });
}
console.log(`โ
Added ${product.emoji} ${product.name} (${variant.name}) to cart!`);
this.renderConfigurator('app'); // ๐ Re-render for instant updates
}
}
// ๐ฐ Calculate cart total
private getCartTotal(): number {
return this.cart.reduce((total, item) => {
const itemPrice = item.product.basePrice + item.variant.priceModifier;
return total + (itemPrice * item.quantity);
}, 0);
}
}
// ๐ฎ Initialize the configurator
const configurator = new ProductConfigurator();
configurator.renderConfigurator('app');
// ๐ฅ Enable HMR for instant updates during development
if (import.meta.hot) {
import.meta.hot.accept(() => {
configurator.renderConfigurator('app');
});
}
๐ฏ Try it yourself: Add a search feature and inventory management!
๐ฎ Example 2: Real-time Game Dashboard
Letโs create a game dashboard with Viteโs HMR:
// ๐ src/game-dashboard.ts
interface GameSession {
id: string;
player: string;
score: number;
level: number;
status: 'playing' | 'paused' | 'completed';
startTime: Date;
achievements: Achievement[];
}
interface Achievement {
id: string;
name: string;
description: string;
emoji: string;
unlockedAt: Date;
}
class GameDashboard {
private sessions: Map<string, GameSession> = new Map();
private achievements: Achievement[] = [
{ id: '1', name: 'First Steps', description: 'Start your first game', emoji: '๐ถ', unlockedAt: new Date() },
{ id: '2', name: 'Speed Demon', description: 'Complete a level in under 30 seconds', emoji: 'โก', unlockedAt: new Date() },
{ id: '3', name: 'High Scorer', description: 'Reach 10,000 points', emoji: '๐', unlockedAt: new Date() }
];
// ๐ฎ Create new game session
startNewGame(playerName: string): string {
const sessionId = `game-${Date.now()}`;
const session: GameSession = {
id: sessionId,
player: playerName,
score: 0,
level: 1,
status: 'playing',
startTime: new Date(),
achievements: [this.achievements[0]] // ๐ถ First Steps achievement
};
this.sessions.set(sessionId, session);
console.log(`๐ฎ ${playerName} started a new game!`);
return sessionId;
}
// ๐ฏ Update game score
updateScore(sessionId: string, points: number): void {
const session = this.sessions.get(sessionId);
if (!session || session.status !== 'playing') return;
session.score += points;
// ๐ Check for achievements
if (session.score >= 10000 && !session.achievements.find(a => a.id === '3')) {
session.achievements.push(this.achievements[2]);
console.log(`๐ ${session.player} unlocked: ${this.achievements[2].emoji} ${this.achievements[2].name}!`);
}
// ๐ Level up every 1000 points
const newLevel = Math.floor(session.score / 1000) + 1;
if (newLevel > session.level) {
session.level = newLevel;
console.log(`๐ ${session.player} reached level ${session.level}!`);
}
this.renderDashboard();
}
// ๐จ Render the dashboard
renderDashboard(): void {
const app = document.getElementById('app');
if (!app) return;
const activeSessions = Array.from(this.sessions.values())
.filter(s => s.status === 'playing');
app.innerHTML = `
<div class="game-dashboard">
<h1>๐ฎ Game Dashboard</h1>
<div class="stats">
<div class="stat">
<h3>๐ฏ Active Games</h3>
<p class="stat-value">${activeSessions.length}</p>
</div>
<div class="stat">
<h3>๐ฅ Total Players</h3>
<p class="stat-value">${this.sessions.size}</p>
</div>
<div class="stat">
<h3>๐ Total Achievements</h3>
<p class="stat-value">${this.getTotalAchievements()}</p>
</div>
</div>
<div class="sessions">
<h2>๐ฎ Active Sessions</h2>
${activeSessions.map(session => `
<div class="session-card">
<h3>๐ค ${session.player}</h3>
<div class="session-stats">
<span class="score">๐ฏ ${session.score.toLocaleString()}</span>
<span class="level">๐ Level ${session.level}</span>
<span class="time">โฑ๏ธ ${this.getPlayTime(session)}</span>
</div>
<div class="achievements">
${session.achievements.map(a => `
<span class="achievement" title="${a.description}">
${a.emoji} ${a.name}
</span>
`).join('')}
</div>
<button onclick="gameManager.updateScore('${session.id}', 100)">
โ Add 100 points
</button>
</div>
`).join('')}
</div>
<div class="new-game">
<h2>๐ Start New Game</h2>
<input type="text" id="playerName" placeholder="Enter player name" />
<button onclick="gameManager.startNewGameFromInput()">๐ฎ Start Game</button>
</div>
</div>
`;
}
// โฑ๏ธ Calculate play time
private getPlayTime(session: GameSession): string {
const now = new Date();
const diff = now.getTime() - session.startTime.getTime();
const minutes = Math.floor(diff / 60000);
const seconds = Math.floor((diff % 60000) / 1000);
return `${minutes}:${seconds.toString().padStart(2, '0')}`;
}
// ๐ Get total achievements count
private getTotalAchievements(): number {
return Array.from(this.sessions.values())
.reduce((total, session) => total + session.achievements.length, 0);
}
// ๐ฎ Start game from input
startNewGameFromInput(): void {
const input = document.getElementById('playerName') as HTMLInputElement;
const playerName = input.value.trim();
if (playerName) {
this.startNewGame(playerName);
input.value = '';
this.renderDashboard();
}
}
}
// ๐ฎ Create global game manager
const gameManager = new GameDashboard();
(window as any).gameManager = gameManager; // Make it globally accessible
// ๐ Initial render
gameManager.renderDashboard();
// ๐ฅ HMR support for instant updates
if (import.meta.hot) {
import.meta.hot.accept(() => {
gameManager.renderDashboard();
});
}
๐ Advanced Concepts
๐งโโ๏ธ Advanced Topic 1: Custom Vite Plugins
When youโre ready to level up, create custom plugins:
// ๐ฏ vite-plugin-typescript-paths.ts
import type { Plugin } from 'vite';
import { readFileSync } from 'fs';
import { resolve } from 'path';
export function typescriptPaths(): Plugin {
return {
name: 'typescript-paths',
configResolved(config) {
// ๐ Read tsconfig.json
const tsconfig = JSON.parse(
readFileSync(resolve(config.root, 'tsconfig.json'), 'utf-8')
);
// ๐จ Apply path mapping
if (tsconfig.compilerOptions?.paths) {
const paths = tsconfig.compilerOptions.paths;
const alias: Record<string, string> = {};
for (const [key, value] of Object.entries(paths)) {
const aliasKey = key.replace('/*', '');
const aliasValue = resolve(config.root, (value as string[])[0].replace('/*', ''));
alias[aliasKey] = aliasValue;
}
config.resolve.alias = { ...config.resolve.alias, ...alias };
}
}
};
}
// ๐ช Using the custom plugin
// vite.config.ts
import { defineConfig } from 'vite';
import { typescriptPaths } from './plugins/vite-plugin-typescript-paths';
export default defineConfig({
plugins: [
typescriptPaths(), // โจ Custom plugin for TypeScript paths
],
resolve: {
alias: {
'@': resolve(__dirname, 'src'),
'@components': resolve(__dirname, 'src/components'),
'@utils': resolve(__dirname, 'src/utils')
}
}
});
๐๏ธ Advanced Topic 2: Environment-Specific Configurations
For complex projects with multiple environments:
// ๐ Advanced Vite configuration
import { defineConfig, loadEnv } from 'vite';
import type { UserConfig } from 'vite';
export default defineConfig(({ command, mode }) => {
// ๐ Load environment variables
const env = loadEnv(mode, process.cwd(), '');
const config: UserConfig = {
define: {
// ๐ฏ Global constants
__APP_VERSION__: JSON.stringify(env.npm_package_version),
__API_URL__: JSON.stringify(env.VITE_API_URL),
__DEV__: command === 'serve'
},
server: {
port: parseInt(env.VITE_PORT) || 3000,
proxy: {
// ๐ API proxy for development
'/api': {
target: env.VITE_API_URL || 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
},
build: {
// ๐๏ธ Production optimizations
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
utils: ['lodash', 'date-fns']
}
}
},
// ๐ Bundle analysis
reportCompressedSize: true,
chunkSizeWarningLimit: 1000
},
// ๐งช Testing configuration
test: {
environment: 'jsdom',
setupFiles: ['./src/test/setup.ts']
}
};
// ๐ฏ Mode-specific configurations
if (mode === 'development') {
config.server!.hmr = {
overlay: true,
clientPort: 3001
};
}
if (mode === 'production') {
config.build!.minify = 'terser';
config.build!.terserOptions = {
compress: {
drop_console: true // ๐ซ Remove console.logs in production
}
};
}
return config;
});
โ ๏ธ Common Pitfalls and Solutions
๐ฑ Pitfall 1: Slow TypeScript Checking
// โ Wrong way - blocking TypeScript checking
// vite.config.ts
export default defineConfig({
// This will slow down your dev server! ๐ฐ
plugins: [
typescript({
check: true, // ๐ Blocks dev server
declaration: true // ๐ Generates .d.ts files
})
]
});
// โ
Correct way - non-blocking type checking
export default defineConfig({
plugins: [
typescript({
check: false, // โก Don't block dev server
declaration: false // โก Skip .d.ts generation in dev
})
]
});
// ๐ ๏ธ Run type checking separately
// package.json
{
"scripts": {
"dev": "vite",
"type-check": "tsc --noEmit",
"type-check:watch": "tsc --noEmit --watch"
}
}
๐คฏ Pitfall 2: Import Path Issues
// โ Dangerous - might not work in production!
import { utils } from '../../../utils/helpers';
import Component from './Component.tsx'; // ๐ฅ Explicit .tsx not needed!
// โ
Safe - use path mapping and proper imports!
// tsconfig.json
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"],
"@/components/*": ["./src/components/*"],
"@/utils/*": ["./src/utils/*"]
}
}
}
// โ
Clean imports
import { utils } from '@/utils/helpers';
import Component from './Component'; // โ
No extension needed
๐ ๏ธ Best Practices
- โก Keep Dev Fast: Donโt block the dev server with type checking
- ๐ฆ Use Path Mapping: Clean imports with TypeScript paths
- ๐ฅ Leverage HMR: Use
import.meta.hot
for custom HMR logic - ๐ Environment Variables: Use
.env
files for configuration - ๐๏ธ Optimize Builds: Configure chunking for better performance
- ๐งช Separate Concerns: Type checking, linting, and dev server separately
๐งช Hands-On Exercise
๐ฏ Challenge: Build a TypeScript Code Playground
Create a Vite-powered TypeScript playground with instant compilation:
๐ Requirements:
- โ Real-time TypeScript compilation with error display
- ๐จ Syntax highlighting for TypeScript code
- ๐ Instant preview of compiled JavaScript
- ๐พ Save/load code snippets with localStorage
- ๐ Hot reload for instant updates
- ๐ Bundle size analysis
๐ Bonus Points:
- Add Monaco Editor integration
- Implement sharing functionality
- Create preset code examples
- Add TypeScript version switching
๐ก Solution
๐ Click to see solution
// ๐ฏ TypeScript Playground Implementation
interface CodeSnippet {
id: string;
name: string;
typescript: string;
javascript: string;
errors: string[];
createdAt: Date;
}
class TypeScriptPlayground {
private snippets: Map<string, CodeSnippet> = new Map();
private currentSnippet: CodeSnippet | null = null;
private compileTimeout: number | null = null;
constructor() {
this.loadSnippets();
this.setupEventListeners();
this.renderPlayground();
}
// ๐ฎ Setup the playground interface
renderPlayground(): void {
const app = document.getElementById('app');
if (!app) return;
app.innerHTML = `
<div class="playground">
<header class="playground-header">
<h1>๐ฎ TypeScript Playground</h1>
<div class="controls">
<button id="newSnippet">๐ New</button>
<button id="saveSnippet">๐พ Save</button>
<select id="snippetSelect">
<option value="">๐ Load Snippet...</option>
${Array.from(this.snippets.values()).map(s =>
`<option value="${s.id}">${s.name}</option>`
).join('')}
</select>
</div>
</header>
<div class="editor-container">
<div class="editor-panel">
<h3>๐ TypeScript Code</h3>
<textarea
id="typescriptEditor"
placeholder="// ๐ Start typing TypeScript code here!
interface User {
name: string;
age: number;
emoji: string;
}
const user: User = {
name: 'Alice',
age: 25,
emoji: '๐'
};
console.log(\`Hello \${user.name}! \${user.emoji}\`);"
></textarea>
</div>
<div class="output-panel">
<h3>โก Compiled JavaScript</h3>
<pre id="javascriptOutput"></pre>
<h3>๐จ Type Errors</h3>
<div id="errorOutput"></div>
</div>
</div>
<div class="preview-panel">
<h3>๐ฎ Code Preview</h3>
<div id="codePreview"></div>
</div>
</div>
`;
this.loadDefaultSnippet();
}
// ๐ฏ Setup event listeners
private setupEventListeners(): void {
document.addEventListener('DOMContentLoaded', () => {
const editor = document.getElementById('typescriptEditor') as HTMLTextAreaElement;
const newBtn = document.getElementById('newSnippet');
const saveBtn = document.getElementById('saveSnippet');
const select = document.getElementById('snippetSelect') as HTMLSelectElement;
// โก Real-time compilation
editor?.addEventListener('input', () => {
if (this.compileTimeout) {
clearTimeout(this.compileTimeout);
}
this.compileTimeout = window.setTimeout(() => {
this.compileTypeScript(editor.value);
}, 300); // ๐ 300ms debounce
});
// ๐ New snippet
newBtn?.addEventListener('click', () => this.createNewSnippet());
// ๐พ Save snippet
saveBtn?.addEventListener('click', () => this.saveCurrentSnippet());
// ๐ Load snippet
select?.addEventListener('change', (e) => {
const snippetId = (e.target as HTMLSelectElement).value;
if (snippetId) this.loadSnippet(snippetId);
});
});
}
// โก Compile TypeScript code
private async compileTypeScript(code: string): Promise<void> {
try {
// ๐ฏ Simple TypeScript compilation simulation
// In a real implementation, you'd use TypeScript's compiler API
const errors: string[] = [];
let javascript = code;
// ๐ Basic error checking
if (code.includes('any')) {
errors.push("โ ๏ธ Avoid using 'any' type - be more specific!");
}
if (code.includes('console.log') && code.includes('production')) {
errors.push("๐ซ Remove console.log statements in production code!");
}
// ๐จ Simple transformation (remove type annotations)
javascript = code
.replace(/:\s*string/g, '')
.replace(/:\s*number/g, '')
.replace(/:\s*boolean/g, '')
.replace(/interface\s+\w+\s*{[^}]*}/g, '')
.replace(/type\s+\w+\s*=\s*[^;]+;/g, '');
// ๐ Update outputs
this.updateOutputs(javascript, errors);
// ๐ฎ Update preview
this.updatePreview(javascript);
} catch (error) {
console.error('Compilation error:', error);
this.updateOutputs('', [`๐ฅ Compilation failed: ${error}`]);
}
}
// ๐ Update output panels
private updateOutputs(javascript: string, errors: string[]): void {
const jsOutput = document.getElementById('javascriptOutput');
const errorOutput = document.getElementById('errorOutput');
if (jsOutput) {
jsOutput.textContent = javascript || '// ๐ฏ Compiled JavaScript will appear here';
}
if (errorOutput) {
if (errors.length > 0) {
errorOutput.innerHTML = errors.map(error =>
`<div class="error">${error}</div>`
).join('');
} else {
errorOutput.innerHTML = '<div class="success">โ
No errors found!</div>';
}
}
}
// ๐ฎ Update live preview
private updatePreview(javascript: string): void {
const preview = document.getElementById('codePreview');
if (!preview) return;
try {
// ๐ Execute the code safely
const originalLog = console.log;
const logs: string[] = [];
console.log = (...args) => {
logs.push(args.map(arg =>
typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
).join(' '));
};
// ๐ฏ Execute in isolated scope
new Function(javascript)();
// ๐ Restore console.log
console.log = originalLog;
// ๐ Display results
preview.innerHTML = `
<div class="preview-output">
<h4>๐ค Console Output:</h4>
${logs.length > 0 ?
logs.map(log => `<div class="log-line">${log}</div>`).join('') :
'<div class="no-output">๐คซ No console output</div>'
}
</div>
`;
} catch (error) {
preview.innerHTML = `
<div class="preview-error">
<h4>๐ฅ Runtime Error:</h4>
<div class="error">${error}</div>
</div>
`;
}
}
// ๐ Create new snippet
private createNewSnippet(): void {
const editor = document.getElementById('typescriptEditor') as HTMLTextAreaElement;
if (editor) {
editor.value = `// ๐ฏ New TypeScript snippet
interface HelloWorld {
message: string;
emoji: string;
}
const greeting: HelloWorld = {
message: "Hello, TypeScript!",
emoji: "๐"
};
console.log(\`\${greeting.message} \${greeting.emoji}\`);`;
this.compileTypeScript(editor.value);
}
}
// ๐พ Save current snippet
private saveCurrentSnippet(): void {
const editor = document.getElementById('typescriptEditor') as HTMLTextAreaElement;
const name = prompt('๐ Enter snippet name:');
if (name && editor) {
const snippet: CodeSnippet = {
id: Date.now().toString(),
name,
typescript: editor.value,
javascript: '', // Will be compiled
errors: [],
createdAt: new Date()
};
this.snippets.set(snippet.id, snippet);
this.saveSnippets();
this.renderPlayground();
console.log(`๐พ Saved snippet: ${name}`);
}
}
// ๐ Load snippet
private loadSnippet(snippetId: string): void {
const snippet = this.snippets.get(snippetId);
if (snippet) {
const editor = document.getElementById('typescriptEditor') as HTMLTextAreaElement;
if (editor) {
editor.value = snippet.typescript;
this.compileTypeScript(snippet.typescript);
this.currentSnippet = snippet;
}
}
}
// ๐ฏ Load default example
private loadDefaultSnippet(): void {
this.createNewSnippet();
}
// ๐พ Save snippets to localStorage
private saveSnippets(): void {
localStorage.setItem('ts-playground-snippets', JSON.stringify(
Array.from(this.snippets.entries())
));
}
// ๐ Load snippets from localStorage
private loadSnippets(): void {
const saved = localStorage.getItem('ts-playground-snippets');
if (saved) {
const entries = JSON.parse(saved);
this.snippets = new Map(entries);
}
}
}
// ๐ Initialize the playground
const playground = new TypeScriptPlayground();
// ๐ฅ HMR support
if (import.meta.hot) {
import.meta.hot.accept(() => {
playground.renderPlayground();
});
}
๐ Key Takeaways
Youโve learned so much about Vite! Hereโs what you can now do:
- โ Set up Vite with TypeScript with lightning-fast builds ๐ช
- โ Configure advanced plugins and optimizations ๐ก๏ธ
- โ Implement HMR for instant development feedback ๐ฏ
- โ Debug build issues like a pro ๐
- โ Build production-ready apps with TypeScript and Vite! ๐
Remember: Vite is your development superpower! It makes TypeScript development feel instant and joyful. ๐ค
๐ค Next Steps
Congratulations! ๐ Youโve mastered Vite with TypeScript!
Hereโs what to do next:
- ๐ป Build a project using Vite + TypeScript
- ๐งฉ Explore Vite plugins for your framework (React, Vue, Svelte)
- ๐ Learn about advanced build optimizations
- ๐ Share your fast development experience with others!
Remember: Every TypeScript expert was once waiting for slow webpack builds. Now you have the speed of Vite! Keep coding, keep learning, and most importantly, enjoy the instant feedback! ๐
Happy coding! ๐๐โจ