Quasar 在构建和调试时依赖诸多优秀的底层工具,例如 Webpack。Quasar 的一大优势就是为你封装并处理了这些工具的复杂配置,因此即便你不熟悉 Webpack 或其他开发工具,也能顺利使用 Quasar。
那么可以通过 /quasar.config 文件配置哪些内容?主要包括:
- 应用中要使用的 Quasar 组件、指令和插件
- 默认的 Quasar 语言包
- 要使用的 图标库
- Quasar 组件默认的 图标集
- 开发服务器端口、HTTPS 模式、主机名等
- 要使用的 CSS 动画
- Boot 文件 列表(决定执行顺序)—— 这些文件位于
/src/boot,用于在挂载根 Vue 组件前初始化应用 - 全局要包含在构建包中的 CSS/Sass/… 文件
- PWA 的 manifest 与 Workbox 配置
- Electron Packager 或 Electron Builder 的配置
- 扩展 Webpack 配置
TIP
修改这些设置无需手动重启开发服务器。Quasar 会自动检测变化并重新加载相关进程。你不必中断开发流程,只需安心等待 Quasar CLI 快速重新加载修改后的代码,甚至还能保持当前的运行状态,大大节省你的时间!
WARNING
/quasar.config 文件由 Quasar CLI 构建系统执行,因此该文件中的代码直接运行在 Node.js 环境中,而非应用上下文中。这意味着你可以在其中引入 ‘node:fs’、‘node:path’、‘webpack’ 等模块。
结构
基础用法
/quasar.config 文件导出一个接收 ctx(上下文)参数并返回配置对象的函数。你可以根据上下文动态调整应用配置:
import { defineConfig } from '#q-app/wrappers'
export default defineConfig((ctx) => { // can be async too
console.log(ctx)
// Example output on console:
{
dev: true,
prod: false,
mode: { spa: true },
modeName: 'spa',
target: {},
targetName: undefined,
arch: {},
archName: undefined,
debug: undefined
}
// context gets generated based on the parameters
// with which you run "quasar dev" or "quasar build"
return {
// ... your config
}
})举个例子,你可以仅在 PWA 模式下引入某个字体,其他模式则不引入:
{
extras: [
ctx.mode.pwa // we're adding only if working on a PWA
? "roboto-font"
: null,
];
}或者针对 SPA 模式和 Cordova 模式分别使用不同的全局 CSS 文件,其他模式则不加载:
{
css: [
ctx.mode.spa ? "app-spa.sass" : null, // looks for /src/css/app-spa.sass
ctx.mode.cordova ? "app-cordova.sass" : null, // looks for /src/css/app-cordova.sass
];
}还可以配置开发服务器在 SPA 模式下使用 8000 端口、PWA 模式使用 9000 端口、其他模式使用 9090 端口:
{
devServer: {
port: ctx.mode.spa ? 8000 : ctx.mode.pwa ? 9000 : 9090;
}
}也可以在返回配置前执行异步操作:
export default defineConfig(async (ctx) => {
const data = await someAsyncFunction()
return {
// ... use "data"
}
})
// or:
export default defineConfig((ctx) => {
return new Promise(resolve => {
// some async work then:
// resolve() with the quasar config
resolve({
//
})
})
})玩法无限。
IDE 自动补全
你可以使用 defineConfig() 辅助函数包裹导出的函数,以获得更好的 IDE 自动补全体验(通过 TypeScript):
import { defineConfig } from "#q-app/wrappers";
export default defineConfig((ctx) => {
/* configuration options */
});可配置项说明
css
/**
* Global CSS/Stylus/SCSS/SASS/... files from `/src/css/`,
* except for theme files, which are included by default.
*/
css?: string[];示例:
{
css: [
"app.sass", // referring to /src/css/app.sass
"~some-library/style.css", // referring to node_modules/some-library/style.css
];
}vendor
默认情况下,来自 node_modules 的所有内容会被注入 vendor chunk,以优化性能和缓存。若需手动增删该 chunk 的内容,可这样配置:
return {
vendor: {
/* optional;
disables vendor chunk: */ disable: true,
add: ["src/plugins/my-special-plugin"],
remove: ["axios", "vue$"],
},
};boot
更多内容请参阅 Boot 文件。
/** Boot files to load. Order is important. */
boot?: QuasarBootConfiguration;
interface BootConfigurationItem {
path: string;
server?: false;
client?: false;
}
type QuasarBootConfiguration = (string | BootConfigurationItem)[];preFetch
更多内容请参阅 PreFetch 特性 页面。
/** Enable the preFetch feature. */
preFetch?: boolean;extras
/**
* What to import from [@quasar/extras](https://github.com/quasarframework/quasar/tree/dev/extras) package.
* @example ['material-icons', 'roboto-font', 'ionicons-v4']
*/
extras?: (QuasarIconSets | QuasarFonts)[];framework
告诉 CLI 要导入哪些 Quasar 组件/指令/插件、使用哪个 Quasar 国际化语言包、Quasar 组件使用什么图标集等。
仅当 “all” 设为 false 时才需要填写 “components” 和 “directives”。
framework: {
/**
* @see - QuasarConfOptions tab in API cards throughout the docs
*/
config?: SerializableConfiguration<QuasarUIConfiguration>;
/**
* One of the Quasar IconSets
*
* @see https://v2.quasar.dev/options/quasar-icon-sets
*
* @example 'material-icons'
*/
iconSet?: QuasarIconSets;
/**
* One of the Quasar language packs
*
* @see https://v2.quasar.dev/options/quasar-language-packs
*
* @example 'en-US'
* @example 'es'
*/
lang?: QuasarLanguageCodes;
/**
* Quasar CSS addons have breakpoint aware versions of flex and spacing classes
*
* @see https://v2.quasar.dev/layout/grid/introduction-to-flexbox#flex-addons
* @see https://v2.quasar.dev/style/spacing#flex-addons
*/
cssAddon?: boolean;
/**
* Auto import - how to detect components in your vue files
* "kebab": q-carousel q-page
* "pascal": QCarousel QPage
* "combined": q-carousel QPage
*
* @default 'kebab'
*/
autoImportComponentCase?: "kebab" | "pascal" | "combined";
/**
* Quasar will auto import components based on your usage.
* But, in case you have a special case, you can manually specify Quasar components to be available everywhere.
*
* An example case would be having custom component definitions with plain string templates, inside .js or .ts files,
* in which you are using Quasar components (e.g. q-avatar).
*
* Another example would be that dynamically rendering components depending on an API response or similar (e.g. in a CMS),
* something like `<component :is="dynamicName">` where `dynamicName` is a string that matches a Quasar component name.
*
* @example ['QAvatar', 'QChip']
*/
components?: (keyof QuasarComponents)[];
/**
* Quasar will auto import directives based on your usage.
* But, in case you have a special case, you can manually specify Quasar directives to be available everywhere.
*
* An example case would be having custom component definitions with plain string templates, inside .js or .ts files,
* in which you are using Quasar directives (e.g. v-intersection).
*
* @example ['Intersection', 'Mutation']
*/
directives?: (keyof QuasarDirectives)[];
/**
* Quasar plugins to be installed. Specify the ones you are using in your app.
*
* @example ['Notify', 'Loading', 'Meta', 'AppFullscreen']
*/
plugins?: (keyof QuasarPlugins)[];
}更多参考:
animations
更多内容请参阅 CSS 动画。
/**
* What Quasar CSS animations to import.
* @example [ 'bounceInLeft', 'bounceOutRight' ]
* */
animations?: QuasarAnimationsConfiguration | 'all';devServer
Webpack devServer 选项。完整选项列表请参阅 官方文档。Quasar CLI 会根据 “quasar dev” 的参数和 Quasar 模式自动覆盖部分选项以确保配置正确。注意:如果你在代理开发服务器(比如使用云端 IDE 或本地隧道),需要在 client 部分设置 webSocketURL 为你的公网应用 URL,以保证热重载和模块热替换等功能正常工作,详见此处。
常用属性:
| 属性 | 类型 | 说明 |
|---|---|---|
| port | Number | 开发服务器端口 |
| host | String | 开发服务器使用的本地 IP/主机名 |
| open | Boolean/Object | 除非设为 false,Quasar 会自动打开浏览器访问开发服务器地址。适用于 SPA、PWA 和 SSR 模式。使用 open 包的参数。详见下方。 |
| proxy | Object/Array | 当你有独立的后端 API 开发服务器,又希望在同一域名下发送 API 请求时,代理配置会非常有用。 |
| devMiddleware | Object | 传给 webpack-dev-middleware v4 的配置 |
| server | Object | 在此配置 HTTPS 替代 HTTP(见下方) |
| onBeforeSetupMiddleware | Function | 在 webpack-dev-server 应用自身配置前配置开发中间件。 |
| onAfterSetupMiddleware | Function | 在 webpack-dev-server 应用自身配置后配置开发中间件。 |
使用 open 属性可以指定用特定浏览器打开,而非操作系统默认浏览器(查看支持的值)。前述链接中描述的 options 参数即为 quasar.config 文件 > devServer > open 的配置项。示例:
// (syntax below requires @quasar/app-webpack v3.3+)
// opens Google Chrome
devServer: {
open: {
app: {
name: "google chrome";
}
}
}
// opens Firefox
devServer: {
open: {
app: {
name: "firefox";
}
}
}
// opens Google Chrome and automatically deals with cross-platform issues:
import open from "open";
devServer: {
open: {
app: {
name: open.apps.chrome;
}
}
}当你在 /quasar.config 文件中设置 devServer > server > type: 'https' 时,Quasar 会自动为你生成 SSL 证书。不过如果你想为 localhost 自行创建证书,可以参考 Filippo 的这篇教程。然后你的 quasar.config 文件 > devServer > server 应该类似这样:
devServer: {
server: {
type: 'https', // NECESSARY (alternative is type 'http')
options: {
// Use ABSOLUTE paths or path.join(__dirname, 'root/relative/path')
key: "/path/to/server.key",
pfx: "/path/to/server.pfx",
cert: "/path/to/server.crt",
ca: "/path/to/ca.pem",
passphrase: 'webpack-dev-server' // do you need it?
}
}
}你还可以配置自动打开远程 Vue Devtools:
devServer: {
vueDevtools: true;
}Docker 和 WSL 下的 HMR 问题
如果你使用 Docker 容器,可能会遇到 HMR 失效的问题。HMR 依赖操作系统发出文件变更通知,而 Docker 容器中这一机制可能无法正常工作。
一个权宜之计是启用轮询模式来检测文件系统变化。启用方式如下:
build: {
// ...
extendWebpack(cfg) {
cfg.watchOptions = {
aggregateTimeout: 200,
poll: 1000,
};
},
// ...build
build: {
/**
* Transpile JS code with Babel
*
* @default true
*/
webpackTranspile?: boolean;
/**
* Add dependencies for transpiling with Babel (from node_modules, which are by default not transpiled).
* It is ignored if "transpile" is not set to true.
* @example [ /my-dependency/, 'my-dep', ...]
*/
webpackTranspileDependencies?: (RegExp | string)[];
/**
* Esbuild is used to build contents of /src-pwa, /src-ssr, /src-electron, /src-bex
* @example
* {
* browser: ['es2022', 'firefox115', 'chrome115', 'safari14'],
* node: 'node20'
* }
*/
esbuildTarget?: EsbuildTargetOptions;
/**
* Extend Webpack config generated by Quasar CLI.
* Equivalent to chainWebpack(), but you have direct access to the Webpack config object.
*/
extendWebpack?: (
config: WebpackConfiguration,
invokeParams: InvokeParams
) => void;
/**
* Extend Webpack config generated by Quasar CLI.
* Equivalent to extendWebpack(), but using [webpack-chain](https://github.com/sorrycc/webpack-chain) instead.
*/
chainWebpack?: (chain: WebpackChain, invokeParams: InvokeParams) => void;
/**
* Prepare external services before `$ quasar dev` command runs
* like starting some backend or any other service that the app relies on.
* Can use async/await or directly return a Promise.
*/
beforeDev?: (params: QuasarHookParams) => void;
/**
* Run hook after Quasar dev server is started (`$ quasar dev`).
* At this point, the dev server has been started and is available should you wish to do something with it.
* Can use async/await or directly return a Promise.
*/
afterDev?: (params: QuasarHookParams) => void;
/**
* Run hook before Quasar builds app for production (`$ quasar build`).
* At this point, the distributables folder hasn't been created yet.
* Can use async/await or directly return a Promise.
*/
beforeBuild?: (params: QuasarHookParams) => void;
/**
* Run hook after Quasar built app for production (`$ quasar build`).
* At this point, the distributables folder has been created and is available
* should you wish to do something with it.
* Can use async/await or directly return a Promise.
*/
afterBuild?: (params: QuasarHookParams) => void;
/**
* Run hook if publishing was requested (`$ quasar build -P`),
* after Quasar built app for production and the afterBuild hook (if specified) was executed.
* Can use async/await or directly return a Promise.
* `opts` is Object of form `{arg, distDir}`,
* where "arg" is the argument supplied (if any) to -P parameter.
*/
onPublish?: (ops: { arg: string; distDir: string }) => void;
/**
* Public path of your app.
* Use it when your public path is something else,
* like _"<protocol>://<domain>/some/nested/folder"_ – in this case,
* it means the distributables are in _"some/nested/folder"_ on your webserver.
*
* @default '/'
*/
publicPath?: string;
/**
* @default 'index.html'
*/
htmlFilename?: string;
/**
* Folder where Quasar CLI should generate the distributables.
* Relative path to project root directory.
*
* @default 'dist/{ctx.modeName}' For all modes except Cordova.
* @default 'src-cordova/www' For Cordova mode.
*/
distDir?: string;
/**
* Ignores the public folder.
*/
ignorePublicFolder?: boolean;
/**
* Sets [Vue Router mode](https://router.vuejs.org/guide/essentials/history-mode.html).
* History mode requires configuration on your deployment web server too.
* For Capacitor and Electron, it's always 'hash' for [compatibility reasons](https://github.com/quasarframework/quasar/issues/17322#issuecomment-2191987962).
*
* @default 'hash'
*/
vueRouterMode?: "hash" | "history";
/**
* Sets Vue Router base.
* Should not need to configure this, unless absolutely needed.
*/
vueRouterBase?: string;
/** Include vue runtime + compiler version, instead of default Vue runtime-only. */
vueCompiler?: boolean;
/**
* Automatically open remote Vue Devtools when running in development mode.
*/
vueDevtools?: boolean;
/**
* Should the Vue Options API be available? If all your components only use Composition API
* it would make sense performance-wise to disable Vue Options API for a compile speedup.
*
* @default true
*/
vueOptionsAPI?: boolean;
/** Show a progress bar while compiling with Webpack. */
webpackShowProgress?: boolean;
/**
* Source map [strategy](https://webpack.js.org/configuration/devtool/) to use.
*/
webpackDevtool?: WebpackConfiguration["devtool"];
/**
* @example
* {
* // import { ... } from 'locales/...'
* locales: path.join(__dirname, 'src/locales')
* }
*/
alias?: { [key: string]: string };
/**
* Configuration for TypeScript integration.
*/
typescript?: {
/**
* Once your codebase is fully using TypeScript and all team members are comfortable with it,
* you can set this to `true` to enforce stricter type checking.
* It is recommended to set this to `true` and use stricter typescript-eslint rules.
*
* It will set the following TypeScript options:
* - "strict": true
* - "allowUnreachableCode": false
* - "allowUnusedLabels": false
* - "noImplicitOverride": true
* - "exactOptionalPropertyTypes": true
* - "noUncheckedIndexedAccess": true
*
* @see https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html#getting-stricter-checks
*/
strict?: boolean;
/**
* Extend the generated `.quasar/tsconfig.json` file.
*
* If you don't have dynamic logic, you can directly modify your `tsconfig.json` file instead.
*/
extendTsConfig?: (tsConfig: TSConfig) => void;
/**
* Generate a shim file for `*.vue` files to process them as plain Vue component instances.
*
* Vue Language Tools VS Code extension can analyze `*.vue` files in a better way, without the shim file.
* So, you can disable the shim file generation and let the extension handle the types.
*
* However, some tools like ESLint can't work with `*.vue` files without the shim file.
* So, if your tooling is not properly working, enable this option.
*/
vueShim?: boolean;
};
/**
* Add properties to `process.env` that you can use in your website/app JS code.
*
* @example { SOMETHING: 'someValue' }
*/
env?: { [index: string]: string | boolean | undefined | null };
/**
* Defines constants that get replaced in your app.
* Unlike `env`, you will need to use JSON.stringify() on the values yourself except for booleans.
* Also, these will not be prefixed with `process.env.`.
*
* @example { SOMETHING: JSON.stringify('someValue') } -> console.log(SOMETHING) // console.log('someValue')
*/
rawDefine?: { [index: string]: string | boolean | undefined | null };
/**
* Folder where Quasar CLI should look for .env* files.
* Can be an absolute path or a relative path to project root directory.
*
* @default project root directory
*/
envFolder?: string;
/**
* Additional .env* files to be loaded.
* Each entry can be an absolute path or a relative path to quasar.config > build > envFolder.
*
* @example ['.env.somefile', '../.env.someotherfile']
*/
envFiles?: string[];
/**
* Gzip the distributables.
* Could be either a boolean or compression plugin options object.
* In addition, you can specify which file extension you want to
* gzip with extension array field in replacement of compression plugin test option.
* By default it's ['js','css'].
* @example
* {
* extension: ['js','css','svg'],
* threshold: 0,
* minRatio: 1
* }
* @default false
*/
gzip?:
| boolean
| (DefinedDefaultAlgorithmAndOptions<any> & {
extensions: string[];
});
/**
* Show analysis of build bundle with webpack-bundle-analyzer.
* When providing an object, it represents webpack-bundle-analyzer config options.
*/
analyze?: boolean | BundleAnalyzerPlugin.Options;
/**
* Minification options. [Full list](https://github.com/webpack-contrib/terser-webpack-plugin/#minify).
*/
uglifyOptions?: TerserOptions;
/** Options to supply to `sass-loader` for `.scss` files. */
scssLoaderOptions?: object;
/** Options to supply to `sass-loader` for [`.sass`](https://github.com/webpack-contrib/sass-loader#sassoptions) files. */
sassLoaderOptions?: object;
/** Options to supply to `stylus-loader`. */
stylusLoaderOptions?: object;
/** Options to supply to `less-loader`. */
lessLoaderOptions?: object;
/** Options to supply to `vue-loader` */
vueLoaderOptions?: object;
/** Options to supply to `ts-loader` */
tsLoaderOptions?: object;
/**
* RTL options. [Full list](https://github.com/vkalinichev/postcss-rtl).
* When providing an object, it is the configuration for postcss-rtl plugin, and if fromRTL is present it will only be used for client styles
* When providing a function, the function will receive a boolean that is true for client side styles and false otherwise and the path to the style file
*
*/
rtl?:
| boolean
| object
| ((isClientCSS: boolean, resourcePath: string) => object);
/**
* Set to `false` to disable minification, or specify the minifier to use.
* Available options are 'terser' or 'esbuild'.
* If set to anything but boolean false then it also applies to CSS.
* For production only.
* @default 'esbuild'
*/
minify?: boolean | 'terser' | 'esbuild';
/**
* Minification options for html-minifier-terser: https://github.com/terser/html-minifier-terser?tab=readme-ov-file#options-quick-reference
* @default
* {
* removeComments: true,
* collapseWhitespace: true,
* removeAttributeQuotes: true,
* collapseBooleanAttributes: true,
* removeScriptTypeAttributes: true
* }
*/
htmlMinifyOptions?: HtmlMinifierOptions;
/**
* If `true`, a separate sourcemap file will be created. If 'inline', the
* sourcemap will be appended to the resulting output file as data URI.
* 'hidden' works like `true` except that the corresponding sourcemap
* comments in the bundled files are suppressed.
* @default false
*/
sourcemap?: boolean | 'inline' | 'hidden';
}例如,如果你运行 “quasar build --debug”,则 sourceMap 和 extractCSS 会被强制设为 “true”,不受你的配置影响。
sourceFiles
使用此属性可以修改应用中部分文件的默认名称。所有路径都必须是相对于项目根目录的相对路径。
/**
* Use this property to change the default names of some files of your website/app if you have to.
* All paths must be relative to the root folder of your project.
*
* @default
* {
* rootComponent: 'src/App.vue',
* router: 'src/router/index',
* store: 'src/stores/index',
* indexHtmlTemplate: 'index.html',
* pwaRegisterServiceWorker: 'src-pwa/register-service-worker',
* pwaServiceWorker: 'src-pwa/custom-service-worker',
* pwaManifestFile: 'src-pwa/manifest.json',
* electronMain: 'src-electron/electron-main',
* bexManifestFile: 'src-bex/manifest.json'
* }
*/
sourceFiles: {
rootComponent?: string;
router?: string;
store?: string;
indexHtmlTemplate?: string;
pwaRegisterServiceWorker?: string;
pwaServiceWorker?: string;
pwaManifestFile?: string;
electronMain?: string;
bexManifestFile?: string;
}htmlVariables
/** Add variables that you can use in /index.html. */
htmlVariables?: Record<string, any>;你可以定义变量,然后在 /index.html 中引用它们,示例如下:
import { defineConfig } from "#q-app/wrappers";
export default defineConfig((ctx) => {
return {
htmlVariables: {
myVar: "some-content",
},
};
});然后在模板中使用:
<%= myVar %> <% if (myVar) { %>something<% } %>再来一个例子:
htmlVariables: {
title: 'test name',
some: {
prop: 'my-prop'
}
}在模板中使用:
<%= title %> <%= some.prop %> <% if (some.prop) { %><%= title %><% } %>示例:为 dev/build 设置环境变量
请参考文档中的 添加到 process.env 章节。
深入理解 Webpack 配置
详情请参阅 处理 Webpack 配置 文档页面。