Vite学习笔记

学习时间:2025年4月6日

官网:https://vitejs.cn/vite3-cn/

1 简介

Vite 是一个基于 ES Modules(ESM)的前端开发与构建工具,由 Vue 作者尤雨溪(Evan You)开发。

它主要解决了传统打包工具(如 Webpack)冷启动慢热更新慢 的问题。

特性 Vite Webpack
启动速度 秒级(原生模块加载) 慢(全量打包)
热更新速度 快(按需) 慢(整个模块依赖图)
配置复杂度 简洁,开箱即用 配置较多
插件系统 基于 Rollup,轻量强大 更成熟但重
社区生态 快速增长中 成熟稳定

2 快速开始

2.1 搭建Vite项目

使用NPM搭建:

1
npm create vite@latest

按照提示操作即可:

  • 输入项目名称:
1
2
3
◆  Project name:
│ vite-test

  • 选择框架,这里选择Vue框架
1
2
3
4
5
6
7
8
9
10
11
12
◆  Select a framework:
│ ○ Vanilla
│ ● Vue
│ ○ React
│ ○ Preact
│ ○ Lit
│ ○ Svelte
│ ○ Solid
│ ○ Qwik
│ ○ Angular
│ ○ Others

  • 选择模板:
1
2
3
4
5
6
◆  Select a variant:
│ ● TypeScript
│ ○ JavaScript
│ ○ Official Vue Starter ↗
│ ○ Nuxt ↗

选项 含义
TypeScript 使用 Vue + TypeScript(类型更安全)
JavaScript 使用 Vue + JavaScript(传统写法)
Official Vue Starter 跳转到官方 Vue Starter 模板,通常是个 GitHub 仓库
Nuxt 跳转到 Nuxt 项目初始化(更重的框架,支持 SSR 等)

这里选择官方Vue Starter模板(脚手架)

  • 选择其他功能:
1
2
3
4
5
6
7
8
9
10
◆  Select features to include in your project: 
│ ◻ TypeScript
│ ◻ JSX Support
│ ◻ Router (SPA development)
│ ◻ Pinia (state management)
│ ◻ Vitest (unit testing)
│ ◻ End-to-End Testing
│ ◻ ESLint (error prevention)
│ ◻ Prettier (code formatting)

选项 含义
TypeScript 启用 TypeScript 支持(默认是 JavaScript)
JSX Support 启用 JSX/TSX 支持(可以写类似 React 那样的语法)
Router (SPA development) 启用 Vue Router,支持单页面应用的路由管理
Pinia (state management) 启用 Pinia,全新的 Vue 官方状态管理库
Vitest (unit testing) 启用单元测试框架 Vitest(Vite 官方测试工具)
End-to-End Testing 启用 E2E 测试,比如使用 Cypress、Playwright 等
ESLint (error prevention) 启用 ESLint,帮助你发现语法错误和代码风格问题
Prettier (code formatting) 启用 Prettier,用来统一格式化代码风格

这里选择TypeScriptRouterPiniaESLintPrettier,以搭建完整的Vue项目.


上述步骤完成后,进入该项目目录,运行:

1
npm install

启动项目:

1
npm run dev

image-20250407210243324

2.2 项目结构

项目结构简化版:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
vite-test/
├─ public/ # 静态资源
├─ src/ # 应用源代码
│ ├─ assets/ # 图片、样式等资源
│ ├─ components/ # 可复用组件
│ ├─ router/ # 路由定义
│ ├─ stores/ # 状态管理(Pinia)
│ ├─ views/ # 页面级组件
│ ├─ App.vue # 根组件
│ └─ main.ts # 应用入口
├─ index.html # 页面入口模板
├─ vite.config.ts # Vite 配置
├─ tsconfig.json # TypeScript 配置
├─ eslint.config.ts # ESLint 配置
├─ .prettierrc.json # Prettier 的配置文件,统一代码格式
└─ package.json # 项目信息 & 依赖

项目根目录中:

名称 说明
.prettierrc.json Prettier 的配置文件,统一代码格式,比如缩进、分号、引号风格等。
index.html 项目入口 HTML,Vite 会把它作为根模板。可以在这里挂载 Vue 应用。
package.json 管理项目依赖、脚本命令、包信息等。
package-lock.json 锁定依赖版本,确保团队所有人依赖一致。
vite.config.ts Vite 的配置文件,比如配置插件、别名路径等。
tsconfig.json TypeScript 编译配置的主入口文件,包含类型检查、路径别名等。
tsconfig.app.json 专门为 Vue 应用写的 TS 配置,通常被 tsconfig.json 引入。
tsconfig.node.json 专门为 node 环境(如配置文件)写的 TS 配置。
eslint.config.ts ESLint 的配置文件,用于规范代码语法、风格。
env.d.ts Vue 类型声明补充文件,告诉 TS 如何识别 .vue 文件。
  • public/:里面的文件不会被打包处理,直接原样拷贝到最终构建结果中(和index.html一级)。
  • src/:核心代码
    • assets/:存放静态资源(图片、CSS、SVG等)。
    • components/:可复用的 Vue 组件模块。
    • router/:用于管理前端路由(URL 与组件的映射)。index.ts 就是路由的主配置文件,定义路径和页面组件之间的关系。
    • stores/:用于管理应用的全局状态(类似 Vuex 的功能)。
    • views/:页面级组件,每个 Vue 页面(例如 /home/about)都应该放在这里。通常和路由配合使用。
    • App.vue:根组件,是所有组件的顶层父组件。main.ts 会把它挂载到 index.html 中的 #app
    • main.ts:应用的启动入口:创建 Vue 实例、安装插件(如 router、Pinia)、挂载 App.vue

2.3 index.html

注意到入口文件index.html位于项目根目录下,而不是像基于Webpack打包的项目(例如使用vue-cli创建的项目)那样,位于public下,这是由于打包机制的不同导致的。

index.html的基本内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!doctype html>  
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>vite-project</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

Vite 项目中index.html 不是一个静态文件,而是整个应用的 入口文件(entry module)。 Vite 会把它当成 构建图的起点(entry point of module graph) 来处理。

当在开发环境中运行Vite项目时:

  • Vite 启动一个开发服务器(Dev Server),监听端口(默认 5173),拦截浏览器访问;
  • 浏览器请求路径/时,Vite 并不是去找一个静态文件,而是找到根目录下的index.html,解析<script type="module" src="/src/main.ts"></script>,自动为这些模块注入 HMR(热更新)客户端,最后返回一个「经过 Vite 转译后的 HTML」;

为什么这么设计:浏览器原生就是从 HTML 启动加载的,所以index.html 就像传统浏览器项目的入口文件,它在开发中也是“模块图的一部分”;

3 环境常量和模式

3.1 环境常量

Vite 在特殊的 import.meta.env 对象下暴露了一些常量。这些常量在开发阶段被定义为全局变量,并在构建阶段被静态替换。

Vite 会自动读取项目根目录(也可以由envDir进行配置,详见[[Vite学习笔记#4.3.3 envDir]])下的 .env 文件,以及以下格式的文件:

1
2
3
4
5
6
7
.env                # 所有模式下都会加载
.env.[mode] # 只有在指定模式下加载

# 例如
.env.production
.env.development
.env.test
文件名 对应模式(mode) 加载时机
.env 所有环境通用 永远加载
.env.development vite --mode development 开发环境时加载
.env.production vite --mode production 构建时加载

Vite 只会将 VITE_ 开头的变量 注入到客户端代码中,并自动将环境变量暴露在 import.meta.env 对象下,作为字符串。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# title
VITE_GLOB_APP_TITLE = '地名地址'

# port
VITE_PORT = 3301

# open 运行 npm run dev 时自动打开浏览器
VITE_OPEN = true

# 是否生成包预览文件
VITE_REPORT = false

# 是否开启gzip压缩
VITE_BUILD_GZIP = false

# 是否删除生产环境 console
VITE_DROP_CONSOLE = false
1
console.log(import.meta.env.VITE_PORT) // "3301"

此外,一些内置环境常量在所有情况下都可用:

  • import.meta.env.MODE: {string} :应用运行的模式。
  • import.meta.env.BASE_URL: {string}:部署应用时的基本 URL,由 base 配置项决定。
  • import.meta.env.PROD: {boolean}:应用是否运行在生产环境(使用 NODE_ENV='production' 运行开发服务器或构建应用时使用 NODE_ENV='production' )。
  • import.meta.env.DEV: {boolean}:应用是否运行在开发环境 (永远与 import.meta.env.PROD相反)。
  • import.meta.env.SSR: {boolean}:应用是否运行在 server 上。

结合TypeScript的智能提示:Vite 在 vite/client.d.ts中为 import.meta.env 提供了类型定义。随着在 .env[mode] 文件中自定义了越来越多的环境变量,可能想要在代码中获取这些以 VITE_ 为前缀的用户自定义环境变量的 TypeScript 智能提示。

要想做到这一点,可以在 /src/types/ 目录下创建一个 vite-env.d.ts 文件,接着按下面这样增加 ImportMetaEnv 的定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
interface ViteTypeOptions {  
strictImportMetaEnv: unknown; // 可以将 ImportMetaEnv 的类型设为严格模式,这样就不允许有未知的键值了
}

interface ImportMetaEnv {
/** 应用端口 */
VITE_APP_PORT: number;
/** 应用名称 */
VITE_APP_NAME: string;
/** API 基础路径(代理前缀) */
VITE_APP_BASE_API: string;
/** API 地址 */
VITE_APP_API_URL: string;
/** 是否开启 Mock 服务 */
VITE_MOCK_DEV_SERVER: boolean;
// 更多的自定义环境常量
// ...
}

interface ImportMeta {
readonly env: ImportMetaEnv;
}

tsconfig.json添加配置"include: ["src/types/vite-env.d.ts"]"即可生效。

3.2 模式

在 Vite 中,mode 就是当前运行项目所处的「环境模式」,比如:

模式名 说明
development 开发环境
production 生产/构建环境
test 测试环境(可自定义)

Vite 会根据指定的 mode 来做以下几件事:

  • 决定加载哪个 .env 文件

例如:

1
vite --mode production

Vite 会按顺序加载这三个文件:.env.env.production.env.production.local,从中读取所有以 VITE_ 开头的环境变量,并注入到 import.meta.env

  • 可在配置文件中做条件判断
1
2
3
4
5
export default defineConfig(({ mode }) => {
if (mode === 'development') {
// 做一些只在开发环境的配置
}
})
  • 注入到前端代码中
1
2
console.log(import.meta.env.MODE); // 当前模式名
console.log(import.meta.env.VITE_API_URL); // 在 .env 文件中定义的变量

mode的设置:

  • 默认情况
1
2
vite        # 默认使用 development 模式
vite build # 默认使用 production 模式
  • 显式指定
1
2
vite --mode test
vite build --mode staging

可以为每个模式分别准备 .env.test.env.staging 文件。

4 配置

4.1 基本结构

当以命令行方式运行 vite 时,Vite 会自动解析项目根目录下名为 vite.config.js 的配置文件,使用 TypeScript 时推荐 vite.config.ts

最基本的写法:

1
2
3
4
5
6
// 最基本写法
import { defineConfig } from 'vite'

export default defineConfig({
// 配置项写在这里
})

配置结构总览:

1
2
3
4
5
6
7
8
9
10
11
12
defineConfig({
root, // 项目根目录(默认当前目录)
base, // 公共路径(默认 '/')
resolve, // 路径别名等解析设置
server, // 开发服务器设置
build, // 构建配置
plugins, // 插件数组
css, // CSS 相关配置
define, // 全局常量定义
envDir, // 环境变量文件夹
envPrefix, // 哪些变量会被导入 import.meta.env
})

4.2 使用环境变量

环境变量通常可以从 process.env 获得。

注意 Vite 默认是不加载 .env 文件的,因为这些文件需要在执行完 Vite 配置后才能确定加载哪一个,举个例子,rootenvDir 选项会影响加载行为。不过当的确需要时,可以使用 Vite 导出的 loadEnv 函数来加载指定的 .env 文件。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { defineConfig, loadEnv } from 'vite'

export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd());

return {
server: {
port: parseInt(env.VITE_PORT), // 注意需要类型转换
open: env.VITE_OPEN === 'true'
},
define: {
__APP_VERSION__: JSON.stringify(env.VITE_APP_VERSION)
}
}
})

其中:

  • loadEnv(mode, process.cwd())

    • mode: 当前运行的模式(比如 'development''production'
    • process.cwd(): 当前项目的根目录路径
    • 作用:从根目录下读取 .env 文件 + .env.{mode} 文件中的变量,组合成一个对象并返回
  • 返回的env结构:是一个普通的对象,所有值都是字符串

    • {
        VITE_API_BASE: '/api',
        VITE_PORT: '3000',
        VITE_OPEN: 'true',
        VITE_APP_VERSION: '1.0.0'
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12

      ### 4.3 共享选项

      #### 4.3.1 base

      - **类型:** `string`
      - **默认:** `/`

      表示构建后资源的公共路径前缀,例如:

      ```typescript
      base: '/my-app/'

几种不同的部署配置:

配置 建议使用场景
base: '/' 绝大多数在线部署
base: './' 离线 HTML、本地打开、内嵌式部署
base: '/my-app/' 网站部署在子路径 /my-app/

4.3.2 mode

  • 类型: string
  • 默认: 'development' 用于开发,'production' 用于构建

4.3.3 envDir

  • 类型: string | false
  • 默认: root

用于加载 .env 文件的目录。可以是一个绝对路径,也可以是相对于项目根的路径。设置为 false 将禁用 .env 文件的加载。

1
envDir: "root"

4.3.4 define

  • 类型: Record<string, any>

定义全局常量替换方式。其中每项在开发环境下会被定义在全局,而在构建时被静态替换。

Vite 使用 esbuild define 来进行替换,因此值的表达式必须是一个包含 JSON 可序列化值(null、boolean、number、string、array 或 object)或单一标识符的字符串。对于非字符串值,Vite 将自动使用 JSON.stringify 将其转换为字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
import { name, version, engines, dependencies, devDependencies } from "./package.json";  

// 平台的名称、版本、运行所需的 node 版本、依赖、构建时间的类型提示
const __APP_INFO__ = {
pkg: { name, version, engines, dependencies, devDependencies },
buildTimestamp: Date.now(),
};

export default defineConfig(() => {
define: {
__APP_INFO__: JSON.stringify(__APP_INFO__),
},
});

4.3.5 plugins

  • 类型: (Plugin | Plugin[] | Promise<Plugin | Plugin[]>)[]

需要用到的插件数组。

1
2
3
export default defineConfig({  
plugins: [vue(), viteSingleFile()]
})

4.3.6 resovle.alias

表示路径别名。

1
2
3
4
5
6
7
8
9
10
11
12
import path from 'path'

export default defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'), // 用 @ 代表 src/ 目录
'components': path.resolve(__dirname, 'src/components'), //用 components 快捷访问组件目录
"vue-i18n": "vue-i18n/dist/vue-i18n.cjs.js",
'jquery': 'jquery/dist/jquery.slim.min.js'
}
}
})

这样就可以以下面的方式引入组件:

1
2
3
4
5
import Hello from '@/components/Hello.vue'

// 或者

import Hello from 'components/Hello.vue'

4.3.7 css.preprocessorOptions[extension].additionalData

  • 类型: Record<string, object>

指定传递给 CSS 预处理器的选项,同时为每一段样式内容添加额外的代码。

1
2
3
4
5
6
7
8
css: {  
preprocessorOptions: {
scss: {
// 在编译每个 .scss 文件前,会自动注入:
additionalData: `@use "@/styles/variables.scss" as *;`,
},
},
}

使用:

1
2
// variables.scss
$primary-color: #42b983;
1
2
3
4
5
6
// 某个组件
<style lang="scss" scoped>
.button {
color: $primary-color;
}
</style>

4.4 服务器选项 server

server选项仅用于开发环境。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server: {  
host: "0.0.0.0",
port: viteEnv.VITE_PORT,
open: viteEnv.VITE_OPEN,
cors: true,
proxy: {
"/dev-api": {
target: "http://192.168.30.131:9596",
changeOrigin: true,
rewrite: path => path.replace(/^\/dev-api/, "")
}
},
hmr: true
}

4.4.1 host

  • 类型: string | boolean
  • 默认: 'localhost'

指定服务器应该监听哪个 IP 地址。 如果将此设置为 0.0.0.0 或者 true 将监听所有地址,包括局域网和公网地址。

4.4.2 port

  • 类型: number
  • 默认值: 5173

指定开发服务器端口。注意:如果端口已经被使用,Vite 会自动尝试下一个可用的端口,所以这可能不是开发服务器最终监听的实际端口。

4.4.3 open

  • 类型: boolean | string

开发服务器启动时,自动在浏览器中打开应用程序。

4.4.4 proxy

  • 类型: Record<string, string | ProxyOptions>

为开发服务器配置自定义代理规则。

常用示例

1
2
3
4
5
6
7
proxy: {  
"/dev-api": { // 表示要代理的请求前缀路径,所有以 /dev-api 开头的请求都会被拦截并代理
target: "http://192.168.30.131:9596", // 将请求转发到该地址的服务器(后端)
changeOrigin: true, // 代理请求时,修改请求头中的 Origin 和 Host 为目标地址
rewrite: path => path.replace(/^\/dev-api/, "") // 重写请求路径
}
}

4.5 构建选项 build

4.5.1 outDir

  • 类型: string
  • 默认: dist

指定输出路径(相对于项目根目录)。

1
2
3
build: {
outDir: "airport"
}

上述配置将会打包在项目根目录下的airport文件夹内。

4.5.2 assetsDir

  • 类型: string
  • 默认: assets

指定生成的静态资源(JS、CSS、图片等)放在输出目录( build.outDir)的哪个文件夹下。

1
2
3
build: {
assetsDir: "static"
}

生成的dist目录结构:

1
2
3
4
5
6
dist/
├── index.html
└── static/
├── js/
├── css/
├── img/

4.5.3 chunkSizeWarningLimit

  • 类型: number
  • 默认: 500

规定触发警告的 chunk 大小。(以 kB 为单位)。不影响构建结果,仅提醒你优化打包体积。

4.5.4 minify

  • 类型: boolean | 'terser' | 'esbuild'
  • 默认: 客户端构建默认为'esbuild'(terser压缩更彻底,可配置更多选项),SSR构建默认为 false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
build: {
minify: isProduction ? "terser" : false, // 只在生产环境启用压缩
terserOptions: isProduction
? {
compress: {
keep_infinity: true, // 防止 Infinity 被压缩成 1/0,这可能会导致 Chrome 上的性能问题
drop_console: true, // 生产环境去除 console.log, console.warn, console.error 等
drop_debugger: true, // 生产环境去除 debugger
pure_funcs: ["console.log", "console.info"], // 移除指定的函数调用
},
format: {
comments: false, // 删除注释
},
}
: {},
}

4.5.5 rollupOptions

自定义底层的 Rollup 打包配置。这与从 Rollup 配置文件导出的选项相同,并将与 Vite 的内部 Rollup 选项合并。Rollup文档

示例

1
2
3
4
5
6
7
8
9
build: {
rollupOptions: {
output: {
entryFileNames: "static/js/[name]-[hash].js", // 定义“入口文件”(即main.ts)输出到dist目录时的命名格式
chunkFileNames: "static/js/[name]-[hash].js", // 定义“代码分块文件”(动态导入、依赖拆分出来的模块)的命名规则。
assetFileNames: "static/[ext]/[name]-[hash].[ext]", // 控制静态资源(图片、CSS、字体等)文件的输出路径和命名规则。
}
}
}

最终打包后的dist目录可能如下:

1
2
3
4
5
6
7
8
9
10
11
dist/
├── index.html
└── static/
├── js/
│ ├── main-7c98f3c1.js
│ ├── vendor-2d4c1aa1.js
│ └── LazyView-abc123.js
├── css/
│ └── style-9e8a8d.css
├── png/
│ └── logo-2348f9.png

5 命令行接口

初始化Vite项目后,package.json的默认内容如下:

1
2
3
4
5
6
7
8
9
{
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit & vite build", // 检查ts语法与构建 并行运行
"preview": "vite preview",
"build-only": "vite build",
// ...
}
}

5.1 开发

  • 基本命令:vite
  • 作用:在当前目录下启动 Vite 开发服务器。vite dev 和 vite serve 是 vite 的别名。
  • 选项:略

5.2 构建

  • 基本命令:vite build
  • 作用:构建生产版本。
  • 选项:略

其余命令略。