在 Quasar 应用中管理 Vite:配置扩展、插件、JSX 与别名的完整实战指南
在 Quasar 应用中管理 Vite配置扩展、插件、JSX 与别名的完整实战指南【免费下载链接】quasarQuasar Framework - Build high-performance VueJS user interfaces in record time项目地址: https://gitcode.com/gh_mirrors/qu/quasar本篇指南以quasar/app-vite构建系统为核心讲解 Quasar CLI 如何替你生成 Vite 配置以及如何通过quasar.config文件的build节点扩展它从extendViteConf深合并、vitePlugins插件数组、依赖预构建排除、quasar inspect调试命令到 JSX/TSX 支持、文件夹别名与 PostCSS 处理。读完你将掌握在 Quasar 项目中安全、精准地驾驭 Vite 的全部手段并理解其背后的实现原理。为什么你的项目里没有 vite.config.jsQuasar CLIVite 版项目默认不存在vite.config.js/vite.config.ts文件。这不是遗漏而是设计使然Quasar CLI 会替你生成一份完整的 Vite 配置覆盖项目根目录、publicDir、环境变量注入、Vue 插件、Quasar 专属插件、产物目录等大量细节你无需也不应操心这些底层接线。从源码看这份配置在 app-vite/lib/config-tools.js 的createViteConfig()中集中构建包含configFile: false—— 明确告知 Vite 不要再去找vite.config.*文件避免配置冲突该字段同时被quasar inspect用来识别这是 Vite 配置还是 Rolldown 配置root、base取自build.publicPath、publicDir可由build.ignorePublicFolder关闭、cacheDirmode随 dev/build 自动切换为development/productionenvDir: false以避免 Vite 自行加载.env引发不必要的客户端刷新define合并 Quasar 的import.meta.env注入与build.defineplugins依次挂载vitejs/plugin-vue、quasar/vite-plugin以及你在build.vitePlugins中声明的所有插件针对 SSR/SSG 服务端线程单独设置ssr: true的 Vue 插件选项并将构建目标切换为 Node。因此你需要改动 Vite 行为时正确入口是quasar.config文件的build节点而非新建vite.config.*。关于quasar.config文件本身的完整说明见 quasar-config-file 文档。通过 extendViteConf 扩展 Vite 配置当需要微调 Vite 配置时在quasar.config文件的build.extendViteConf中编写回调即可// quasar.config 文件 build: { extendViteConf (viteConf, { isServer, isClient }) { // 返回一个 Object它会被深合并进生成的配置 // 而不是直接修改 viteConf return { build: { chunkSizeWarningLimit: 750 } } // 等价于下面这份 vite.config.js / vite.config.ts // export default defineConfig({ // build: { // chunkSizeWarningLimit: 750 // } // }) } }两种写法都受支持见 build.d.ts 类型定义返回覆盖对象回调返回一个对象Quasar 用 Vite 的mergeConfig将其与生成的配置做深合并直接修改viteConf回调直接增删改传入的配置对象无需返回任何值。extendViteConf可以是异步函数。第二个参数携带isClient/isServer两个布尔标志用于区分当前正在构建客户端线程还是服务端SSR/SSG线程。底层实现在 config-tools.js 的extendViteConfig()Quasar 会先执行你的回调再依次调用所有 App Extension 注册的extendViteConf钩子两者的返回值都会被mergeConfig深合并。注意viteConf是 Quasar 已经配置好的对象其中许多选项直接来源于quasar.config的build节点。不要篡改输入输出文件相关的配置如entry、outDir等已被 Quasar 接管的部分除非你完全清楚自己在做什么。追加 Vite 插件则推荐走下一节的vitePlugins数组。深合并的利与弊深合并意味着你只需给出想覆盖的局部build: { extendViteConf () { return { build: { rollupOptions: { output: { manualChunks: { vendor: [vue, quasar] } } } } } } }不需要重写整份配置。但正因是深合并如果某处需要整体替换数组应优先使用Object.assign语义直接修改viteConf上的对应字段或显式覆盖整个数组避免与默认值意外合并。Npm 包从 Quasar 导入时的双副本问题一个 npm 包组件库、辅助工具包或 App Extension如果在自己的代码里写了import { Notify } from quasar在 dev 模式下会被 Vite 的依赖预构建dep optimizer打成一个独立 bundle并链接到第二份 Quasar 副本。结果就是你的应用安装的 Quasar 插件在那个包看来从未被安装运行时报错如Notify.create is not a function。解决办法是把这类包从预构建中排除让它们的 Quasar 导入与你的应用代码解析到同一份模块// quasar.config 文件 build: { extendViteConf () { // 返回值会被深合并进生成的 Vite 配置 return { optimizeDeps: { exclude: [my-quasar-helper-package] } } } }App Extension 的开发者也应当自行在扩展内配置这一排除逻辑通过extendViteConf钩子而不是依赖宿主应用代为配置具体做法见 Injecting Quasar Plugin。[!WARNING] 依赖预构建只作用于 dev server。生产构建依靠的是 Quasar 的导入映射机制它按quasar.config framework autoImportScriptExtensions中列出的文件扩展名处理默认[js, jsx, ts, tsx]。如果该包以.mjs文件发布 ESM 构建产物请把mjs加入该列表否则生产包中仍会混入第二份 Quasar症状与 dev 模式相同。用 quasar inspect 检视生成的 Vite 配置Quasar CLI 提供quasar inspect命令用于查看给定模式与场景下实际生成的 Vite/Rolldown 配置$ quasar inspect -h Description Inspect Quasar generated Vite config Usage $ quasar inspect $ quasar inspect -c build $ quasar inspect -m electron -p build.outDir Options --cmd, -c Quasar command [dev|build] (default: dev) --mode, -m App mode [spa|ssr|ssg|pwa|bex|cordova|capacitor|electron] (default: spa) --depth, -d Number of levels deep (default: 2) --path, -p Path of config in dot notation Examples: -p build.outDir -p server.port -p plugins --thread, -t Display only one specific app mode config thread --no-color Disable colored output --help, -h Displays this message从 app-vite/lib/cmd/inspect.js 的实现看该命令会按你指定的mode加载对应的模式配置spa-config.js、ssr-config.js等逐个生成配置对象SSR/SSG 模式可能有多个线程再通过dot-prop按点号路径提取子配置如build.outDir、server.port、plugins最后用util.inspect以指定深度打印。校验要点--mode指定的模式必须已安装否则直接报Requested mode for inspection is NOT installed.--thread只能选择该模式实际提供的线程名配置对象含configFile字段则判定为 Vite 配置否则为 Rolldown 配置。调试时最常用的组合是quasar inspect -m ssr -p plugins查看 SSR 模式下最终生效的插件列表或quasar inspect -c build -m pwa -p build.outDir确认产物目录。添加 Vite 插件vitePlugins 数组先使用项目的包管理器安装插件然后在quasar.config文件的build.vitePlugins中声明// quasar.config 文件 build: { vitePlugins: [ // 两种写法完全等价 [plugin-name, {/* plugin options */}], [plugin-name, {/* plugin options */}, { server: true, client: true }] ] }第三项元素runOptions用于控制插件在客户端 / 服务端线程的启停对 SSR 应用尤其有用// quasar.config 文件 build: { vitePlugins: [ // 只在服务端禁用 [plugin-name, {/* plugin options */}, { server: false }], // 只在客户端禁用 [plugin-name, {/* plugin options */}, { client: false }] ] }vitePlugins支持多种声明语法与 build.d.ts 的PluginEntry类型一一对应// quasar.config 文件 vitePlugins: [ [plugin1-name, {/* plugin1 options */}, { server: true, client: true }], [plugin2-name, {/* plugin2 options */}, { server: true, client: true }] // ... ] // 或直接传入插件工厂函数注意此时无法传 runOptions import plugin1 from plugin1 import plugin2 from plugin2 vitePlugins: [ [plugin1, {/* plugin1 options */}, { server: true, client: true }], [plugin2, {/* plugin2 options */}, { server: true, client: true }] // ... ] // 最后一种形式也支持但有缺点 // Quasar CLI 无法感知 options 参数的变化改完需要手动重启 dev server import plugin1 from plugin1 import plugin2 from plugin2 vitePlugins: [ plugin1({/* plugin1 options */}), plugin2({/* plugin2 options */}) // ... ]关于各语法在底层的解析差异可看 config-tools.js 的parseVitePlugins()字符串形式Quasar 用getPackage()解析包名并取default导出作为插件工厂随后用merge({}, pluginOpts)浅拷贝选项再调用工厂——这层拷贝是为了防止插件在运行期改写自身选项而触发配置无限 diff 循环函数形式直接以拷贝后的选项调用工厂对象形式即已实例化的插件对象同样做一次merge拷贝后压入数组{ client: true, server: true }过滤在服务端编译线程vite-ssr-server/vite-ssg-server中跳过server: false的插件在客户端线程中跳过client: false的插件若直接传入plugin1({...})这种已调用工厂的形式Quasar 无法得知选项变更因此会在启动时给出提示建议改用数组形式以获得热更新感知。通过 extendViteConf 追加插件SSR/SSG 场景你也可以用extendViteConf()追加插件这在需要对服务端或客户端线程分别应用插件时特别有用import plugin1 from plugin1 import plugin2 from plugin2 build: { extendViteConf (viteConf, { isClient, isServer }) { viteConf.plugins.push( plugin1({ /* plugin1 options */ }), plugin2({ /* plugin2 options */ }) // ... ) } }更进一步quasar.config文件导出的函数接收ctx参数可在整个配置文件中按模式或环境做条件判断export default defineConfig(ctx { return { build: { extendViteConf(viteConf, { isClient, isServer }) { if (ctx.mode.pwa) { viteConf.plugins.push(/* ... */) } if (ctx.dev) { viteConf.plugins.push(/* ... */) } } } } })示例用 rollup-plugin-copy 拷贝静态文件构建到生产环境时常需要把静态或外部文件拷入产物目录rollup-plugin-copy是常见选择// quasar.config 文件 // ... build: { // ... vitePlugins: [ [ rollup-plugin-copy, { targets: [ { // 具体语法参见 rollup-plugin-copy 的 npm 文档 src: [ORIGIN_PATH], dest: [DEST_PATH] }, { // 把 firebase-messaging-sw.js 拷入 SPA/PWA/SSR/SSG 的 dist 目录 src: config/firebase/firebase-messaging-sw.js, dest: dest/spa // 以构建 SPA 为例 } ] } ] // 其他 vite/rollup 插件 ] } // ...注意dest需要与你构建的模式产物目录保持一致如 SPA 为dist/spa也可以结合ctx.modeName动态拼接。调整 vitejs/plugin-vue 选项需要微调 Vue 官方插件vitejs/plugin-vue时使用build.viteVuePluginOptions// quasar.config 文件 build: { viteVuePluginOptions: { script: { // 示例启用实验性的 props 解构 propsDestructure: true }, template: { compilerOptions: { // 示例启用自定义元素 / Web Component 标签识别 isCustomElement: (tag) tag.startsWith(my-) } } } }该选项的类型即vitejs/plugin-vue的Options见 build.d.ts因此所有官方支持的选项都可在此传入。底层上Quasar 在createViteConfig()中会以merge()合并默认值SSR/SSG 服务端线程默认叠加{ ssr: true, template: { ssr: true } }再交给vueVitePlugin(options)实例化见 config-tools.js。启用 JSX / TSXQuasar UI v2.26、quasar/app-vite v3.8开启 JSX/TSX如果你想用 JSX/TSX 编写组件替代或混用 Vue 模板只需在build.vueJsx开启// quasar.config 文件TypeScript 项目 build: { /** * 是否用 JSX/TSX 编写组件.jsx/.tsx 文件或 .vue 文件中 * 的 script langjsx|tsx。 * * Vite 会自己编译 JSX此选项只是让 Vite 指向 Vue 的 JSX 运行时 * 而非它默认假设的 React 运行时并为 TypeScript 项目在生成的 * .quasar/tsconfig.json 中加入对应的 jsx / jsxImportSource。 * * 可设为 true或设为选项对象以覆盖下方默认值或设为 preserve * 表示交由 Vite 插件如 vitejs/plugin-vue-jsx它提供 Vue 专有的 * JSX 语法糖v-model、v-show、v-slots来转换 JSX。 * * 设为 true 时提供给 ViteOxc的默认选项 * example * { * runtime: automatic, * importSource: vue * } * * default false */ vueJsx?: boolean | NonNullableOxcOptions[jsx]; }仅此一步即可无需安装额外包——Vite 自带的 Oxc 编译器负责 JSX 转换该选项只是把 JSX 运行时从 React 默认值切到 Vue并为 TS 项目同步生成.quasar/tsconfig.json中的jsx/jsxImportSource类型同步逻辑由 types-generator.js 维护。从源码看createViteConfig()会在启用时注入oxc: { jsx: build.vueJsx }见 config-tools.js类型定义位于 build.d.ts。开启后即可使用.jsx/.tsx文件// /src/components/MyBadge.jsx import { QBadge } from quasar export default function MyBadge({ text }) { return QBadge classq-ma-sm coloraccent label{text} / }// /src/components/MyBadge.tsx import { QBadge } from quasar export default function MyBadge({ text }: { text: string }) { return QBadge classq-ma-sm coloraccent label{text} / }也可以在.vue文件的script块中声明语言使用script setup langjsx import { QBadge } from quasar const MyBadge () QBadge coloraccent labelHello / /scriptscript setup langtsx import { QBadge } from quasar const MyBadge () QBadge coloraccent labelHello / /scriptQuasar 组件在 JSX/TSX 下拥有完整类型props、事件onClick、onUpdate:modelValue等以及 Vue 对任意组件通用的 propsclass、style、key、ref。自定义 JSX 转换选项除了truevueJsx也可以接收一个选项对象直接交给 ViteOxc覆盖默认值// quasar.config 文件 build: { vueJsx: { runtime: automatic, importSource: vue } }runtime: automatic配合importSource: vue意味着无需在文件里显式import { jsx } from vue/jsx-runtime编译器会自动注入。使用 vitejs/plugin-vue-jsx 获得 Vue 语法糖Vite 编译的是纯 JSX不包含 Vue 特有的语法糖v-model、v-show、v-slots。如果需要这些能力安装vitejs/plugin-vue-jsx到应用根目录然后把转换交给它// quasar.config 文件 build: { // Vite 不再动 JSX交由该插件转换 vueJsx: preserve, vitePlugins: [ [ vitejs/plugin-vue-jsx, { /* plugin options */ } ] ] }这里的preserve模式与上方 Oxc 选项对象互斥前者是让 Vite 插件处理后者是交给 Vite 内置 Oxc 处理。文件夹别名Folder AliasesQuasar 预配置了别名指向/src目录。若要新增别名例如把utils指向/src/utils从而可以import { formatTime } from utils/time.js有三种方式推荐直接用/utils/零配置别名已是社区惯例对协作者更友好通过build.alias属性最简单的别名声明方式使用绝对路径// quasar.config 文件 export default defineConfig(ctx { return { build: { alias: { // 指向 /src/utils utils: ctx.appPaths.resolve.src(utils) } } } })直接扩展 Vite 配置不要直接整体赋值viteConf.resolve.alias会覆盖内置别名用Object.assign追加或返回含额外别名的对象且务必使用绝对路径// quasar.config 文件 export default defineConfig(ctx { return { build: { extendViteConf(viteConf, { isServer, isClient }) { viteConf.resolve.alias.utils ctx.appPaths.resolve.src(utils) } } } })build.alias的类型为{ [key: string]: string }文档与类型注释均提醒使用绝对路径推荐通过ctx.appPaths的解析方法生成见 build.d.ts。底层上createViteConfig()会把build.alias直接铺进resolve.aliasconfig-tools.js随后还会追加各模式依赖的别名如 Capacitor 插件的 web 实现别名见getModeDepsAliases()。[!TIP]TypeScript 用户无需重复配置不需要把别名同步到tsconfig.json也无需vite-tsconfig-paths之类的包——Quasar CLI 默认会在生成的.quasar/tsconfig.json中维护这些映射。PostCSS 与样式预处理*.vue文件及其他样式文件默认都会经过 PostCSS 管道无需为它安装额外的 loader。默认配置使用 Autoprefixer如需调整直接修改项目根目录的postcss.config.js即可Quasar 初始化项目时会生成该文件。此外Quasar 在createViteConfig()中为 Sass/SCSS 预处理器预设了silenceDeprecations选项以屏蔽过时 API 的警告相关样式变量的注入则由quasar/vite-plugin完成见 config-tools.js。小结Quasar CLI 把 Vite 配置生成、插件装配与模式差异化处理全部收进quasar.config文件的build节点向开发者暴露了四条可控通道extendViteConf返回对象深合并或直接修改适合精细化调整任意 Vite 选项vitePlugins声明式装配插件支持客户端/服务端线程开关viteVuePluginOptions/vueJsx分别掌管 Vue 插件选项与 JSX/TSX 编译alias声明式追加文件夹别名。配合quasar inspect命令随时检视最终生效配置你可以在不触碰vite.config.*的前提下获得与手写 Vite 配置完全等价的掌控力。【免费下载链接】quasarQuasar Framework - Build high-performance VueJS user interfaces in record time项目地址: https://gitcode.com/gh_mirrors/qu/quasar创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考