Vite And Webpack

The differences between Vite and Webpack

The differences between Vite and Webpack

2025-11-21

Vite

  • Vite 采用 “约定优于配置” 的理念,默认配置已能满足大部分项目需求
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'

export default defineConfig({
  // 1. 项目根目录(默认process.cwd())
  root: process.cwd(),

  // 2. 项目部署基础路径(默认'/',子路径需配置,如GitHub Pages)
  base: '/',

  // 3. 开发服务器配置
  server: {
    port: 5173, // 开发端口(默认5173)
    open: true, // 自动打开浏览器
    host: '0.0.0.0', // 允许局域网访问
    strictPort: false, // 端口被占用时是否自动切换
    proxy: {
      // 跨域代理
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, ''),
      },
    },
    hmr: {
      // 热更新配置
      overlay: true, // 错误浮层显示
    },
  },

  // 4. 构建配置
  build: {
    outDir: 'dist', // 输出目录(默认dist)
    assetsDir: 'assets', // 静态资源目录(默认assets)
    assetsInlineLimit: 4096, // 小于4kb的资源内嵌为base64
    sourcemap: false, // 是否生成sourcemap(默认false)
    minify: 'esbuild', // 压缩工具(esbuild比terser快10-100倍)
    rollupOptions: {
      // Rollup打包配置(Vite底层用Rollup)
      input: {
        // 多入口配置
        main: resolve(__dirname, 'index.html'),
        admin: resolve(__dirname, 'admin.html'),
      },
      output: {
        // 静态资源命名规则
        chunkFileNames: 'assets/js/[name]-[hash].js',
        entryFileNames: 'assets/js/[name]-[hash].js',
        assetFileNames: 'assets/[ext]/[name]-[hash].[ext]',
      },
    },
  },

  // 5. 插件配置
  plugins: [
    vue(), // Vue3插件
    // 其他常用插件:
    // vite-plugin-html(HTML注入)
    // vite-plugin-svg-icons(SVG图标)
    // vite-plugin-pwa(PWA支持)
  ],

  // 6. 解析配置
  resolve: {
    alias: {
      // 路径别名
      '@': resolve(__dirname, 'src'),
      components: resolve(__dirname, 'src/components'),
    },
    extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'], // 省略后缀
  },

  // 7. CSS配置
  css: {
    modules: {
      // CSS Modules配置
      scopeBehaviour: 'local', // 局部作用域
      generateScopedName: '[name]__[local]___[hash:base64:5]', // 类名生成规则
    },
    preprocessorOptions: {
      // 预处理器配置(无需额外loader)
      scss: {
        additionalData: `@import "@/styles/variables.scss";`, // 全局注入变量
      },
    },
    devSourcemap: true, // 开发环境CSS sourcemap
  },

  // 8. 依赖优化
  optimizeDeps: {
    include: ['lodash-es', 'axios'], // 强制预构建的依赖
    exclude: ['vue-demi'], // 排除预构建的依赖
  },

  // 9. 环境变量配置
  envDir: '.env', // 环境变量文件目录(默认项目根目录)
  envPrefix: 'VITE_', // 环境变量前缀(默认VITE_,如VITE_API_URL)
})

Webpack

  • Webpack 是 “配置驱动” 的打包工具,几乎所有功能都需要手动配置
// webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const webpack = require('webpack')

module.exports = {
  // 1. 入口配置
  entry: {
    main: './src/main.js', // 主入口
    vendor: ['lodash-es', 'axios'], // 第三方依赖入口(拆分用)
  },

  // 2. 输出配置
  output: {
    filename: 'assets/js/[name].[contenthash].js', // 入口文件命名(contenthash缓存)
    chunkFilename: 'assets/js/[name].[contenthash].chunk.js', // chunk文件命名
    path: path.resolve(__dirname, 'dist'), // 输出目录
    publicPath: '/', // 静态资源基础路径
    assetModuleFilename: 'assets/[ext]/[name].[hash].[ext]', // 静态资源命名(Webpack5+)
  },

  // 3. 模块解析配置
  resolve: {
    alias: {
      // 路径别名
      '@': path.resolve(__dirname, 'src'),
      components: path.resolve(__dirname, 'src/components'),
    },
    extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue', '.json'], // 省略后缀
    modules: [path.resolve(__dirname, 'src'), 'node_modules'], // 模块查找路径
  },

  // 4. 模块规则配置(核心:处理不同类型文件)
  module: {
    rules: [
      // 4.1 JavaScript/TypeScript处理(Babel转译)
      {
        test: /\.(js|jsx|ts|tsx)$/,
        exclude: /node_modules/, // 排除node_modules
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              '@babel/preset-env', // ES6+转ES5
              '@babel/preset-react', // React转译
              '@babel/preset-typescript', // TypeScript转译
            ],
            plugins: [
              '@babel/plugin-proposal-class-properties', // 类属性支持
              '@babel/plugin-transform-runtime', // 避免重复代码
            ],
          },
        },
      },

      // 4.2 CSS处理
      {
        test: /\.css$/,
        use: [
          process.env.NODE_ENV === 'development' ? 'style-loader' : MiniCssExtractPlugin.loader, // 开发环境内嵌,生产环境提取
          'css-loader', // 解析CSS
          'postcss-loader', // 自动前缀、CSS优化(需配合postcss.config.js)
        ],
      },

      // 4.3 预处理器(SCSS/Sass)
      {
        test: /\.(scss|sass)$/,
        use: [
          process.env.NODE_ENV === 'development' ? 'style-loader' : MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'sass-loader', // 解析SCSS
        ],
      },

      // 4.4 静态资源处理(Webpack5+ Asset Module)
      {
        test: /\.(png|jpe?g|gif|svg)$/i,
        type: 'asset', // 自动判断:小于8kb内嵌base64,否则输出文件
        parser: {
          dataUrlCondition: {
            maxSize: 8 * 1024, // 8kb阈值
          },
        },
      },

      // 4.5 字体文件处理
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        type: 'asset/resource', // 直接输出文件
      },

      // 4.6 Vue文件处理
      {
        test: /\.vue$/,
        loader: 'vue-loader', // Vue2/Vue3通用
        options: {
          compilerOptions: {
            preserveWhitespace: false, // 去除空格
          },
        },
      },
    ],
  },

  // 5. 插件配置
  plugins: [
    new CleanWebpackPlugin(), // 清理dist目录(Webpack5+可省略,用output.clean)
    new HtmlWebpackPlugin({
      // 生成HTML文件
      template: './public/index.html', // 模板文件
      filename: 'index.html', // 输出文件名
      chunks: ['main', 'vendor'], // 引入的chunk
      minify: {
        // 压缩配置
        removeComments: true, // 移除注释
        collapseWhitespace: true, // 折叠空格
      },
    }),
    new MiniCssExtractPlugin({
      // 提取CSS为单独文件(生产环境)
      filename: 'assets/css/[name].[contenthash].css',
      chunkFilename: 'assets/css/[name].[contenthash].chunk.css',
    }),
    new webpack.DefinePlugin({
      // 注入环境变量
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
      'process.env.API_URL': JSON.stringify('http://localhost:3000'),
    }),
    new webpack.HotModuleReplacementPlugin(), // 热更新插件(开发环境)
  ],

  // 6. 开发工具配置
  devtool: process.env.NODE_ENV === 'development' ? 'eval-cheap-module-source-map' : false,

  // 7. 开发服务器配置(webpack-dev-server)
  devServer: {
    port: 8080, // 开发端口
    open: true, // 自动打开浏览器
    host: '0.0.0.0', // 局域网访问
    hot: true, // 启用热更新
    compress: true, // 启用gzip压缩
    proxy: {
      // 跨域代理
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        pathRewrite: { '^/api': '' },
      },
    },
    historyApiFallback: true, // 支持SPA路由(Vue/React Router)
  },

  // 8. 优化配置(Webpack5+)
  optimization: {
    minimize: process.env.NODE_ENV === 'production', // 生产环境压缩
    minimizer: [
      // 压缩工具
      new TerserPlugin({
        // JS压缩
        parallel: true, // 并行处理
        terserOptions: {
          compress: { drop_console: true }, // 移除console
        },
      }),
      new CssMinimizerPlugin(), // CSS压缩
    ],
    splitChunks: {
      // 代码分割(拆分第三方依赖和公共代码)
      chunks: 'all', // 对所有chunk生效
      cacheGroups: {
        vendor: {
          // 第三方依赖
          test: /[\\/]node_modules[\\/]/,
          name: 'vendor',
          priority: 10, // 优先级
          reuseExistingChunk: true, // 复用已存在的chunk
        },
        common: {
          // 公共代码
          name: 'common',
          minChunks: 2, // 至少被2个模块引用
          priority: 5,
          reuseExistingChunk: true,
        },
      },
    },
    runtimeChunk: 'single', // 单独提取运行时代码(避免缓存失效)
  },

  // 9. 模式配置(development/production)
  mode: process.env.NODE_ENV || 'development',
}

Vite vs Webpack

对比维度ViteWebpack
核心原理开发环境用 ES Module 原生加载(无需打包),生产环境用 Rollup 打包全程 依赖图打包(递归解析所有模块,生成 chunk)
开发启动速度极快(毫秒级),无需等待打包较慢(大型项目需几十秒),需打包所有模块
热更新(HMR)原生 ES Module HMR,速度快需 HMR 插件,依赖打包重建,速度较慢
配置复杂度低(约定优于配置,默认支持多数场景)高(需手动配置 loader、plugin、优化规则)
打包工具生产环境用 Rollup(比 Webpack 轻量)自带打包引擎(功能强但笨重)
静态资源处理原生支持(无需配置 loader)需配置 Asset Module 或 file-loader/url-loader
CSS 处理原生支持 CSS/SCSS/LESS(无需 loader)需配置 style-loader/css-loader/sass-loader
兼容性仅支持 现代浏览器(ES6+)支持旧浏览器(需 Babel 转译 ES5)
生态插件生态较小,但兼容 Rollup 插件生态庞大,插件丰富(覆盖所有场景)
适用场景现代前端项目(Vue/React/TS)、中小型项目复杂项目(多入口、SSR、微前端)、需兼容旧浏览器
默认优化预构建第三方依赖(esbuild)、缓存需手动配置 splitChunks、runtimeChunk 等
错误提示清晰(原生 ES Module 错误定位)较模糊(需 devtool 配置优化)

总结

  • Vite 是下一代构建工具,主打 “快” 和 “简洁”,适合现代浏览器环境的项目,尤其 Vue/React 单页应用。
  • Webpack 是成熟的构建工具,主打 “灵活” 和 “全能”,适合复杂场景或需要兼容旧浏览器的项目