跳到主要内容

知识速查表

CLI 命令

命令说明
npm create vite@latest创建新项目(交互式)
npm create vite@latest my-app -- --template vue使用模板创建项目
npx vite启动开发服务器
npx vite --port 3000指定端口启动
npx vite --open启动并打开浏览器
npx vite --host允许外部访问
npx vite build生产构建
npx vite build --mode staging使用指定模式构建
npx vite preview预览生产构建
npx vite --config my-config.js使用指定配置文件

项目结构

my-project/
├── index.html # HTML 入口
├── package.json # 项目配置
├── vite.config.js # Vite 配置
├── public/ # 静态资源(原样复制)
│ ├── favicon.ico
│ └── robots.txt
└── src/
├── main.js # 入口文件
├── App.vue # 根组件
├── assets/ # 资源(会被处理)
└── components/ # 组件

配置文件模板

基础配置

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

export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': resolve(__dirname, 'src'),
},
},
server: {
port: 3000,
open: true,
},
})

完整配置

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

export default defineConfig(({ mode }) => ({
root: process.cwd(),
base: '/',
publicDir: 'public',

plugins: [vue()],

resolve: {
alias: {
'@': resolve(__dirname, 'src'),
'@components': resolve(__dirname, 'src/components'),
'@views': resolve(__dirname, 'src/views'),
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json'],
},

server: {
port: 3000,
host: true,
open: true,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},

build: {
outDir: 'dist',
sourcemap: mode === 'development',
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router'],
},
},
},
},

css: {
preprocessorOptions: {
scss: {
additionalData: `@use "@/styles/vars.scss" as *;`,
},
},
},
}))

环境变量

.env 文件

# .env                    # 所有环境
# .env.local # 本地(不提交 git)
# .env.[mode] # 特定模式
# .env.[mode].local # 特定模式本地

VITE_API_URL=https://api.example.com
VITE_APP_TITLE=My App

使用环境变量

// 访问环境变量
const apiUrl = import.meta.env.VITE_API_URL
const isDev = import.meta.env.DEV
const isProd = import.meta.env.PROD
const mode = import.meta.env.MODE
const baseUrl = import.meta.env.BASE_URL

TypeScript 类型

// vite-env.d.ts
/// <reference types="vite/client" />

interface ImportMetaEnv {
readonly VITE_API_URL: string
readonly VITE_APP_TITLE: string
}

interface ImportMeta {
readonly env: ImportMetaEnv
}

路径别名

配置

// vite.config.js
import { resolve } from 'path'

export default defineConfig({
resolve: {
alias: {
'@': resolve(__dirname, 'src'),
'@components': resolve(__dirname, 'src/components'),
'@views': resolve(__dirname, 'src/views'),
'@utils': resolve(__dirname, 'src/utils'),
'@assets': resolve(__dirname, 'src/assets'),
},
},
})

使用

// 导入组件
import Button from '@components/Button.vue'

// 导入工具
import { formatDate } from '@utils/date'

// 导入资源
import logo from '@assets/logo.png'

CSS 处理

预处理器

npm install -D sass-embedded  # 或 sass
npm install -D less
npm install -D stylus

CSS Modules

/* style.module.css */
.container { padding: 20px; }
.title { font-size: 24px; }
import classes from './style.module.css'

// 使用
<div className={classes.container}>
<h1 className={classes.title}>Title</h1>
</div>

Scoped CSS (Vue)

<style scoped>
/* 只作用于当前组件 */
.container { padding: 20px; }
</style>

静态资源

资源导入

// 导入图片
import imgUrl from './img.png'

// 作为 URL
import assetUrl from './asset.js?url'

// 作为原始字符串
import shaderCode from './shader.glsl?raw'

// 内联为 base64
import inlineSvg from './icon.svg?inline'

public 目录

public/
├── favicon.ico
├── robots.txt
└── images/
└── logo.png
<!-- 使用根路径引用 -->
<img src="/images/logo.png" />

代理配置

// vite.config.js
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
'/ws': {
target: 'ws://localhost:8080',
ws: true,
},
},
},
})

Glob 导入

// 懒加载
const modules = import.meta.glob('./dir/*.js')

// 立即加载
const modules = import.meta.glob('./dir/*.js', { eager: true })

// 具名导入
const modules = import.meta.glob('./dir/*.js', {
import: 'setup',
eager: true,
})

// 排除文件
const modules = import.meta.glob([
'./dir/*.js',
'!**/bar.js',
])

动态导入

// 路由懒加载
const User = () => import('./views/User.vue')

// 条件加载
if (condition) {
const module = await import('./heavy-module.js')
}

// 动态路径
const module = await import(`./locales/${lang}.js`)

Web Workers

// 构造函数方式
const worker = new Worker(
new URL('./worker.js', import.meta.url),
{ type: 'module' }
)

// 查询后缀方式
import MyWorker from './worker?worker'
const worker = new MyWorker()

// 内联 Worker
import InlineWorker from './worker?worker&inline'

常用插件

插件安装用途
Vuenpm i -D @vitejs/plugin-vueVue 3 支持
Reactnpm i -D @vitejs/plugin-reactReact Fast Refresh
Legacynpm i -D @vitejs/plugin-legacy旧浏览器支持
PWAnpm i -D vite-plugin-pwaPWA 支持
SVGnpm i -D vite-plugin-svgrSVG 作为组件
检查器npm i -D vite-plugin-checkerTypeScript/ESLint 检查
自动导入npm i -D unplugin-auto-importAPI 自动导入
组件导入npm i -D unplugin-vue-components组件自动导入

构建配置

export default defineConfig({
build: {
outDir: 'dist', // 输出目录
assetsDir: 'assets', // 资源目录
sourcemap: false, // Source map
target: 'es2015', // 目标浏览器
minify: 'esbuild', // 压缩工具
cssCodeSplit: true, // CSS 分割
assetsInlineLimit: 4096, // 内联限制
chunkSizeWarningLimit: 500, // 警告阈值

rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router'],
},
},
},
},
})

多页面应用

// vite.config.js
import { resolve } from 'path'

export default defineConfig({
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
about: resolve(__dirname, 'about/index.html'),
},
},
},
})

库模式

// vite.config.js
import { resolve } from 'path'

export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'lib/main.js'),
name: 'MyLib',
fileName: 'my-lib',
formats: ['es', 'umd'],
},
rollupOptions: {
external: ['vue'],
output: {
globals: {
vue: 'Vue',
},
},
},
},
})

HMR API

if (import.meta.hot) {
// 接受自身更新
import.meta.hot.accept()

// 接受依赖更新
import.meta.hot.accept('./dep.js', (newModule) => {
console.log('updated:', newModule)
})

// 监听事件
import.meta.hot.on('vite:beforeUpdate', (data) => {
console.log('before update:', data)
})

// 清理副作用
import.meta.hot.dispose(() => {
clearInterval(timer)
})
}

package.json 脚本

{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"build:staging": "vite build --mode staging",
"type-check": "tsc --noEmit"
}
}

浏览器支持

开发环境

  • Chrome/Edge >= 111
  • Firefox >= 114
  • Safari >= 16.4

最低支持(ESM)

  • Chrome >= 64
  • Firefox >= 67
  • Safari >= 11.1
  • Edge >= 79

旧浏览器支持

npm install -D @vitejs/plugin-legacy
import legacy from '@vitejs/plugin-legacy'

export default defineConfig({
plugins: [
legacy({
targets: ['defaults', 'not IE 11'],
}),
],
})

常见问题

端口被占用

npx vite --port 3000

清空输出目录

build: {
emptyOutDir: true
}

相对路径部署

export default defineConfig({
base: './',
})

禁用 HMR

server: {
hmr: false
}

设置全局变量

export default defineConfig({
define: {
__VERSION__: JSON.stringify('1.0.0'),
},
})

资源链接