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,用来统一格式化代码风格

这里选择TypeScript,Router,Pinia,ESLint和Prettier,以搭建完整的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/:里面的文件不会被打包处理,直接原样拷贝到最终构建结果中。
  • 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

views和components的区别

项目目录 含义 特点 典型用途
views/pages/ 视图级组件(页面) 通常与路由一一对应 首页、详情页、设置页、地图页
components/ 组件(可复用) 通常是页面中的小模块,可以被多个页面复用 按钮、图表、导航栏、表单、卡片

views(或 pages)目录通常用于存放页面组件。每个 view 一般对应一个完整的路由页面

例如:

1
2
3
// router/index.ts
import HomeView from '@/views/HomeView.vue'
import FlightDetailView from '@/views/FlightDetailView.vue'

这些views通常在 <router-view /> 里进行切换。


components 目录用于存放可复用的小组件。它们一般不会直接出现在路由中,而是被 views 中的页面组件引用。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- HomeView.vue -->
<template>
<div>
<Banner />
<FlightCard />
<FlightCard />
</div>
</template>

<script setup>
import Banner from '@/components/Banner.vue'
import FlightCard from '@/components/FlightCard.vue'
</script>

一个推荐的组织结构:

1
2
3
4
5
6
7
8
9
10
src/
├── views/
│ └── Home/
│ ├── index.vue
│ └── components/ # view的私有组件
│ ├── SummaryChart.vue
│ └── FlightCard.vue
├── components/ # 可以复用的公共组件
│ ├── NavBar.vue
│ └── LoadingSpinner.vue

2.3 基本文件

2.3.1 main.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 引入全局样式文件。所有页面都会应用这些样式
import './assets/main.css'

// 从 Vue 包中引入 createApp 函数,用来创建 Vue 应用实例
import { createApp } from 'vue'

// 引入 Pinia,这是 Vue 3 推荐的状态管理库,类似 Vuex。
import { createPinia } from 'pinia'

// 引入根组件 App.vue,这是整个应用的主组件(像一个壳子,里面包着所有页面和组件)。
import App from './App.vue'

// 引入定义的路由配置(来自 src/router/index.ts),这个东西决定了页面跳转的规则。
import router from './router'

// 调用 createApp 创建一个 Vue 应用实例,传入根组件 App.vue。
const app = createApp(App)

// 安装 Pinia 插件(管理全局状态)。
app.use(createPinia())

// 安装路由插件,让 Vue 应用可以根据 URL 显示不同页面。
app.use(router)

// 把 Vue 应用“挂载”到 `index.html` 里的app标签上
app.mount('#app')

从这一刻开始,Vue 就接管了这个 DOM 元素,页面开始运行。

也可以写成链式调用的方式:

1
app.use(createPinia()).use(router).mount('#app');

整体流程:

1
创建Vue应用实例 --> 加载插件(use) --> 挂载Vue应用(amount)

2.3.2 App.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<script setup lang="ts">
import { RouterLink, RouterView } from 'vue-router'
import HelloWorld from './components/HelloWorld.vue'
</script>

<template>
<header>
<img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125" />

<div class="wrapper">
<HelloWorld msg="You did it!" />

<nav>
<RouterLink to="/">Home</RouterLink>
<RouterLink to="/about">About</RouterLink>
</nav>
</div>
</header>

<RouterView />
</template>

<style scoped>
<!-- 略 -->
</style>

代码解释:

位置 作用
<script setup> 使用组合式 API 语法,导入组件
<RouterLink> 页面内跳转,替代 <a> 标签
<RouterView> 当前页面内容的“容器”,根据路由加载组件
HelloWorld 一个Vue组件

2.3.3 index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<!-- 提供挂载点 -->
<div id="app"></div>
<!-- 引入入口 TypeScript 文件 -->
<script type="module" src="/src/main.ts"></script>
</body>
</html>

index.html 文件是网页的入口文件。

3 环境变量和模式

3.1 环境变量定义和命名

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

Vite 会自动读取项目根目录下的 .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"

3.2 内置常量

一些内置常量在所有情况下都可用:

  • 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 上。

3.3 模式

在 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

      ### 4.3 共享选项

      #### 4.3.1 base

      - **类型:** `string`
      - **默认:** `/`
      - 表示构建后资源的公共路径前缀,例如:

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

几种不同的部署配置:

配置 建议使用场景
base: '/' 绝大多数在线部署(如 Vercel、Netlify)
base: './' 离线 HTML、本地打开、内嵌式部署
base: '/my-app/' 网站部署在子路径 /my-app/
② 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'
③ server

表示开发服务器设置。

1
2
3
4
5
6
7
8
9
10
11
12
server: {
host: true, // 启动本地局域网可访问
port: 3000,
open: true, // 自动打开浏览器
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '')
}
}
}
  • build:打包配置
1
2
3
4
5
6
7
8
9
10
11
12
13
build: {
outDir: 'dist', // 打包输出目录
assetsDir: 'static', // 静态资源目录
sourcemap: false, // 是否生成 source map
minify: 'esbuild', // 或 'terser'
rollupOptions: {
output: {
manualChunks: {
vue: ['vue', 'vue-router']
}
}
}
}
  • define:全局变量
1
2
3
define: {
__APP_VERSION__: JSON.stringify('1.0.0')
}
  • plugins:插件
1
2
3
4
5
6
import vue from '@vitejs/plugin-vue'
import svgLoader from 'vite-svg-loader'

export default defineConfig({
plugins: [vue(), svgLoader()]
})
  • css:全局样式,预处理器配置
1
2
3
4
5
6
7
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/variables.scss";`
}
}
}

4 Vue Router

Vue Router 是 Vue.js 官方提供的路由管理器,用于实现 SPA(单页应用)中的页面跳转功能。

在一个 SPA 中,页面不会真正跳转,而是通过改变浏览器地址栏中的路径,然后 Vue Router 控制展示不同的组件视图。

4.1 路由配置和挂载

Vue Router的引入详见3.2小节。

创建路由配置:src/router/index.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 从 vue-router 中导入两个核心方法
// createRouter:创建一个路由实例
// createWebHistory:使用 HTML5 的 History API 来管理路由(URL 没有 #)
import { createRouter, createWebHistory } from 'vue-router'

// 导入视图组件
import HomeView from '../views/HomeView.vue'

// 创建路由实例 router
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/', // URL 路径为 /
name: 'home', // 路由名称,可用于编程式导航
component: HomeView, // 显示的组件为 HomeView
},
{
path: '/about',
name: 'about',
component: () => import('../views/AboutView.vue'), // 懒加载
},
],
})

// 导出 router 实例,在 main.ts 中挂载到 Vue 应用
export default router

main.ts中挂载(或者称为注册):

1
2
import router from './router'
app.use(router)

<router-view> 是一个占位组件,表示“当前路由匹配的组件应该显示在哪里”。当切换 URL 时,Vue Router 会把对应的组件渲染到 <router-view> 所在的位置。

代码示例1

1
2
3
4
5
6
7
<!-- App.vue -->
<template>
<div>
<h1>SAMPLE</h1>
<router-view /> <!-- 这里会根据路由切换,展示不同的页面 -->
</div>
</template>

当配置了如下路由:

1
2
3
4
const routes = [
{ path: '/', component: HomeView },
{ path: '/about', component: AboutView }
]
  • 访问 / 时:HomeView 会被插入到 <router-view /> 的位置。
  • 访问 /about 时:AboutView 会被插入进去。

代码示例2

嵌套路由时 <router-view> 可以嵌套。

1
2
3
4
5
6
7
<!-- Layout.vue -->
<template>
<div class="layout">
<h2>控制台</h2>
<router-view /> <!-- 子路由渲染在这里 -->
</div>
</template>
1
2
3
4
5
6
7
8
{
path: '/dashboard',
component: Layout,
children: [
{ path: 'monitor', component: MonitorView },
{ path: 'map', component: MapView }
]
}

访问 /dashboard/monitor 时,MonitorView 会渲染到 Layout.vue 中的 <router-view>


<router-link> 是 Vue Router 提供的组件,用来创建跳转链接,作用类似于 <a href="">,但不会刷新页面。

代码示例

1
2
3
4
5
6
7
8
9
<template>
<nav>
<!-- 点击这个会跳转到 '/' -->
<router-link to="/">首页</router-link> |

<!-- 跳转到 '/about' -->
<router-link to="/about">关于我们</router-link>
</nav>
</template>

两者比较:

组件 作用 位置限制 常用用法
<router-view> 渲染匹配当前路径的组件 可以在任何组件中使用(不只限 App.vue) 多用于布局组件中作为内容插槽
<router-link> 渲染为跳转链接(不会刷新页面) 任意组件 <router-link to="/xxx">跳转</router-link>