一、静态资源处理
//png txt后缀的文件不会检测是否存在,js json vue文件会检测是否存在
import test from "@/assets/imgs/test1.png"
console.log(test); // /src/assets/imgs/test1.png返回图片的绝对路径
// 显式加载资源为一个 URL
import test from "@/assets/imgs/test1.png?url" //等效于上面那种方式,默认选项
//会检测所有类型的文件是否存在,毕竟要转换为二进制
import test from "@/assets/imgs/test.png?raw"
console.log(test); // 转换为二进制
// 加载为 Web Worker
import Worker from './worker.js?worker'
二、JSON具名导入
{
"name": "John Doe",
"age": 30,
"address": {
"street": "123 Main St",
"city": "Anytown"
}
}
import { name, age } from '@/assets/imgs/test.json';
console.log(name); // 输出 "John Doe"
console.log(age); // 输出 30
//这个是具名导入,json文件的编译结果,可以看出只能具名导出第一层
//原生esmodule导入导出只能是js,在vite中能导入json,png等格式是因为vite做了处理,将其变成了js文件
//这里说的js文件,不是指后缀名为.js的文件,浏览器也不是通过后缀名来判断文件的类型
//是通过响应头里面的Content-Type的类型来判断的
export const name = "John Doe";
export const age = 30;
export const address = {
street: "123 Main St",
city: "Anytown"
};
export default {
name: name,
age: age,
address: address
};
三、glob导入
const modules = import.meta.glob('./dir/*.js')
以上代码会被转换为下面的代码,通过变量modules可以获取到相应模块
这个功能可以用于做约定式路由,也可以用于做动态路由,若依框架动态路由就是用的这个
// vite 生成的代码
const modules = {
'./dir/foo.js': () => import('./dir/foo.js'),
'./dir/bar.js': () => import('./dir/bar.js'),
}
上面的模块是懒加载,如果需要直接导入,可以添加额外参数
const modules = import.meta.glob('./dir/*.js', { eager: true })
// vite 生成的代码
import * as __glob__0_0 from './dir/foo.js'
import * as __glob__0_1 from './dir/bar.js'
const modules = {
'./dir/foo.js': __glob__0_0,
'./dir/bar.js': __glob__0_1,
}
多个匹配模式
const modules = import.meta.glob(['./dir/*.js', './another/*.js'])
反面匹配模式
//以!开头的路径将被忽略
const modules = import.meta.glob(['./dir/*.js', '!**/bar.js'])
如果只想要导入模块中的部分内容,那么可以利用 import 选项
const modules = import.meta.glob('./dir/*.js', { import: 'setup' })
// vite 生成的代码
const modules = {
'./dir/foo.js': () => import('./dir/foo.js').then((m) => m.setup),
'./dir/bar.js': () => import('./dir/bar.js').then((m) => m.setup),
}
Glob 导入注意事项
- 这只是一个 Vite 独有的功能而不是一个 Web 或 ES 标准
- 该 Glob 模式会被当成导入标识符:必须是相对路径(以 ./ 开头)或绝对路径(以 / 开头,相对于项目根目录解析)或一个别名路径
- 所有
import.meta.glob
的参数都必须以字面量传入。你 不 可以在其中使用变量或表达式
四、使用插件
强制插件顺序
为了与某些 Rollup 插件兼容,可能需要强制修改插件的执行顺序,或者只在构建时使用。这应该是 Vite 插件的实现细节。可以使用 enforce
修饰符来强制插件的位置:
pre
:在 Vite 核心插件之前调用该插件- 默认:在 Vite 核心插件之后调用该插件
post
:在 Vite 构建插件之后调用该插件
// vite.config.js
import image from '@rollup/plugin-image'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
{
...image(),
enforce: 'pre'
},
],
})
默认情况下插件在开发 (serve) 和生产 (build) 模式中都会调用。如果插件在服务或构建期间按需使用,请使用 apply 属性指明它们仅在 build
或 serve
模式时调用
// vite.config.js
import typescript2 from 'rollup-plugin-typescript2'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
{
...typescript2(),
apply: 'build',
},
],
})
五、文件系统缓存
Vite 将预构建的依赖项缓存到 node_modules/.vite
中。它会基于以下几个来源来决定是否需要重新运行预构建步骤:
- 包管理器的锁文件内容,例如
package-lock.json
,yarn.lock
,pnpm-lock.yaml
,或者bun.lockb
- 补丁文件夹的修改时间;
vite.config.js
中的相关字段;NODE_ENV
的值
只有在上述其中一项发生更改时,才需要重新运行预构建。
如果出于某些原因你想要强制 Vite 重新构建依赖项,你可以在启动开发服务器时指定--force
选项,或手动删除node_modules/.vite
缓存目录。
六、处理加载报错
当 Vite 加载动态导入失败时,会触发 vite:preloadError
事件。event.payload
包含原始的导入错误信息。如果调用 event.preventDefault()
,则不会抛出错误
window.addEventListener('vite:preloadError', (event) => {
window.location.reload() // 例如,刷新页面
})
七、文件变化时重新构建
你可以使用 vite build --watch
来启用 rollup 的监听器。或者,你可以直接通过 build.watch
调整底层的 WatcherOptions
选项
// vite.config.js
export default defineConfig({
build: {
watch: {
// https://rollupjs.org/configuration-options/#watch
},
},
})
当启用 --watch
标志时,对 vite.config.js
的改动,以及任何要打包的文件,都将触发重新构建
八、环境变量
Vite 在一个特殊的 import.meta.env
对象上暴露环境变量,这些变量在构建时会被静态地替换掉。这里有一些在所有情况下都可以使用的内建变量:
import.meta.env.MODE
: {string} 应用运行的模式 命令行--mode
后面的值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 上。
九、HTML 环境变量替换
Vite 还支持在 HTML 文件中替换环境变量。import.meta.env
中的任何属性都可以通过特殊的 %ENV_NAME%
语法在 HTML 文件中使用:
<h1>Vite is running in %MODE%</h1>
<p>Using data from %VITE_API_URL%</p>
如果环境变量在import.meta.env
中不存在,比如不存在的 %NON_EXISTENT%
,则会将被忽略而不被替换,这与 JS 中的 import.meta.env.NON_EXISTENT
不同,JS 中会被替换为 undefined
。
十、配置
1.情景配置
如果配置文件需要基于(dev/serve
或 build
)命令或者不同的 模式 来决定选项,亦或者是一个 SSR 构建(isSsrBuild
)、一个正在预览的构建产物(isPreview
),则可以选择导出这样一个函数:
export default defineConfig(({ command, mode, isSsrBuild, isPreview }) => {
if (command === 'serve') {
return {
// dev 独有配置
}
} else {
// command === 'build'
return {
// build 独有配置
}
}
})
2.异步配置
export default defineConfig(async ({ command, mode }) => {
const data = await asyncFunction()
return {
// vite 配置
}
})
3.在配置中使用环境变量
环境变量通常可以从 process.env
获得。
注意 Vite 默认是不加载 .env
文件的,因为这些文件需要在执行完 Vite 配置后才能确定加载哪一个,举个例子,root
和 envDir
选项会影响加载行为。不过当你的确需要时,你可以使用 Vite 导出的 loadEnv
函数来加载指定的 .env
文件。
import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ command, mode }) => {
// 根据当前工作目录中的 `mode` 加载 .env 文件
// 设置第三个参数为 '' 来加载所有环境变量,而不管是否有 `VITE_` 前缀。
const env = loadEnv(mode, process.cwd(), '')
return {
// vite 配置
define: {
__APP_ENV__: JSON.stringify(env.APP_ENV),
},
}
})
十一、共享选项
1. define
定义全局常量替换方式。其中每项在开发环境下会被定义在全局,而在构建时被静态替换
export default defineConfig({
define: {
__APP_VERSION__: JSON.stringify('v1.0.0'),
__API_URL__: 'window.__backend_api_url',
},
})
console.log(__APP_VERSION__) //v1.0.0
如果使用的是ts,需要添加类型声明才不会提示错误
// vite-env.d.ts
declare const __APP_VERSION__: string
2. resolve.extensions
导入时想要省略的扩展名列表。注意,不 建议忽略自定义导入类型的扩展名(例如:.vue),因为它会影响 IDE 和类型支持。
export default defineConfig({
resolve: {
alias: {
"@": resolve(__dirname, "./src"),
},
extensions:[".ts", ".js", ".vue", ".json"]
},
})
3. css.postcss
内联的 PostCSS 配置(格式同 postcss.config.js
),或者一个(默认基于项目根目录的)自定义的 PostCSS 配置路径。
对内联的 POSTCSS 配置,它期望接收与 postcss.config.js
一致的格式。但对于 plugins
属性有些特别,只接收使用 数组格式。
注意:如果提供了该内联配置,Vite 将不会搜索其他 PostCSS 配置源。
4. css.preprocessorOptions
指定传递给 CSS 预处理器的选项。文件扩展名用作选项的键。每个预处理器支持的选项可以在它们各自的文档中找到:
export default defineConfig({
css: {
preprocessorOptions: {
less: {
math: 'parens-division',
},
styl: {
define: {
$specialColor: new stylus.nodes.RGBA(51, 197, 255, 1),
},
},
},
},
})
5. css.preprocessorOptions[extension].additionalData
该选项可以用来为每一段样式内容添加额外的代码。但是要注意,如果你添加的是实际的样式而不仅仅是变量,那这些样式在最终的产物中会重复。
export default defineConfig({
css: {
preprocessorOptions: {
scss: {
additionalData: `$injectedColor: orange;`, //$injectedColor: orange;会添加到每一个scss文件中
},
},
},
})
6. css.preprocessorMaxWorkers
如果启用了这个选项,那么 CSS 预处理器会尽可能在 worker 线程中运行。默认是0,可以设置为number | true
,true 表示 CPU 数量减 1。
7. css.devSourcemap
在开发过程中是否启用 sourcemap。
8. envDir
用于加载 .env 文件的目录。可以是一个绝对路径,也可以是相对于项目根的路径。
9. envPrefix
以 envPrefix 开头的环境变量会通过 import.meta.env
暴露在你的客户端源码中。默认是VITE_
十二、服务器选项
1. server.strictPort
设为 true 时若端口已被占用则会直接退出,而不是尝试下一个可用端口
2. server.warmup
提前转换和缓存文件以进行预热。可以在服务器启动时提高初始页面加载速度,并防止转换瀑布
请确保只添加经常使用的文件,以免在启动时过载 Vite 开发服务器
export default defineConfig({
server: {
warmup: {
clientFiles: ['./src/components/*.vue', './src/utils/big-utils.js'],
ssrFiles: ['./src/server/modules/*.js'],
},
},
})
十三、构建选项
1. build.target
设置最终构建的浏览器兼容目标
2. build.outDir
指定输出路径
3. build.assetsDir
指定生成静态资源的存放路径(相对于 build.outDir
)
4. build.assetsInlineLimit
小于此阈值的导入或引用资源将内联为 base64 编码,以避免额外的 http 请求。设置为 0 可以完全禁用此项。
如果传入了一个回调函数,可以通过返回一个布尔值来选择是否加入。如果没有返回任何内容,那么就会应用默认的逻辑。
5. build.cssCodeSplit
启用/禁用 CSS 代码拆分。当启用时,在异步 chunk 中导入的 CSS 将内联到异步 chunk 本身,并在其被加载时一并获取。
如果禁用,整个项目中的所有 CSS 将被提取到一个 CSS 文件中。
6. build.minify
设置为 false 可以禁用最小化混淆,或是用来指定使用哪种混淆器
7. build.write
设置为 false 来禁用将构建后的文件写入磁盘
十四、依赖优化选项
1. optimizeDeps.entries
设置依赖预构建的入口
2. optimizeDeps.exclude
在预构建中强制排除的依赖项
3. optimizeDeps.include
默认情况下,不在 node_modules 中的,链接的包不会被预构建。使用此选项可强制预构建链接的包。
4. optimizeDeps.force
设置为 true 可以强制依赖预构建,而忽略之前已经缓存过的、已经优化过的依赖。
十四、插件API
1. 虚拟模块
虚拟模块是一种很实用的模式,使你可以对使用 ESM 语法的源文件传入一些编译时信息
export default function myPlugin() {
const virtualModuleId = 'virtual:my-module'
const resolvedVirtualModuleId = '\0' + virtualModuleId
return {
name: 'my-plugin', // 必须的,将会在 warning 和 error 中显示
resolveId(id) {
if (id === virtualModuleId) {
return resolvedVirtualModuleId
}
},
load(id) {
if (id === resolvedVirtualModuleId) {
return `export const msg = "from virtual module"`
}
},
}
}
import { msg } from 'virtual:my-module'
console.log(msg)
2. resolveId
拦截自定义的模块,不能是node_modules
里面的,也不能/
和./
,../