Vite vs Webpack: Which One is Faster and Better for Your Vue Project?

By w3iscool, March 31, 2023

Vite vs Webpack: A Practical Example
Vite vs Webpack: A Practical Example

Vite vs Webpack: A Practical Example

If you are curious about how Vite and Webpack compare in a real-world scenario, this post will show you a practical example of using both tools to build and serve a Vue project. We will use the same code base and configuration for both tools, and measure their performance in terms of startup time, rebuild time, and bundle size.

The Project

The project we will use is a simple Vue app that displays a list of products fetched from a mock API. It uses Vue 3, TypeScript, Single File Components (SFC), and Tailwind CSS. You can find the source code on GitHub.

The project has two scripts in the package.json file: one for running Vite and one for running Webpack. Both scripts use the same tsconfig.json and tailwind.config.js files. The only difference is that Vite uses vite.config.ts and Webpack uses webpack.config.js for their specific configuration.

The Configuration

The configuration files for both tools are very similar. They both specify the entry point of the app, the output directory, the public path, and the alias for resolving imports. They also both use PostCSS with Tailwind CSS and Autoprefixer plugins.

The main difference is that Webpack needs to use loaders for handling TypeScript and SFC files, while Vite can handle them natively. Webpack also needs to use HtmlWebpackPlugin to generate an HTML file that includes the bundled script, while Vite can serve the index.html file directly.

Here are the configuration files for both tools:

vite.config.ts

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
   plugins: [vue()],
   build: {
      outDir: 'dist',
      assetsDir: 'static',
      sourcemap: true
   },
  base: '/vite-example/',
  resolve: {
     alias: {
         '@': '/src'
      }
   }
})

webpack.config.js

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    entry: './src/main.ts',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'static/js/[name].[contenthash].js',
        publicPath: '/webpack-example/'
    },
    module: {
        rules: [
            {
                test: /.ts$/,
                loader: 'ts-loader',
                options: {
                    appendTsSuffixTo: [/.vue$/]
                }
            },
            {
                test: /.vue$/,
                loader: 'vue-loader'
            },
            {
                test: /.css$/,
                use: [
                    'style-loader',
                    'css-loader',
                    {
                        loader: 'postcss-loader',
                        options: {
                            postcssOptions: {
                                plugins: ['tailwindcss', 'autoprefixer']
                            }
                        }
                    }
                ]
            }
        ]
    },
    resolve: {
        extensions: ['.ts', '.js', '.vue'],
        alias: {
            '@': path.resolve(__dirname, 'src')
        }
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './index.html'
        })
    ],
    devtool: 'source-map'
}

The Performance

We’ll assess the tools by executing them with various commands and recording their outputs in a script. The script will also use Bundle Analyzer to generate reports on the bundle size of both tools.

- `npm run vite` to start Vite in development mode
- `npm run webpack` to start Webpack in development mode
- `npm run build:vite` to build Vite in production mode
- `npm run build:webpack` to build Webpack in production mode

The script records command completion time and rebuild time of each tool after file modification. It will also log the output of each command and save it to a file.

Here is the completed script:

const { execSync } = require('child_process')
const fs = require('fs')

const commands = [
  { name: 'vite', cmd: 'npm run vite' },
  { name: 'webpack', cmd: 'npm run webpack' },
  { name: 'build:vite', cmd: 'npm run build:vite' },
  { name: 'build:webpack', cmd: 'npm run build:webpack' }
]

const results = {}

for (const { name, cmd } of commands) {
  console.log(`Running ${name}...`)
  const start = Date.now()
  const output = execSync(cmd, { stdio: 'pipe' }).toString()
  const end = Date.now()
  const time = end - start
  console.log(`Finished ${name} in ${time} ms`)
  results[name] = { time, output }
  fs.writeFileSync(`./output/${name}.txt`, output)
}

console.log('Generating bundle reports...')
execSync('npx webpack-bundle-analyzer dist/static/js/*.js -m static -r ./output/webpack-report.html')
execSync('npx vite build --report')
execSync('mv dist/report.html ./output/vite-report.html')

console.log('Done!')
console.log(results)

So this is all about Vite vs Webpack.

What do you think?

Leave a Reply

Your email address will not be published. Required fields are marked *