Quasar CLI with Vite - @quasar/app-vite
使用 import.meta.env 可以在很多方面帮助你:
- 根据 Quasar 模式(SPA/PWA/Cordova/Electron)区分运行时流程
- 根据是开发构建还是生产构建区分运行时流程
- 在构建时基于终端环境变量添加标志
Quasar CLI 提供的值
import.meta.env.<name> | 类型 | 含义 |
|---|---|---|
QUASAR_DEV | Boolean | 代码运行在开发模式 |
QUASAR_PROD | Boolean | 代码运行在生产模式 |
QUASAR_DEBUG | Boolean | 代码运行在开发模式或生产模式设置了 --debug 标志 |
QUASAR_CLIENT | Boolean | 代码运行在客户端(非服务端) |
QUASAR_SERVER | Boolean | 代码运行在服务端(非客户端) |
QUASAR_MODE | String | Quasar CLI 模式(spa、pwa 等) |
QUASAR_<MODE>_MODE | Boolean | 代码运行在 <MODE> Quasar 模式下。例如:QUASAR_ELECTRON_MODE |
QUASAR_TARGET | String | Cordova/Capacitor 模式下为 ios 或 android,BEX 模式下为 chrome 或 firefox |
示例
if (import.meta.env.QUASAR_DEV) {
console.log(`I'm on a development build`)
}
// import.meta.env.MODE 是
// "quasar dev/build -m <mode>" 中的 <mode>
//(如果未指定 -m 参数则默认为 'spa')
if (import.meta.env.QUASAR_MODE === 'electron') {
// ...
}
// 或者使用:
if (import.meta.env.QUASAR_ELECTRON_MODE) {
// ...
}content_paste
代码剥离
编译你的网站/应用时,依赖 import.meta.env 的 if () 分支会被求值,如果表达式为 false,它们会从文件中被剥离。示例:
if (import.meta.env.QUASAR_DEV) {
console.log('dev')
} else {
console.log('build')
}
// 使用 "quasar dev" 运行将得到:
console.log('dev')
// 而使用 "quasar build" 运行将得到:
console.log('build')content_paste
注意上面的 if 在编译时被求值并完全剥离,从而产生更小的包。
基于 import.meta.env 的导入
你可以将上面学到的内容与动态导入结合使用:
if (import.meta.env.QUASAR_MODE === 'electron') {
import('my-fancy-npm-package').then(package => {
// 注意下面的 "default",这是你可以访问
// npm 导入包导出内容的属性
package.default.doSomething()
})
}
// 或者:
if (import.meta.env.QUASAR_ELECTRON_MODE) {
// ...
}content_paste
添加到 import.meta.env
你可以通过 /quasar.config 文件向 import.meta.env 添加自定义定义:
build: {
/**
* 定义全局常量替换。条目在开发时定义为全局变量,
* 在构建时进行静态替换。
*
* 值表达式必须是包含 JSON 可序列化值的字符串
*(null、boolean、number、string、array 或 object)或单个标识符。
*
* @example { __APP_VERSION__: JSON.stringify('v1.0.0') }
* @example { __API_URL__: 'window.__backend_api_url' }
*/
define?: Record<string, string>;
/**
* `define` 选项的语法糖。定义全局常量替换,
* 会自动转换为带 `import.meta.env` 前缀的 "define" 条目,
* 并自动进行 JSON 字符串化。
*
* @example { SOME_DEFINE: 'my-string' } 将转换为 { 'import.meta.env.SOME_DEFINE': '"my-string"' }
* @example { VERSION: 22 } 将转换为 { 'import.meta.env.VERSION': '22' }
*/
defineEnv?: Record<string, any>;
}content_paste
export default defineConfig(ctx => {
return {
// ...
build: {
// 从 quasar.config 文件传递到 UI 代码
define: {
'import.meta.env.API': JSON.stringify(
ctx.dev ? 'https://dev.api.com' : 'https://prod.api.com'
),
'import.meta.env.VERSION': JSON.stringify(22)
},
// 或者使用 defineEnv 的语法糖:
defineEnv: {
API: ctx.dev ? 'https://dev.api.com' : 'https://prod.api.com',
VERSION: 22
}
}
}
})content_paste
然后在你的网站/应用中,你可以访问 import.meta.env.API,它会根据开发或生产构建类型指向上面两个链接之一。import.meta.env.VERSION 也同样可用。
TIP
build.define 和 build.defineEnv 之间有一个根本区别。build.defineEnv 是 build.define 的语法糖:
- 它自动转换为 build.define 语法,在 key 前添加 “import.meta.env.” 前缀并对值进行 JSON 字符串化。
- build.define 还可以用于注入非 “import.meta.env” 的定义。例如:
build: {
define: {
__APP_VERSION__: JSON.stringify('v1.0.0')
}
}
// 然后直接使用 __APP_VERSION__content_paste
你甚至可以将它与 quasar dev/build 的环境变量结合使用:
# 我们在终端设置一个环境变量
$ MY_API=api.com quasar buildcontent_paste
// 然后在 /quasar.config 文件中获取它
build: {
defineEnv: {
API: ctx.dev
? 'https://dev.' + import.meta.env.MY_API
: 'https://prod.' + import.meta.env.MY_API
}
}content_paste
HTML 常量替换
import.meta.env 中的任何属性都可以在 HTML 文件(如你的 /index.html 文件)中使用特殊的 %CONST_NAME% 语法:
<!-- 以下将使用 import.meta.env.API -->
<div>The api is: %API%</div>content_paste
如果 env 在 import.meta.env 中不存在,例如 %NON_EXISTENT%,它会被忽略且不会被替换,这与 JS 中的 import.meta.env.NON_EXISTENT 不同(后者会被替换为 undefined)。
TypeScript 的 IntelliSense
你需要为你的定义提供类型声明。根据你使用它们的位置:
- /src/env.d.ts
- /src-ssr/ssr-env.d.ts
- /src-pwa/pwa-env.d.ts
- …以此类推,每个 Quasar CLI 模式都有对应的文件
/// <reference types="@quasar/app-vite/client" />
/**
* 为你的自定义环境变量添加类型,
* 以避免通过 import.meta.env.VARIABLE_NAME 使用时的 TypeScript 错误
*/
interface ImportMetaEnv {
readonly API: string
}content_paste
故障排除
如果你错误地访问变量或配置有误,可能会在浏览器控制台中看到 process is not defined 错误。
错误用法
build: {
defineEnv: {
FOO: 'hello',
}
}content_paste
const { FOO } = import.meta.env // ❌ 不允许解构或类似操作
import.meta.env.FOO // ✅ 只能替换这样的直接使用
function getEnv(name) {
return import.meta.env[name] // ❌ 无法分析动态使用
}
console.log(process) // ❌
console.log(import.meta.env) // ❌
// 如果你想查看可用的环境变量列表,
// 可以在 quasar.config 文件中打印传递给 `build > env` 的对象
console.log(import.meta.env.FOO) // ✅
console.log(import.meta.env.foo) // ❌ 区分大小写
console.log(import.meta.env.F0O) // ❌ 变量名拼写错误(中间的 o 是 0)content_paste
配置错误
手动定义
build: {
defineEnv: {
FOO: 'hello',
}
}content_paste
console.log(import.meta.env.FOO) // ✅
console.log(import.meta.env.BAR) // ❌ 未在 `build > defineEnv` 中定义content_paste
其他有用链接
你可能还想查看 Dotenv 文件支持。