Evolution of Build Tools
MedJavaScript build tools have evolved from nothing to complex bundlers to lightning-fast native ESM tools. Understanding this history explains why we have Vite today and why it's so much faster than Webpack.
Interactive Visualization
1
No Build Step
1995-2010Just write files and upload. Simple but manual and error-prone at scale.
Script tagsManual concatenationFTP upload
Example Code
<!-- index.html - Just include scripts in order -->
<html>
<head>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="app"></div>
<!-- Load in dependency order! -->
<script src="lib/jquery.min.js"></script>
<script src="lib/underscore.min.js"></script>
<script src="js/utils.js"></script>
<script src="js/models.js"></script>
<script src="js/views.js"></script>
<script src="js/app.js"></script>
</body>
</html>
<!-- Deploy: FTP files to server -->
<!-- Minify: Manually paste into online minifier -->
<!-- No source maps, no hot reload, no tree shaking -->Problems Solved
- Simple to understand
- No tooling to learn
- Works everywhere
New Challenges
- Manual script ordering
- No minification/optimization
- Global namespace pollution
- Slow page loads (many requests)
These challenges led to: Task Runners
1 / 5
Key Insight: Vite won by skipping bundling during dev. Native ESM + on-demand transforms = instant feedback.
Key Points
- No Build (1995): Script tags, manual ordering, FTP deploy
- Task Runners (2012): Grunt/Gulp automated concatenation and minification
- Module Bundlers (2014): Webpack enabled import/export in browsers
- Zero-Config (2017): CRA/Parcel hid complexity but were still slow
- Native ESM (2019): Vite/esbuild skip bundling in dev for 100x speed
Code Examples
Era 1: No Build Step
<!-- Just include scripts in order --> <script src="lib/jquery.min.js"></script> <script src="js/utils.js"></script> <script src="js/app.js"></script> <!-- Deploy: FTP to server -->
Simple but manual. No modules, no optimization.
Era 2: Task Runners (Grunt/Gulp)
// Gruntfile.js grunt.initConfig({ concat: { src: ['src/**/*.js'], dest: 'dist/bundle.js' }, uglify: { src: 'dist/bundle.js', dest: 'dist/bundle.min.js' } }); grunt.registerTask('build', ['concat', 'uglify']);
Automated tasks but no module system.
Era 3: Webpack
// webpack.config.js module.exports = { entry: './src/index.js', output: { filename: '[name].[contenthash].js' }, module: { rules: [ { test: /\.js$/, use: 'babel-loader' }, { test: /\.css$/, use: ['style-loader', 'css-loader'] } ] } };
Modules work! But config is complex and builds are slow.
Era 4: Vite (Native ESM)
// vite.config.js - That's it! import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; export default defineConfig({ plugins: [react()] }); // Dev: No bundling, native ES modules // Build: Rollup for production
No bundling in dev = instant startup and HMR.
Common Mistakes
- Ejecting from CRA without understanding Webpack
- Not using code splitting for large apps
- Ignoring bundle size until production
- Using Webpack for new projects when Vite works
Interview Tips
- Explain why Vite is faster than Webpack in development
- Know the difference between dev and production builds
- Understand tree-shaking and how it reduces bundle size
- Be ready to discuss code splitting strategies
- Know what problems esbuild solves (100x faster transforms)