Vite 构建工具

从「手工作坊」到「智能工厂」—— 前端工程化的核心利器

01 构建工具是什么

🏭 工厂类比:构建工具 = 自动化组装线

你写的前端代码就像原材料(钢板、螺丝、电线),但用户浏览器需要的是成品(一辆车)。

没有构建工具 = 手工作坊:工人一个一个拧螺丝(手动管理 script 标签、手动压缩、手动兼容浏览器)→ 慢、易出错。

有了构建工具 = 自动化工厂:原材料上流水线 → 自动切割、焊接、质检、打包 → 成品出厂。

为什么不能直接写 HTML?

一个小项目当然可以直接写 HTML。但制造业仪表盘这样的项目通常涉及:

没有构建工具时的痛点
问题具体表现构建工具的解决方案
模块化几十个 JS 文件,用 <script> 一个一个引入,顺序还不能错import/export 自动管理依赖
新语法兼容用了 ES6+ 语法,IE/旧浏览器不认自动转译成 ES5
代码压缩上线时手动删除空格和注释自动 minify,体积减小 60%+
样式处理Sass/Less 写完后要手动编译成 CSS自动预处理并注入
资源优化图片没有压缩、没有缓存控制自动 hash 命名、懒加载

构建工具做了什么?

📝 源代码
Vue/Sass/TS/JSX
🔧 编译转换
TypeScript→JS
Sass→CSS
📦 模块打包
import/export
合并/拆分
✂️ 优化压缩
Tree Shaking
Minify
🚀 产物输出
dist/
可直接部署
💡 一句话总结

构建工具 = 把你写的「开发友好」的源代码,自动转换成「浏览器能高效运行」的生产代码。

02 Webpack vs Vite

🏭 工厂类比:老式工厂 vs 现代工厂

Webpack = 老式工厂:接了 1000 个订单,要把所有零件全部组装完才能发货。启动慢(全量打包),但最终产物很可靠。

Vite = 现代工厂:客户要哪个零件,现场马上做哪个(按需编译)。启动极快(利用浏览器原生 ES Module),开发体验丝滑。

⚔️ 核心对比
对比维度Webpack 老式工厂Vite 现代工厂
开发启动慢(几十秒~几分钟)
全部文件打包完才能启动
极快(毫秒级)
不打包,按需编译
热更新 (HMR)改一行 → 重新打包整块改一行 → 只替换那一个模块
底层引擎自研打包器开发:esbuild(Go语言,快10~100倍)
生产:Rollup
配置复杂度高(webpack.config.js 很长)低(开箱即用,极少配置)
生态成熟度非常成熟(10年历史)快速追赶(2020年发布,Vue/React 官方推荐)
适用场景老项目维护、复杂定制需求新项目首选、所有现代前端项目

为什么 Vite 这么快?

Webpack 启动流程

1. 读取 webpack.config.js

2. 从 entry 出发,递归解析所有 import

3. 把所有模块打包成 bundle.js

4. 启动 dev server

→ 项目越大,启动越慢(线性增长)

Vite 启动流程

1. 启动 dev server(瞬间)

2. 浏览器请求首页 → 返回 index.html

3. 遇到 <script type="module"> → 按需编译

4. 只编译当前页面用到的文件

→ 不管项目多大,启动都很快

Webpack 打包模式(传统)原理图
// Webpack: 启动时打包所有文件
Entry → ModuleA → ModuleB → ModuleC → ...
     → ModuleD → ModuleE → ...
     → ModuleF → ModuleG → ModuleH → ...
                                    ↓
                            bundle.js (3MB)
                                    ↓
                            启动 dev server  ← 要等几十秒
Vite 按需编译模式(现代)原理图
// Vite: 浏览器请求什么,才编译什么
浏览器请求 index.html
  → 加载 main.js
    → import Dashboard.vue  ← 只编译这一个文件
    → import api.js         ← 只编译这一个文件

启动时间:~300ms不管项目多大
💡 制造业场景类比

Webpack = 每天开工前,先把所有原材料全部加工成半成品,再开始组装。准备时间长,但后续稳定。

Vite = 丰田精益生产(Just-In-Time)。需要什么零件,现生产什么。零库存、零等待。

03 Vite 项目搭建

3.1 创建项目

终端命令Bash
# 创建 Vite 项目(交互式选择框架)
$ npm create vite@latest my-dashboard

# 或者直接指定模板
$ npm create vite@latest my-dashboard -- --template vue
$ npm create vite@latest my-dashboard -- --template react
▶ 终端输出
Need to install the following packages:
create-vite@5.4.0
Ok to proceed? (y) y
Scaffolding project in /Users/new/my-dashboard...
Done. Now run:
cd my-dashboard
npm install
npm run dev

3.2 安装依赖 & 启动

安装依赖并启动开发服务器Bash
$ cd my-dashboard
$ npm install
$ npm run dev
▶ npm install 输出
added 32 packages in 3s
7 packages are looking for funding
run `npm fund` for details
▶ npm run dev 输出
VITE v5.4.0 ready in 287 ms
Local: http://localhost:5173/
Network: http://192.168.1.100:5173/
➜ press h + enter to show help
🏭 287ms 是什么概念?

Webpack 项目启动通常要 10~60 秒。Vite 只要 不到 1 秒

类比:老式工厂每天开机预热要 30 分钟,现代工厂按下开关就能干活。

3.3 项目结构

my-dashboard/ ├── index.html # 入口 HTML(Vite 以此为入口,不是 main.js) ├── package.json # 项目配置 & 依赖声明 ├── vite.config.js # Vite 配置文件(核心!) ├── public/ # 静态资源(不参与编译) │ └── favicon.ico ├── src/ # 源代码目录 │ ├── main.js # 应用入口 │ ├── App.vue # 根组件 │ ├── assets/ # 静态资源(会被编译优化) │ │ └── logo.svg │ └── components/ # 组件目录 │ └── HelloWorld.vue └── node_modules/ # 依赖包(npm install 生成)
💡 Vite vs Webpack 的关键区别

Webpack 入口是 JS 文件(entry: './src/main.js'),Vite 入口是 HTML 文件(index.html)。

这是因为 Vite 利用浏览器原生 ES Module,从 HTML 开始加载,按需引入 JS。

3.4 package.json 命令

package.jsonJSON
{
  "name": "my-dashboard",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",              // 开发服务器(热更新)
    "build": "vite build",      // 生产构建(输出到 dist/)
    "preview": "vite preview"   // 本地预览生产构建
  }
}

04 配置文件 vite.config.js

🏭 工厂类比:vite.config.js = 工厂的「生产工艺单」

默认配置就像标准化流程,开箱即用。但制造业项目通常需要定制:API代理(原料从哪进货)、路径别名(零件编号简写)、插件(加装特殊设备)。

4.1 制造业仪表盘的完整配置

vite.config.js — 制造业仪表盘配置JavaScript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  // ① 插件 —— 扩展 Vite 能力
  plugins: [
    vue(),  // 让 Vite 能解析 .vue 文件
  ],

  // ② 开发服务器配置
  server: {
    port: 3000,           // 改为 3000 端口(默认 5173)
    open: true,            // 启动时自动打开浏览器

    // ③ API 代理 —— 解决跨域问题
    proxy: {
      // 前端请求 /api/machine/status
      // → 自动转发到 http://localhost:8080/api/machine/status
      '/api': {
        target: 'http://localhost:8080',  // 后端服务地址
        changeOrigin: true,   // 修改请求头中的 Origin
        // rewrite: (path) => path.replace(/^\/api/, '')
        // ↑ 如果后端接口没有 /api 前缀,取消注释
      },
    },
  },

  // ④ 路径别名 —— 简化 import 路径
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
      // 使用前:import Dashboard from '../../../components/Dashboard.vue'
      // 使用后:import Dashboard from '@/components/Dashboard.vue'
    },
  },

  // ⑤ 生产构建优化
  build: {
    outDir: 'dist',            // 输出目录
    sourcemap: false,         // 生产环境不生成 sourcemap
    chunkSizeWarningLimit: 1000, // chunk 大小警告阈值(KB)
    rollupOptions: {
      output: {
        // 分包策略 —— 按依赖拆分,利用浏览器缓存
        manualChunks: {
          'vue-vendor': ['vue', 'vue-router', 'pinia'],
          'echarts-vendor': ['echarts'],
        },
      },
    },
  },
})

4.2 API 代理详解

🏭 代理 = 工厂的「采购代办处」

前端(车间 A)需要从后端(仓库 B)拿数据,但浏览器有跨域限制(不同部门不能直接对接)。

Vite 代理 = 中间设一个「采购代办处」,前端请求发给代办处(同域),代办处再去后端取数据。

前端代码中的 API 请求JavaScript
// 开发环境中,请求会经过 Vite 代理

// 前端发起:
fetch('/api/machine/status')
// 实际请求 → http://localhost:8080/api/machine/status

// 另一个例子:获取 OEE 数据
fetch('/api/oee/realtime?line=L1')
// 实际请求 → http://localhost:8080/api/oee/realtime?line=L1
⚠️ 注意

代理只在开发环境(npm run dev)有效。生产环境需要 Nginx 等反向代理来处理。

4.3 路径别名效果

没有别名 vs 有别名对比
// ❌ 没有别名 —— 相对路径地狱
import Dashboard from '../../../components/Dashboard.vue'
import { getOEE } from '../../api/oee'
import formatTime from '../../utils/format'

// ✅ 有别名 @ → src/
import Dashboard from '@/components/Dashboard.vue'
import { getOEE } from '@/api/oee'
import formatTime from '@/utils/format'

05 开发 vs 生产

🏭 工厂类比

npm run dev = 草稿模式:设计师在画草图,可以随时擦掉重画,有辅助线(source map),速度优先。

npm run build = 定稿发布:把草图变成印刷品。去掉辅助线(minify),只保留必要内容(tree shaking),加上防伪标记(hash)。

⚔️ 开发模式 vs 生产模式
特性dev 草稿模式build 定稿发布
代码压缩❌ 不压缩(方便调试)✅ 压缩(变量名缩短、删除空格)
Source Map✅ 有(浏览器能看到源码)❌ 没有(保护源码)
Tree Shaking不需要✅ 删除未使用的代码
文件 Hash不需要✅ app.3a7b2c.js(缓存控制)
热更新 (HMR)✅ 改代码立即生效❌ 不适用
API 代理✅ vite.config.js 中的 proxy❌ 需要 Nginx 配置
用途本地开发调试部署到服务器给用户访问

5.1 npm run dev — 开发模式

启动开发服务器Bash
$ npm run dev
▶ 终端输出
VITE v5.4.0 ready in 287 ms
Local: http://localhost:5173/
watching for file changes...
🔥 热更新 (HMR) 体验

修改 src/components/Dashboard.vue 中的文字:

- <h1>设备监控</h1>
+ <h1>产线实时监控</h1>

保存文件后,浏览器自动更新,不需要刷新页面!保留了页面状态(如已选中的标签页、表单输入等)。

5.2 npm run build — 生产构建

构建生产版本Bash
$ npm run build
▶ 构建输出
vite v5.4.0 building for production...
42 modules transformed.
dist/index.html 0.46 kB │ gzip: 0.30 kB
dist/assets/vue-vendor-Di43x2aC.js 52.31 kB │ gzip: 18.44 kB
dist/assets/echarts-vendor-Bx9kL1pQ.js 341.28 kB │ gzip: 98.17 kB
dist/assets/index-Cr4t7sX1.js 12.84 kB │ gzip: 4.72 kB
dist/assets/index-Bm9kR2wY.css 8.92 kB │ gzip: 3.15 kB
✓ built in 2.31s
🏭 读懂构建产物

vue-vendor-Di43x2aC.js — Vue 框架代码。文件名中的 Di43x2aC 是内容哈希:代码没变,哈希不变(浏览器缓存有效);代码变了,哈希变了(用户拿到最新版)。

gzip: 98.17 kB — 实际传输大小。ECharts 从 341KB 压缩到 98KB,节省 71%。

5.3 Tree Shaking 详解

Tree Shaking = 摇树掉落枯叶原理
// utils.js — 导出了 3 个函数
export function formatTime(t) { /* ... */ }
export function parseData(d) { /* ... */ }
export function generateReport(r) { /* ... 500行 ... */ }

// Dashboard.vue — 只用了 2 个
import { formatTime, parseData } from '@/utils'

// 生产构建时:
// generateReport 被自动删除(摇掉了)
// 结果:打包体积减小,加载速度更快

06 与 Vue/React 配合

Vite 对 Vue 和 React 都有一等支持。创建项目时选择对应模板即可。

6.1 Vue 3 项目

创建 Vue 3 项目Bash
# 方式一:交互式选择 Vue
$ npm create vite@latest factory-dashboard -- --template vue

# 方式二:使用 Vue 官方脚手架(内含更多预设)
$ npm create vue@latest factory-dashboard
vite.config.js — Vue 3JavaScript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
})
src/App.vue — 制造业仪表盘示例Vue
<template>
  <div class="dashboard">
    <h1>产线实时监控</h1>
    <OEEChart :line-id="'L1'" />
    <MachineStatus />
  </div>
</template>

<script setup>
import OEEChart from '@/components/OEEChart.vue'
import MachineStatus from '@/components/MachineStatus.vue'
</script>

6.2 React 项目

创建 React 项目Bash
# 使用 JavaScript 模板
$ npm create vite@latest factory-dashboard -- --template react

# 使用 TypeScript 模板
$ npm create vite@latest factory-dashboard -- --template react-ts
vite.config.js — ReactJavaScript
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
})
src/App.jsx — 制造业仪表盘示例React JSX
import { useState } from 'react'
import OEEChart from '@/components/OEEChart'
import MachineStatus from '@/components/MachineStatus'

function App() {
  const [lineId, setLineId] = useState('L1')

  return (
    <div className="dashboard">
      <h1>产线实时监控</h1>
      <OEEChart lineId={lineId} />
      <MachineStatus />
    </div>
  )
}

export default App
框架模板名插件官方脚手架
Vue 3--template vue@vitejs/plugin-vuenpm create vue@latest
React--template react@vitejs/plugin-reactVite 默认即可
Vue 3 + TS--template vue-ts同上 + TypeScriptnpm create vue@latest
React + TS--template react-ts同上 + TypeScriptVite 默认即可

07 常用插件

🏭 插件 = 工厂的「附加设备」

基础工厂(Vite)能做基本加工,但你可以加装设备:自动包装机(压缩)、质量检测仪(代码分析)、特殊焊接器(Vue/React 解析)。

常用插件一览
插件作用使用场景
@vitejs/plugin-vue 让 Vite 能解析 .vue 单文件组件 Vue 3 项目必装
@vitejs/plugin-react 让 Vite 支持 React JSX 语法 React 项目必装
vite-plugin-compression 构建时生成 .gz 压缩文件 生产部署优化,Nginx 可直接提供 gzip
rollup-plugin-visualizer 生成打包体积可视化分析图 优化包体积,发现大依赖
vite-plugin-svg-icons SVG 雪碧图,图标按需加载 制造业项目大量设备图标
@vitejs/plugin-legacy 为旧浏览器生成兼容代码 需要支持 IE 或内网旧浏览器

7.1 完整插件配置示例

vite.config.js — 常用插件配置JavaScript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import compression from 'vite-plugin-compression'
import { visualizer } from 'rollup-plugin-visualizer'

export default defineConfig({
  plugins: [
    // ① Vue 支持
    vue(),

    // ② Gzip 压缩
    compression({
      algorithm: 'gzip',
      threshold: 10240,  // 大于 10KB 的文件才压缩
    }),

    // ③ 打包分析(构建后生成 stats.html)
    visualizer({
      open: true,        // 构建完自动打开分析页面
      filename: 'stats.html',
    }),
  ],
})
安装插件Bash
$ npm install -D vite-plugin-compression rollup-plugin-visualizer
▶ 安装输出
added 8 packages in 2s

7.2 打包分析效果

📊 rollup-plugin-visualizer 生成的体积分析

构建完成后会自动打开 stats.html,以矩形树图形式展示每个依赖的体积占比:

echarts
341 KB (62%)
vue
52 KB (9%)
vue-router
18 KB
pinia
12 KB
业务代码
28 KB

一眼看出 ECharts 占了大头 → 可以考虑按需引入来优化。

08 面试高频考点

以下 6 道题覆盖了 Vite/Webpack 面试中最常问的知识点。

1 Vite 为什么比 Webpack 快?底层原理是什么?

核心原因:开发阶段不打包。

1. 利用浏览器原生 ES Module:Vite 启动时不打包所有文件,而是启动一个 dev server。浏览器通过 <script type="module"> 直接请求所需的模块,Vite 按需编译后返回。

2. 使用 esbuild 预构建:依赖(node_modules)使用 Go 语言编写的 esbuild 进行预构建,比 Webpack 的 JavaScript 打包快 10~100 倍。

3. 强缓存策略:依赖预构建结果会被缓存(node_modules/.vite/),不变就不重新构建。源码部分的请求通过 304 协商缓存。

对比 Webpack:Webpack 启动时需要从 entry 递归解析所有模块的依赖关系,全部打包成 bundle 后才能启动服务。项目越大,启动越慢。

2 HMR(热模块替换)的原理是什么?

HMR = 修改代码后,只替换变化的模块,不刷新整个页面。

工作流程

1. 文件变化:你保存了 Dashboard.vue

2. WebSocket 通知:Vite dev server 通过 WebSocket 告诉浏览器「Dashboard.vue 变了」

3. 请求新模块:浏览器只重新请求这一个文件的最新版本(带时间戳缓存失效)

4. 替换执行:框架(Vue/React)的 HMR runtime 接收新模块,替换旧的,保持页面状态不变

为什么比 Webpack 快:Webpack HMR 需要重新打包受影响的 chunk;Vite 只需要重新编译那一个文件,不需要重新计算依赖图。

HMR 原理图流程
// WebSocket 通信
Server → Client: { "type": "update", "path": "/src/components/Dashboard.vue" }

// 浏览器收到后
import('/src/components/Dashboard.vue?t=1718012345')  // 带时间戳,绕过缓存
  .then(newModule => {
    // Vue HMR runtime 自动替换组件
    hot.accept(newModule)
  })
3 什么是 Tree Shaking?它的工作原理是什么?

Tree Shaking = 摇掉没用到的代码,减小打包体积。

前提条件:使用 ES Module(import/export),不能用 CommonJS(require/module.exports)。因为 ES Module 是静态的,打包工具可以在编译时分析出哪些导出没被使用。

工作原理

1. Rollup(Vite 的生产打包引擎)从入口文件开始,分析所有 import 语句

2. 构建「模块依赖图」

3. 标记所有被使用的 export

4. 删除未被标记的代码(Dead Code Elimination)

Tree Shaking 示例JavaScript
// 📦 utils.js
export function used() { return '我被用到了' }       // ✅ 保留
export function unused() { return '没被用到' }     // ❌ 删除

// 📄 main.js
import { used } from './utils'  // 只导入了 used
console.log(used())                // unused 不会被包含在产物中
4 什么是 Code Splitting(代码分割)?怎么配置?

Code Splitting = 把一个大包拆成多个小包,按需加载。

类比:不把整本百科全书一次性搬过来,而是需要查「ECharts」时再去拿那一册。

方式一:动态 import(推荐)

// 路由懒加载 —— 只有点击菜单时才加载对应页面
const routes = [
  {
    path: '/dashboard',
    component: () => import('@/views/Dashboard.vue')  // 懒加载
  },
  {
    path: '/report',
    component: () => import('@/views/Report.vue')      // 懒加载
  }
]

方式二:manualChunks(vite.config.js)

// vite.config.js — 手动分包
build: {
  rollupOptions: {
    output: {
      manualChunks: {
        'vue-vendor': ['vue', 'vue-router'],
        'echarts': ['echarts'],
      }
    }
  }
}

好处:首屏只加载核心代码(Vue + 首页),ECharts 等大库按需加载。首屏加载从 500KB 降到 100KB。

5 Vite 常见配置项有哪些?各自的用途?
配置项用途示例
server.port开发服务器端口port: 3000
server.proxyAPI 代理(解决跨域)proxy: { '/api': { target: '...' } }
server.open启动时自动打开浏览器open: true
resolve.alias路径别名'@': path.resolve(__dirname, 'src')
build.outDir构建输出目录outDir: 'dist'
build.sourcemap是否生成 sourcemapsourcemap: true
build.rollupOptionsRollup 构建选项(分包等)manualChunks: { ... }
plugins插件列表[vue()]
base公共基础路径base: '/dashboard/'
css.preprocessorOptionsCSS 预处理配置scss: { additionalData: '...' }
6 Webpack 的核心概念有哪些?(面试必问)

虽然 Vite 越来越流行,但 Webpack 仍然是面试高频考点,很多老项目也在用。5 个核心概念:

概念作用类比示例
Entry
入口
打包的起点,Webpack 从这里开始分析依赖 工厂的起始工位 entry: './src/main.js'
Output
输出
打包后的文件存放到哪里,叫什么名字 成品仓库地址 output: { path: 'dist/', filename: 'bundle.[hash].js' }
Loader
加载器
让 Webpack 能处理非 JS 文件(CSS、图片、Vue 等) 特殊加工设备 module: { rules: [{ test: /\.vue$/, loader: 'vue-loader' }] }
Plugin
插件
扩展 Webpack 功能(压缩、生成 HTML、环境变量) 工厂附加设备 plugins: [new HtmlWebpackPlugin()]
Mode
模式
development 或 production,自动启用对应优化 草稿模式 / 定稿模式 mode: 'production'
webpack.config.js 简明示例JavaScript
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  mode: 'development',          // 模式
  entry: './src/main.js',        // 入口
  output: {                       // 输出
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.[contenthash:8].js',
  },
  module: {                        // Loader
    rules: [
      { test: /\.vue$/, loader: 'vue-loader' },
      { test: /\.css$/, use: ['style-loader', 'css-loader'] },
    ],
  },
  plugins: [                       // Plugin
    new HtmlWebpackPlugin({ template: './index.html' }),
  ],
}
💡 面试技巧

当面试官问 Webpack 时,你可以主动提到:「Webpack 的概念我也熟悉,不过新项目我会优先选 Vite,因为它解决了 Webpack 最大的痛点——开发启动慢的问题。」

中际旭创 · 制造业全栈工程师培训 · 第 11 课

Vite 构建工具 — 让前端开发从「手工作坊」升级为「智能工厂」