








这是一个关键认知点:
vite build 开始时,Vite 会先用 esbuild 将 node_modules 中的依赖打包成 ESM 格式,这个过程非常快。vite.config.js 或 vite.config.ts。production)加载 .env.production 等文件,并将变量注入到代码中。index.html)。dist 目录(或配置的 outDir)。build.manifest,会生成一个 manifest.json 文件,记录了原始文件和打包后文件的映射关系,用于服务端渲染等场景。vite build 命令在你的 Vite 项目根目录下,打开终端并运行:
# 直接打包,默认为 production 模式
npm run build
# 或者使用 yarn
yarn build
# 或者使用 pnpm
pnpm build
这个命令通常在你的 package.json 中被定义:
{
"scripts": {
"build": "vite build"
}
}
打包完成后,你会看到一个 dist 目录,里面就是最终可以部署到服务器的静态文件。
vite.config.js 配置文件这是 Vite 的核心配置文件。一个基础的配置如下:
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
// 其他配置...
})
defineConfig 函数主要为了提供 TypeScript 类型提示,非常推荐使用。
打开 dist 目录,你通常会看到:
index.html:你的主入口文件,其中的 JS 和 CSS 引用已经被替换为带有哈希值的文件名。assets/:存放所有打包后的资源文件,如 index-a1b2c3d4.js, style-5e6f7g8h.css。manifest.json:如果启用了,会包含文件映射信息。index.html 的变化是关键,它确保了浏览器能正确加载到更新后的资源,解决了缓存问题。build)在 vite.config.js 中,build 对象控制着生产构建的所有行为。
// vite.config.js
export default defineConfig({
build: {
// 打包输出目录
outDir: 'dist',
// 静态资源存放目录
assetsDir: 'assets',
// 是否生成 source map 文件
// 'hidden' 会生成 .map 文件,但不在 JS 文件中引用,用于错误上报
sourcemap: false, // true | 'hidden' | 'inline'
// 构建后是否生成 manifest.json
manifest: false, // true | string | object
// chunk 大小警告的限制 (kb)
chunkSizeWarningLimit: 500,
// Rollup 配置,可以覆盖 Vite 内部 Rollup 的默认配置
rollupOptions: {
// 入口文件,可以是字符串、对象或数组
input: 'src/main.js', // 或 { main: 'src/main.js', admin: 'src/admin/main.js' }
// 输出配置
output: {
// JS 文件命名格式
chunkFileNames: 'assets/js/[name]-[hash].js',
entryFileNames: 'assets/js/[name]-[hash].js',
// 资源文件命名格式 (图片, 字体等)
assetFileNames: 'assets/[ext]/[name]-[hash].[ext]',
// 手动代码分割
manualChunks: (id) => {
// 将 node_modules 中的依赖单独打包
if (id.includes('node_modules')) {
// 例如,将 vue 和 vue-router 打包到一个 chunk
if (id.toString().includes('vue') || id.toString().includes('vue-router')) {
return 'vendor-vue';
}
// 其他依赖
return 'vendor';
}
}
}
},
// 压缩配置
// Vite 5+ 默认使用 esbuild 压缩 JS,CSS 使用 Lightning CSS
// 你也可以切换回 Terser
minify: 'esbuild', // 'terser' | 'esbuild'
terserOptions: {
// Terser 的具体配置
}
}
})
Vite 内置了三种模式:
development (开发)production (生产)test (测试).env 文件来管理不同环境的变量。.env:所有模式都会加载。.env.local:所有模式都会加载,但会被 git 忽略。.env.development:npm run dev 时加载。.env.production:npm run build 时加载。VITE_ 开头的变量才会暴露给客户端代码。# .env.production
VITE_APP_TITLE=My Awesome App
VITE_API_BASE_URL=https://api.production.com
在代码中使用:
console.log(import.meta.env.VITE_APP_TITLE); // "My Awesome App"
Vite 默认会进行很好的代码分割,主要有两种策略:
// 路由懒加载
const routes = [
{
path: '/about',
component: () => import('./views/About.vue') // About.vue 会被单独打包成一个 chunk
}
]
// 条件加载
if (someCondition) {
import('./some-heavy-library').then(module => {
// 使用模块
})
}
build.rollupOptions.output.manualChunks 配置,如上例所示,将 node_modules 中的不同库拆分成不同的 vendor chunk,可以更好地利用浏览器缓存。esbuild,速度极快。如果需要更精细的控制(如移除 console 和 debugger),可以切换到 terser 并配置 terserOptions。Lightning CSS,非常快。也可以通过插件(如 vite-plugin-purgecss)移除未使用的 CSS。package.json 中设置了 sideEffects: false,以获得最佳效果。<link rel="modulepreload"> 标签,让浏览器提前加载资源,提升页面加载速度。import logoUrl from './logo.svg',然后用在 img 标签的 src 中。vite-plugin-svgr 插件,可以直接 import { ReactComponent as Logo } from './logo.svg' (在 React 中) 或 import Logo from './logo.svg?component' (在 Vue 3 中)。assetsInlineLimit(默认 4kb)的图片会被转为 base64 Data URL。import styles from './style.module.css'。sass),Vite 会自动识别 .scss/.sass 文件。autoprefixer, tailwindcss)并创建 postcss.config.js 即可。MPA 的核心是配置多个入口。
// vite.config.js
import { defineConfig } from 'vite'
import { resolve } from 'path'
export default defineConfig({
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
admin: resolve(__dirname, 'admin/index.html'),
},
},
},
})
你需要确保每个入口 HTML 文件都正确地引用了它自己的 JS 入口。
如果你想用 Vite 打包一个 JS 库供其他项目使用,可以使用库模式。
vite build --mode lib --file my-lib.js
更推荐在 vite.config.js 中配置:
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
export default defineConfig({
plugins: [vue()],
build: {
lib: {
// 库的入口文件
entry: resolve(__dirname, 'src/index.js'),
// 库的名称
name: 'MyAwesomeLib',
// 打包后的文件名
fileName: (format) => `my-awesome-lib.${format}.js`
},
rollupOptions: {
// 确保外部化处理那些你不想打包进库的依赖
external: ['vue'],
output: {
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
globals: {
vue: 'Vue'
}
}
}
}
})
这会生成 es 和 umd 格式的文件,方便不同环境使用。
Vite 的插件 API 简单而强大。一个插件就是一个对象,包含 name 和各种钩子函数(如 config, configureServer, buildStart 等)。
常用插件推荐:
@vitejs/plugin-vue / @vitejs/plugin-react:官方框架支持。vite-plugin-windicss / tailwindcss:原子化 CSS 框架。vite-plugin-pwa:添加 PWA 能力。vite-plugin-compression2:生成 .gz / .br 压缩文件。vite-plugin-eslint:在构建时进行 ESLint 检查。Vite 的构建过程非常简单,易于集成到任何 CI/CD 流程中。
GitHub Actions 示例:
name: Build and Deploy
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
cache: 'npm' # 或 'yarn', 'pnpm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist
history 模式的路由(如 Vue Router 的 createWebHistory),服务器需要配置回退到 index.html。否则刷新页面会 404。base 配置是否正确。如果部署在子目录,必须设置 base。base: '/' (默认):生成绝对路径,如 /assets/logo.png。适合部署在根域名。base: './':生成相对路径,如 ./assets/logo.png。适合部署在任何子目录,但可能不适用于所有场景。https://example.com/my-app/,base 必须设置为 /my-app/。对于超大型项目,Node.js 的默认内存可能不够用。
# 增加 Node.js 内存限制
export NODE_OPTIONS="--max-old-space-size=8192"
npm run build
或者在 package.json 中修改:
{
"scripts": {
"build": "node --max-old-space-size=8192 ./node_modules/.bin/vite build"
}
}
Vite 默认目标是支持原生 ESM 的现代浏览器。要兼容旧版浏览器(如 IE11),你需要:
@vitejs/plugin-legacy:npm install -D @vitejs/plugin-legacy
// vite.config.js
import legacy from '@vitejs/plugin-legacy'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
legacy({
targets: ['defaults', 'not IE 11'] // 设置目标浏览器
})
]
})
这个插件会:
core-js)。index.html 中添加 type="module" 和 nomodule 的 script 标签,让浏览器自动选择合适的版本。Vite 的打包系统凭借其 Rollup 核心、开箱即用的优化 和 极致的开发体验,已经成为现代前端工程化的首选工具之一。
vite build 和基本的 vite.config.js 配置。build 配置项,学会使用环境变量和手动代码分割。本文将针对依赖预构建、代码分割、资源压缩、Tree Shaking、缓存策略、图片优化、字体优化七大核心功能,从原理、配置、实战示例、注意事项四个维度进行详细拆解,结合 Vue3 项目实际场景给出可落地的配置方案。
核心结论
依赖预构建是 Vite 针对 node_modules 中第三方依赖的性能优化手段,通过将零散的 ESM 依赖打包为单文件、转换非 ESM 依赖为 ESM 格式,解决了依赖加载的网络请求过多、浏览器兼容性问题,是 Vite 开发环境和生产环境打包的基础优化。
原理讲解
为什么需要依赖预构建?
Vite 依赖预构建的执行逻辑
import Vue from 'vue'),识别出需要预构建的依赖;node_modules/.vite/deps 目录;vite.config.js 修改或 package.json 变动时,才会重新预构建。对 Vue3 项目的特殊优化
Vite 会优先预构建 Vue3 及其生态依赖(如 vue-router、pinia),确保 Vue 相关代码的加载速度,同时兼容 Vue3 的 ESM 模块格式。
配置示例
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
// 依赖预构建核心配置
optimizeDeps: {
// 1. 指定需要强制预构建的依赖(自动检测不生效时使用)
include: ['vue', 'vue-router', 'pinia', 'axios', 'lodash-es'],
// 2. 指定不需要预构建的依赖(如已为 ESM 格式且体积小的依赖)
exclude: ['small-esm-package'],
// 3. 自定义 Esbuild 选项(如添加插件)
esbuildOptions: {
target: 'es2020' // 指定编译目标,适配更多浏览器
},
// 4. 强制重新预构建(开发环境调试时使用)
force: false // 设为 true 会忽略缓存,每次启动都重新预构建
}
})
注意事项
【重点】node_modules/.vite 目录是预构建产物的缓存目录,若出现依赖加载异常(如依赖版本更新后代码未生效),可删除该目录后重启 Vite。
【避坑提醒】对于通过 CDN 引入的依赖(如在 index.html 中通过 <script> 引入 Vue),需在 optimizeDeps.exclude 中排除,避免重复预构建。
核心结论
代码分割是将项目代码拆分为多个小的 chunk(代码块),实现按需加载(首屏只加载必要代码,其他代码在需要时再加载),是降低 Vue3 项目首屏加载时间的核心手段,Vite 基于 Rollup 实现了灵活的代码分割能力。
原理讲解
代码分割的核心场景
Vite 代码分割的实现方式
build.rollupOptions.output.manualChunks 自定义分割规则;import() 语法实现动态加载(如路由懒加载)。Vue3 项目的代码分割优势
Vue3 的组合式 API(Composition API)更利于代码分割,Rollup 可更精准地识别未使用的代码,结合代码分割进一步减小包体积。
配置示例
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
// 动态导入实现路由懒加载,每个路由组件生成独立 chunk
const Home = () => import(/* webpackChunkName: "home" */ '../views/Home.vue')
const ProductList = () => import(/* webpackChunkName: "product" */ '../views/ProductList.vue')
const Cart = () => import(/* webpackChunkName: "cart" */ '../views/Cart.vue')
const UserCenter = () => import(/* webpackChunkName: "user" */ '../views/UserCenter.vue')
const routes = [
{ path: '/', component: Home },
{ path: '/products', component: ProductList },
{ path: '/cart', component: Cart },
{ path: '/user', component: UserCenter }
]
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes
})
export default router
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
build: {
rollupOptions: {
output: {
// 配置 chunk 文件名格式(添加哈希值用于缓存)
chunkFileNames: 'static/js/[name]-[hash:8].js',
entryFileNames: 'static/js/[name]-[hash:8].js',
// 手动代码分割规则
manualChunks: {
// 1. 将 Vue 生态依赖打包为独立 chunk
vueVendor: ['vue', 'vue-router', 'pinia'],
// 2. 将工具类依赖打包为独立 chunk
utilsVendor: ['axios', 'lodash-es', 'dayjs'],
// 3. 将业务通用组件打包为独立 chunk
components: ['src/components/BaseTable.vue', 'src/components/BaseModal.vue'],
// 4. 动态分割 node_modules 中的依赖
...((id) => {
if (id.includes('node_modules')) {
// 将不同的第三方库拆分为不同的 chunk
return id.split('node_modules/')[1].split('/')[0]
}
})
}
}
}
}
})
注意事项
【重点】路由懒加载时可通过 /* webpackChunkName: "xxx" */ 注释自定义 chunk 名称,便于打包后分析。
【避坑提醒】不要过度分割代码,过多的 chunk 会导致浏览器发起更多网络请求,反而降低性能(建议一个 chunk 体积不小于 10KB)。
核心结论
资源压缩是通过 Gzip 或 Brotli 算法对打包后的 JS、CSS、HTML 等文件进行压缩,可减少文件体积 60%-80%,大幅提升资源加载速度。Vite 可通过插件实现打包时生成压缩文件,也可通过服务器配置实现运行时压缩。
原理讲解
Gzip 与 Brotli 对比
| 特性 | Gzip | Brotli |
|---|---|---|
| 压缩率 | 较高 | 更高(比 Gzip 高 10%-20%) |
| 压缩速度 | 较快 | 稍慢 |
| 浏览器支持 | 全支持 | 现代浏览器均支持(Chrome 50+、Firefox 44+) |
| 服务器支持 | 广泛 | Nginx 1.13.9+、Apache 2.4.26+ 支持 |
Vite 实现资源压缩的两种方式
vite-plugin-compression 插件在 npm run build 时生成 .gz 或 .br 压缩文件,部署时直接提供压缩文件;配置示例
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import compression from 'vite-plugin-compression' // 需先安装:npm i vite-plugin-compression -D
export default defineConfig({
plugins: [
vue(),
// Gzip 压缩配置
compression({
verbose: true, // 是否在控制台输出压缩结果
disable: false, // 是否禁用压缩
threshold: 10240, // 仅压缩大于 10KB 的文件
algorithm: 'gzip', // 压缩算法
ext: '.gz', // 压缩文件后缀
deleteOriginFile: false // 是否删除原文件(建议保留,便于回退)
}),
// Brotli 压缩配置
compression({
verbose: true,
disable: false,
threshold: 10240,
algorithm: 'brotliCompress', // Brotli 压缩算法
ext: '.br',
deleteOriginFile: false
})
]
})
server {
listen 80;
server_name your-domain.com;
root /usr/share/nginx/html;
# 启用 Gzip 压缩
gzip on;
gzip_types text/plain text/css application/javascript application/json application/vue+json;
gzip_min_length 10240;
gzip_comp_level 6;
# 启用 Brotli 压缩(需 Nginx 编译时加入 Brotli 模块)
brotli on;
brotli_types text/plain text/css application/javascript application/json application/vue+json;
brotli_min_length 10240;
brotli_comp_level 6;
# 优先返回 Brotli 压缩文件
location ~* \.(js|css|html)$ {
add_header Vary Accept-Encoding;
if ($http_accept_encoding ~* br) {
try_files $uri.br $uri =404;
add_header Content-Encoding br;
default_type application/javascript;
}
if ($http_accept_encoding ~* gzip) {
try_files $uri.gz $uri =404;
add_header Content-Encoding gzip;
default_type application/javascript;
}
}
# 前端路由配置
try_files $uri $uri/ /index.html;
}
注意事项
【重点】建议同时生成 Gzip 和 Brotli 压缩文件,服务器根据浏览器的 Accept-Encoding 请求头返回对应的压缩文件,兼顾兼容性和压缩率。
【避坑提醒】不要对图片、视频等已压缩的资源进行 Gzip/Brotli 压缩,不仅不会减小体积,还可能增大体积并消耗服务器资源。
核心结论
Tree Shaking 是静态代码分析技术,通过识别并移除项目中未被使用的代码(死代码),可减少 Vue3 项目打包体积 10%-30%。Vite 基于 Rollup 实现了开箱即用的 Tree Shaking,对 Vue3 的 Composition API 支持尤为友好。
原理讲解
Tree Shaking 的工作条件
import/export),CommonJS 模块(require)不支持;Vite + Vue3 的 Tree Shaking 优势
如何标记代码无副作用
在 package.json 中添加 sideEffects 字段,告诉 Rollup 哪些文件有副作用,哪些没有:
{
"sideEffects": [
"*.css", // CSS 文件有副作用(样式会影响全局)
"*.scss",
"src/utils/global.js" // 全局初始化文件有副作用
]
}
配置示例
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
build: {
// Tree Shaking 相关配置(Vite 生产环境默认开启,可显式配置)
target: 'es2020', // 支持 ES 模块的树摇优化
cssCodeSplit: true, // 对 CSS 进行 Tree Shaking,移除未使用的样式
rollupOptions: {
treeshake: {
// 开启严格的 Tree Shaking(默认 true)
moduleSideEffects: false,
// 识别并移除未使用的全局变量
propertyReadSideEffects: false
}
}
}
})
// src/utils/format.js
export const formatDate = (date) => {
return new Date(date).toLocaleDateString()
}
export const formatPrice = (price) => {
return `¥${price.toFixed(2)}`
}
// src/components/Product.vue
import { formatPrice } from '../utils/format.js'
// 仅使用 formatPrice,formatDate 会被 Tree Shaking 移除
export default {
setup() {
const price = formatPrice(99.9)
return { price }
}
}
注意事项
【重点】避免在代码中使用 import * as utils from './utils' 这种整体导入方式,会导致 Tree Shaking 失效,应使用按需导入(import { xxx } from './utils')。
【避坑提醒】对于有副作用的代码(如 import './style.css'),需在 package.json 的 sideEffects 中声明,否则会被 Tree Shaking 误删。
核心结论
缓存策略是通过文件名哈希和HTTP 缓存头的配合,让浏览器缓存静态资源(如 JS、CSS、图片),仅在资源更新时重新请求,大幅减少重复请求,提升页面加载速度。
原理讲解
缓存的两个核心维度
Cache-Control、Expires 头判断资源是否过期,过期前直接从本地缓存读取,不发起请求;Last-Modified 或 ETag 头,服务器判断资源是否更新,未更新则返回 304,浏览器使用本地缓存。Vite 实现缓存的关键手段
app-123456.js),资源更新时哈希值变化,浏览器视为新资源;配置示例
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
build: {
rollupOptions: {
output: {
// 为不同类型的资源设置哈希格式
// [name]:模块名,[hash:8]:8位哈希值,[ext]:文件后缀
entryFileNames: 'static/js/[name]-[hash:8].js',
chunkFileNames: 'static/js/[name]-[hash:8].js',
assetFileNames: 'static/[ext]/[name]-[hash:8].[ext]'
}
},
// 关闭生产环境 sourcemap(减少文件体积,避免哈希值因 sourcemap 变化)
sourcemap: false
}
})
server {
listen 80;
server_name your-domain.com;
root /usr/share/nginx/html;
# 1. 静态资源(JS、CSS、图片、字体)设置强缓存,缓存1年
location ~* \.(js|css|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, max-age=31536000, immutable";
add_header ETag $request_filename; # 添加 ETag 用于协商缓存
}
# 2. HTML 文件设置不缓存,确保每次获取最新
location ~* \.html$ {
expires -1;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
}
# 3. 前端路由配置
try_files $uri $uri/ /index.html;
}
注意事项
【重点】immutable 头表示资源在缓存期内不会变化,浏览器无需发起协商请求,进一步提升性能。
【避坑提醒】若项目需要频繁更新,可适当缩短静态资源的缓存时间(如 1 个月),避免用户长时间看到旧版本。
核心结论
图片是 Vue3 项目中体积占比最高的资源之一,通过压缩图片体积、转换为更优格式(WebP/AVIF)、按需加载图片等手段,可显著减少图片资源的加载时间。Vite 可通过插件实现图片的自动化优化。
原理讲解
图片格式优化对比
| 格式 | 特点 | 压缩率 | 浏览器支持 |
|---|---|---|---|
| JPG | 有损压缩,适合照片 | 中等 | 全支持 |
| PNG | 无损压缩,适合图标/插画 | 较低 | 全支持 |
| WebP | 谷歌推出,兼顾有损/无损 | 高(比 JPG 小 25%-35%) | 现代浏览器支持 |
| AVIF | 新一代格式,压缩率更高 | 极高(比 WebP 小 20%-30%) | Chrome 85+、Firefox 91+ |
Vite 图片优化的实现方式
vite-plugin-imagemin 插件对图片进行无损/有损压缩;<picture> 标签实现降级兼容;配置示例
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import imagemin from 'vite-plugin-imagemin' // 需先安装:npm i vite-plugin-imagemin -D
export default defineConfig({
plugins: [
vue(),
// 图片优化配置
imagemin({
// 通用配置
verbose: true, // 输出压缩日志
disable: false, // 是否禁用
// 不同图片格式的压缩配置
gifsicle: { optimizationLevel: 7 }, // GIF 压缩级别(1-7)
optipng: { optimizationLevel: 7 }, // PNG 压缩级别(0-7)
mozjpeg: { quality: 80 }, // JPG 质量(0-100)
pngquant: { quality: [0.8, 0.9], speed: 4 }, // PNG 有损压缩
webp: { quality: 80 }, // WebP 质量
avif: { quality: 80 } // AVIF 质量
})
],
build: {
// 内联小图片(小于 4KB 的图片转为 Base64)
assetsInlineLimit: 4096
}
})
<template>
<picture>
<!-- 优先加载 AVIF 格式 -->
<source srcset="/static/images/product.avif" type="image/avif">
<!-- 其次加载 WebP 格式 -->
<source srcset="/static/images/product.webp" type="image/webp">
<!-- 降级加载 JPG 格式 -->
<img src="/static/images/product.jpg" alt="产品图片" loading="lazy">
</picture>
</template>
注意事项
【重点】loading="lazy" 可实现图片懒加载,仅当图片进入视口时才加载,提升首屏性能。
【避坑提醒】在 Windows 系统中安装 vite-plugin-imagemin 可能需要安装额外的编译工具(如 Python),若安装失败可使用 vite-plugin-imagemin 的国内镜像源。
核心结论
字体文件通常体积较大(中文字体可达数 MB),通过提取字体子集(只保留项目中使用的字符)、预加载关键字体、使用现代字体格式(WOFF2) 等手段,可大幅减少字体加载时间,避免页面出现“字体闪烁”(FOUT)问题。
原理讲解
字体格式优化
字体子集提取
使用工具(如 glyphhanger、font-spider)分析项目中使用的字符,只保留这些字符生成精简的字体文件,可将中文字体体积从数 MB 减小到几十 KB。
字体预加载
通过 <link rel="preload"> 标签预加载首屏所需的字体文件,确保字体在页面渲染前加载完成,避免字体闪烁。
配置示例
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
build: {
rollupOptions: {
output: {
// 字体文件输出目录和命名
assetFileNames: 'static/fonts/[name]-[hash:8].[ext]'
}
}
},
// 配置字体文件的解析
resolve: {
alias: {
'@fonts': '/src/assets/fonts'
}
}
})
npm i font-spider -g<!DOCTYPE html>
<html>
<head>
<style>
@font-face {
font-family: 'PingFang SC';
src: url('./src/assets/fonts/PingFangSC-Regular.woff2') format('woff2');
}
body { font-family: 'PingFang SC'; }
</style>
</head>
<body>
<!-- 项目中使用的所有字符 -->
首页 产品 购物车 我的 登录 注册 价格 数量 加入购物车
</body>
</html>
font-spider index.html,工具会自动提取子集并替换原字体文件。<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Vue3 电商项目</title>
<!-- 预加载首屏关键字体 -->
<link rel="preload" href="/static/fonts/PingFangSC-Regular-12345678.woff2" as="font" type="font/woff2" crossorigin>
<!-- 预获取非首屏字体 -->
<link rel="prefetch" href="/static/fonts/PingFangSC-Bold-87654321.woff2" as="font" type="font/woff2" crossorigin>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
// src/styles/fonts.scss
@font-face {
font-family: 'PingFang SC';
src: url('@fonts/PingFangSC-Regular.woff2') format('woff2'),
url('@fonts/PingFangSC-Regular.woff') format('woff');
font-weight: 400;
font-style: normal;
font-display: swap; // 字体加载时使用备用字体,加载完成后替换(避免FOUT)
}
body {
font-family: 'PingFang SC', sans-serif;
}
注意事项
【重点】font-display: swap 是解决字体闪烁的关键,建议所有自定义字体都添加该属性。
【避坑提醒】预加载字体时必须添加 crossorigin 属性,否则浏览器会忽略预加载请求(字体文件属于跨域资源,即使在同一域名下)。
通过这七大功能的协同配置,可将 Vue3 + Vite 项目的首屏加载时间降低 50% 以上,大幅提升用户体验。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。