@quasar/app-vite
Version:
Quasar Framework App CLI with Vite
437 lines (421 loc) • 14.2 kB
TypeScript
import { Plugin, UserConfig as ViteUserConfig } from "vite";
import { Options as VuePluginOptions } from "@vitejs/plugin-vue";
import { QuasarHookParams } from "./conf";
import { CompilerOptions, TypeAcquisition } from "typescript";
interface HtmlMinifierOptions {
caseSensitive?: boolean;
collapseBooleanAttributes?: boolean;
collapseInlineTagWhitespace?: boolean;
collapseWhitespace?: boolean;
conservativeCollapse?: boolean;
continueOnParseError?: boolean;
customAttrAssign?: RegExp[];
customAttrCollapse?: RegExp;
customAttrSurround?: RegExp[];
customEventAttributes?: RegExp[];
decodeEntities?: boolean;
html5?: boolean;
ignoreCustomComments?: RegExp[];
ignoreCustomFragments?: RegExp[];
includeAutoGeneratedTags?: boolean;
keepClosingSlash?: boolean;
maxLineLength?: number;
minifyCSS?: boolean;
minifyJS?: boolean;
minifyURLs?: boolean;
preserveLineBreaks?: boolean;
preventAttributesEscaping?: boolean;
processConditionalComments?: boolean;
processScripts?: string[];
quoteCharacter?: string;
removeAttributeQuotes?: boolean;
removeComments?: boolean;
removeEmptyAttributes?: boolean;
removeEmptyElements?: boolean;
removeOptionalTags?: boolean;
removeRedundantAttributes?: boolean;
removeScriptTypeAttributes?: boolean;
removeStyleLinkTypeAttributes?: boolean;
removeTagWhitespace?: boolean;
sortAttributes?: boolean;
sortClassName?: boolean;
trimCustomFragments?: boolean;
useShortDoctype?: boolean;
}
// TSConfig type is adapted from https://github.com/unjs/pkg-types/blob/0bec64641468c9560dea95da2cff502ea8118286/src/types/tsconfig.ts
type StripEnums<T extends Record<string, any>> = {
[K in keyof T]: T[K] extends boolean
? T[K]
: T[K] extends string
? T[K]
: T[K] extends object
? T[K]
: T[K] extends Array<any>
? T[K]
: T[K] extends undefined
? undefined
: any;
};
interface TSConfig {
compilerOptions?: StripEnums<CompilerOptions>;
exclude?: string[];
compileOnSave?: boolean;
extends?: string | string[];
files?: string[];
include?: string[];
typeAcquisition?: TypeAcquisition;
}
interface InvokeParams {
isClient: boolean;
isServer: boolean;
}
interface BuildTargetOptions {
/**
* @default ['es2022', 'firefox115', 'chrome115', 'safari14']
*/
browser?: string | string[];
/**
* @example 'node20'
*/
node?: string;
}
interface PluginEntryRunOptions {
server?: boolean;
client?: boolean;
}
type PluginEntry =
| [pluginName: string, options?: any, runOptions?: PluginEntryRunOptions]
| [
pluginFactory: (options?: any) => Plugin,
options?: any,
runOptions?: PluginEntryRunOptions
]
| Plugin
| null
| undefined
| false;
interface QuasarStaticBuildConfiguration {
/**
* @example
* {
* browser: ['es2022', 'firefox115', 'chrome115', 'safari14'],
* node: 'node20'
* }
*/
target?: BuildTargetOptions;
/**
* Extend Vite config generated by Quasar CLI.
*
* You can either return overrides or directly modify the config object.
*
* @example
* ```js
* // return overrides
* extendViteConf: (config) => ({
* optimizeDeps: {
* include: ['some-package']
* }
* })
* ```
*
* @example
* ```js
* // directly modify the config object
* import { mergeConfig } from 'vite'
* // ...
* extendViteConf(config) {
* config.optimizeDeps = mergeConfig(config.optimizeDeps, {
* include: ['some-package']
* }, false)
* }
* ```
*/
extendViteConf?: (
config: ViteUserConfig,
invokeParams: InvokeParams
) => ViteUserConfig | void;
/**
* Options to supply to @vitejs/plugin-vue
*
* @see https://v2.quasar.dev/quasar-cli-vite/handling-vite#vite-vue-plugin-options
*/
viteVuePluginOptions?: VuePluginOptions;
/**
* Vite plugins
*
* @see https://v2.quasar.dev/quasar-cli-vite/handling-vite#adding-vite-plugins
*
* @example
* // ESM
* import { somePlugin } from 'some-plugin'
* // ...
* [
* [ 'some-plugin', { ...pluginOptions... } ],
*
* // disable running on client or server threads (set server/client to false):
* [ 'some-plugin', { ...pluginOptions... }, { server: true, client: true } ],
*
* [ somePlugin, { ...pluginOptions... } ],
*
* // disable running on client or server threads (set server/client to false):
* [ somePlugin, { ...pluginOptions... }, { server: true, client: true } ],
*
* somePlugin({ ...pluginOptions... })
* ]
*
* @example
* // CJS
* [
* [ 'some-plugin', { ...pluginOptions... } ],
*
* // disable running on client or server threads (set server/client to false):
* [ 'some-plugin', { ...pluginOptions... }, { server: true, client: true } ],
*
* [ require('some-plugin'), { ...pluginOptions... } ],
*
* // disable running on client or server threads (set server/client to false):
* [ require('some-plugin'), { ...pluginOptions... }, { server: true, client: true } ],
*
* require('some-plugin')({ ...pluginOptions... })
* ]
*/
vitePlugins?: PluginEntry[];
/**
* @see https://v2.quasar.dev/quasar-cli-vite/handling-vite#folder-aliases
*
* @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;
};
/**
* 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;
/**
* 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;
/**
* 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;
/**
* Do you want to analyze the production bundles?
* Generates and opens an HTML report.
*
* @default false
*/
analyze?: boolean;
/**
* 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;
/**
* Add properties to `process.env` that you can use in your website/app JS code.
*
* @see https://v2.quasar.dev/quasar-cli-vite/handling-process-env
*
* @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[];
/**
* Filter the env variables that are exposed to the client
* through the env files. This does not account also for the definitions
* assigned directly to quasar.config > build > env prop.
*/
envFilter?: (env: {
[index: string]: string | boolean | undefined | null;
}) => {
[index: string]: string | boolean | undefined | null;
};
/**
* Build production assets with or without the hash part in filenames.
* Example: "454d87bd" in "assets/index.454d87bd.js"
*
* When used, please be careful how you configure your web server cache strategy as
* files will not change name so your client might get 304 (Not Modified) even when
* it's not the case.
*
* Will not change anything if your Vite config already touches the
* build.rolldownOptions.output.entryFileNames/chunkFileNames/assetFileNames props.
*
* Gets applied to production builds only.
*
* Useful especially for (but not restricted to) PWA. If set to false then updating the
* PWA will force to re-download all assets again, regardless if they were changed or
* not (due to how Rolldown works through Vite).
*
* @default true
*/
useFilenameHashes?: boolean;
/**
* whether to inject module preload polyfill.
* @default false
*/
polyfillModulePreload?: boolean;
/**
* Ignores the public folder.
* @default false
*/
ignorePublicFolder?: boolean;
/**
* 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;
}
/**
* Following properties of `build` are automatically configured by Quasar CLI
* depending on dev/build commands and Quasar mode.
* You can override some, but make sure you know what you are doing.
*/
interface QuasarDynamicBuildConfiguration {
/**
* Set to `false` to disable minification, or specify the minifier to use.
* Available options are 'oxc' (recommended) or 'terser'.
* If set to anything but boolean false then it also applies to CSS.
* For production only.
* @default 'oxc'
*/
minify?: boolean | "oxc" | "terser";
/**
* Minification options for html-minifier-terser.
*
* @see https://github.com/terser/html-minifier-terser?tab=readme-ov-file#options-quick-reference for complete list of options
*
* @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";
}
export type QuasarBuildConfiguration = QuasarStaticBuildConfiguration &
QuasarDynamicBuildConfiguration;