From e3f3cc9896dd6977c61ccdc83b713f81a54185ba Mon Sep 17 00:00:00 2001 From: Jeff Date: Tue, 14 Jul 2026 11:45:21 -0600 Subject: [PATCH 1/3] fix(app-vite): audit Cordova mode and guide --- app-vite/lib/modes/cordova/cordova-builder.js | 4 +- .../types/configuration/cordova-conf.d.ts | 21 +- .../app-icons-cordova.md | 21 +- .../developing-cordova-apps/build-commands.md | 20 +- .../configuring-cordova.md | 26 +- .../cordova-plugins.md | 31 +-- .../managing-google-analytics.md | 84 ++----- .../developing-cordova-apps/preparation.md | 163 +++---------- .../publishing-to-store.md | 172 +++---------- .../troubleshooting-and-tips.md | 225 +++--------------- 10 files changed, 167 insertions(+), 600 deletions(-) diff --git a/app-vite/lib/modes/cordova/cordova-builder.js b/app-vite/lib/modes/cordova/cordova-builder.js index 38fe682bac0..8098230d292 100644 --- a/app-vite/lib/modes/cordova/cordova-builder.js +++ b/app-vite/lib/modes/cordova/cordova-builder.js @@ -80,7 +80,9 @@ export class QuasarModeBuilder extends AppBuilder { const outputTargetList = ensureArray( this.quasarConf.cordova.getCordovaBuildOutputFolder?.(cordovaContext) - ) || cordovaOutputFolders[target] + ) || + cordovaOutputFolders[target] || + [] // Remove old build output outputTargetList.forEach(outputFile => { diff --git a/app-vite/types/configuration/cordova-conf.d.ts b/app-vite/types/configuration/cordova-conf.d.ts index edf20d9864b..28ffdb6f81f 100644 --- a/app-vite/types/configuration/cordova-conf.d.ts +++ b/app-vite/types/configuration/cordova-conf.d.ts @@ -3,6 +3,7 @@ export type QuasarCordovaTargets = | "ios" | "blackberry10" | "browser" + | "electron" | "osx" | "ubuntu" | "webos" @@ -20,15 +21,15 @@ export interface QuasarCordovaConfiguration { * will be executed after the UI has compiled. * * @param context.debug - True if in debug mode - * @param context.target - The target platform (ios/android) + * @param context.target - The target platform * @returns Array of strings (command parameters) * * @default: [ 'build', '--debug'/'--release', '--device', 'ios'/'android' ] - * @example: ({ isDebug, target }) => [ 'build', `--${isDebug ? 'debug' : 'release'}`, '--device', 'target' ] + * @example: ({ debug, target }) => [ 'build', `--${debug ? 'debug' : 'release'}`, '--device', target ] */ getCordovaBuildParams?: (context: { readonly debug: boolean; - readonly target: "ios" | "android"; + readonly target: QuasarCordovaTargets; }) => string[]; /** @@ -38,24 +39,24 @@ export interface QuasarCordovaConfiguration { * to the /dist folder. * * @param context.debug - True if in debug mode - * @param context.target - The target platform (ios/android) + * @param context.target - The target platform * @returns string | string[] | undefined - (relative path(s) from /src-cordova) * * @default ios: platforms/ios/build/... and android: platforms/android/app/build/outputs * @example: - * ({ isDebug, target }) => { + * ({ debug, target }) => { * return target === 'ios' - * ? `platforms/ios/build/${isDebug ? 'Debug' : 'Release'}-iphoneos + * ? `platforms/ios/build/${debug ? 'Debug' : 'Release'}-iphoneos` * : 'platforms/android/app/build/outputs' * } * @example: (when interested in only one platform, leaving the other to the default value) - * ({ isDebug, target }) => { + * ({ debug, target }) => { * if (target === 'ios') { - * return `platforms/ios/build/${isDebug ? 'Debug' : 'Release'}-iphoneos` + * return `platforms/ios/build/${debug ? 'Debug' : 'Release'}-iphoneos` * } * } * @example: () - * ({ isDebug, target }) => { + * ({ debug, target }) => { * if (target === 'ios') { * // try these two folders * return [ 'platforms/ios/build/device', 'platforms/ios/build/emulator' ] @@ -64,6 +65,6 @@ export interface QuasarCordovaConfiguration { */ getCordovaBuildOutputFolder?: (context: { readonly debug: boolean; - readonly target: "ios" | "android"; + readonly target: QuasarCordovaTargets; }) => string | string[] | undefined; } diff --git a/docs/src/pages/quasar-cli-vite/developing-cordova-apps/app-icons-cordova.md b/docs/src/pages/quasar-cli-vite/developing-cordova-apps/app-icons-cordova.md index bad9a9e829a..48e2a557a35 100644 --- a/docs/src/pages/quasar-cli-vite/developing-cordova-apps/app-icons-cordova.md +++ b/docs/src/pages/quasar-cli-vite/developing-cordova-apps/app-icons-cordova.md @@ -26,7 +26,7 @@ scope: - l: icon.png e: 57x57 - l: icon@2x.png - e: 144x144 + e: 114x114 - l: icon-20@2x.png - l: icon-20@3x.png - l: icon-29.png @@ -95,7 +95,7 @@ scope: - l: Default@2x~ipad~anyany.png --- -Cordova is one of the most complicated of all of the build targets as far as icons go, because not only do you need to place the icons in specific folders, you also need to register them in the `src-cordova/config.xml` file. Further, if you are using splash screens (which you should), you will also need to install `cordova-plugin-splashscreen` and register it in your config.xml. +Cordova icons and splash screens are native resources declared in `/src-cordova/config.xml`. The required files and declarations depend on the installed `cordova-android` and `cordova-ios` versions. If you discover one file that is new or missing, please [open an issue](https://github.com/quasarframework/quasar/issues). @@ -115,13 +115,7 @@ icongenie generate -m cordova -i /path/to/source/icon.png [-b /path/to/backgroun ## Manual instructions -Unless you are using the Icon Genie CLI, this is what you need to do: - -```bash -cd src-cordova -cordova plugin add cordova-plugin-splashscreen -cordova plugin save -``` +Unless you are using Icon Genie CLI, replace the generated resources and keep their `config.xml` declarations aligned with the requirements of each installed Cordova platform. Current Cordova platforms provide splash-screen handling; install `cordova-plugin-splashscreen` only when an older platform version explicitly requires it. @@ -182,14 +176,5 @@ And here is part of what your config.xml should look like: - - - - - - - - - ``` diff --git a/docs/src/pages/quasar-cli-vite/developing-cordova-apps/build-commands.md b/docs/src/pages/quasar-cli-vite/developing-cordova-apps/build-commands.md index deeadb134ca..66694cef44c 100644 --- a/docs/src/pages/quasar-cli-vite/developing-cordova-apps/build-commands.md +++ b/docs/src/pages/quasar-cli-vite/developing-cordova-apps/build-commands.md @@ -1,12 +1,12 @@ --- -title: Mobile App Build Commands +title: Cordova Build Commands desc: (@quasar/app-vite) The Quasar CLI list of commands when developing or building a hybrid mobile app with Cordova. --- Before we dive in, make sure you got the Cordova CLI installed. ```bash -npm install -g cordova +pnpm add --global cordova ``` ## Developing @@ -27,7 +27,7 @@ quasar dev -m cordova -T ios '--' some params --and options --here It will open the IDE (Android Studio / Xcode) and from there you can manually select the emulator (or multiple ones simultaneously!) and install the dev app on it/them. You can also run the dev app on a real mobile/tablet device. ::: warning -In Android Studio, you will be greeted with a message recommending to upgrade the Gradle version. **DO NOT UPGRADE GRADLE** as it will break the Cordova project. Same goes for any other requested upgrades. +Do not accept Android Studio upgrade suggestions automatically. Confirm that the proposed Java, Gradle, Android Gradle Plugin, and SDK versions are supported by the installed `cordova-android` version. Gradle upgrade @@ -42,15 +42,15 @@ In order for you to be able to develop on a device emulator or directly on a pho 1. Detects your machine's external IP address. If there are multiple such IPs detected, then it asks you to choose one. If you'll be using a mobile phone to develop then choose the IP address of your machine that's pingable from the phone/tablet. 2. It starts up a development server on your machine. 3. It temporarily changes the `` tag in `/src-cordova/config.xml` to point to the IP previously detected. This allows the app to connect to the development server. -4. It defers to Cordova CLI to build a native app with the temporarily changed config.xml. -5. Cordova CLI checks if a mobile phone / tablet is connected to your development machine. If it is, it installs the development app on it. If none is found, then it boots up an emulator and runs the development app. -6. Finally, it reverts the temporary changes made to `/src-cordova/config.xml`. +4. It runs `cordova prepare` for the selected platform. +5. It opens Android Studio or Xcode, where you select and run an emulator, simulator, or connected device. +6. When the Cordova development process stops, Quasar reverts its temporary changes to `/src-cordova/config.xml`. ::: danger -If developing on a mobile phone/tablet, it is very important that the external IP address of your build machine is accessible from the phone/tablet, otherwise you'll get a development app with white screen only. Also check your machine's firewall to allow connections to the development chosen port. +When developing on a physical device, the selected address of the development machine must be reachable from that device. Ensure the firewall permits the development-server port and that the network does not isolate connected clients. ::: -## Building for Production +## Building for production ```bash quasar build -m cordova -T [android|ios] @@ -70,7 +70,7 @@ quasar build -m cordova -T ios -- some params --and options --here - Built packages will be located in `/dist/cordova` unless configured otherwise. -- If you wish to skip the Cordova CLI packaging step and only fill `/src-cordova/www` folder: +- If you wish to skip the native Cordova build, generate `/src-cordova/www` and run `cordova prepare` only: ```bash quasar build -m cordova -T [ios|android] --skip-pkg @@ -83,7 +83,7 @@ quasar build -m cordova -T [ios|android] --ide ``` ::: warning -In Android Studio, you will be greeted with a message recommending to upgrade the Gradle version. **DO NOT UPGRADE GRADLE** as it will break the Cordova project. Same goes for any other requested upgrades. +Do not accept Android Studio upgrade suggestions automatically. Check the compatibility requirements of the installed Cordova platform before changing the native toolchain. Gradle upgrade diff --git a/docs/src/pages/quasar-cli-vite/developing-cordova-apps/configuring-cordova.md b/docs/src/pages/quasar-cli-vite/developing-cordova-apps/configuring-cordova.md index ff08aceeafb..37803c65195 100644 --- a/docs/src/pages/quasar-cli-vite/developing-cordova-apps/configuring-cordova.md +++ b/docs/src/pages/quasar-cli-vite/developing-cordova-apps/configuring-cordova.md @@ -5,7 +5,7 @@ related: - /quasar-cli-vite/quasar-config-file --- -We'll be using Quasar CLI (and Cordova CLI) to develop and build a Mobile App. The difference between building a SPA, PWA, SSR, SSG, Electron App or a Mobile App is simply determined by the "mode" parameter in "quasar dev" and "quasar build" commands. +Quasar CLI selects the Cordova build target through the mode and target arguments passed to `quasar dev` and `quasar build`. Cordova CLI manages the native project under `/src-cordova`. There are two configuration files of great importance to your mobile apps. We'll go over each one. @@ -17,12 +17,12 @@ Some properties from this file will get overwritten as we'll see in next section ## quasar.config file -Quasar CLI helps you in setting some properties of the mobile Apps automatically (from config.xml): the Cordova "id", app version, description and android-versionCode. This is for convenience so you'll be able to have a single point where, for example, you change the version of your app, not multiple files that you need to simultaneously touch which is error prone. +Quasar CLI updates the app version, description, and optional Android version code in `config.xml` before Cordova runs. The widget `id` is set when the Cordova project is created and is not rewritten from the Quasar config. For determining the values for each of the properties mentioned above, Quasar CLI: 1. Looks in the `/quasar.config` file for a "cordova" Object. Does it have "version", "description" and/or "androidVersionCode"? If yes, it will use them. -2. If not, then it looks into your `/package.json` for "cordovaId", "version" and "description" fields. +2. If not, it falls back to `/package.json > version` and `/package.json > description`. ```ts /quasar.config file > cordova cordova: { @@ -37,13 +37,13 @@ cordova: { * will be executed after the UI has compiled. * * @param context.debug - True if in debug mode - * @param context.target - The target platform (ios/android) + * @param context.target - The target platform * @returns Array of strings (command parameters) * * @default: [ 'build', '--debug'/'--release', '--device', 'ios'/'android' ] - * @example: ({ isDebug, target }) => [ 'build', `--${isDebug ? 'debug' : 'release'}`, '--device', 'target' ] + * @example: ({ debug, target }) => [ 'build', `--${debug ? 'debug' : 'release'}`, '--device', target ] */ - getCordovaBuildParams?: (context: { debug: boolean; target: 'ios' | 'android' }) => string[]; + getCordovaBuildParams?: (context: { debug: boolean; target: string }) => string[]; /** * Function to return the Cordova output folder after the "cordova build" @@ -52,31 +52,31 @@ cordova: { * to the /dist folder. * * @param context.debug - True if in debug mode - * @param context.target - The target platform (ios/android) + * @param context.target - The target platform * @returns string | string[] | undefined - (relative path(s) from /src-cordova) * * @default ios: platforms/ios/build/... and android: platforms/android/app/build/outputs * @example: - * ({ isDebug, target }) => { + * ({ debug, target }) => { * return target === 'ios' - * ? `platforms/ios/build/${isDebug ? 'Debug' : 'Release'}-iphoneos + * ? `platforms/ios/build/${debug ? 'Debug' : 'Release'}-iphoneos` * : 'platforms/android/app/build/outputs' * } * @example: (when interested in only one platform, leaving the other to the default value) - * ({ isDebug, target }) => { + * ({ debug, target }) => { * if (target === 'ios') { - * return `platforms/ios/build/${isDebug ? 'Debug' : 'Release'}-iphoneos` + * return `platforms/ios/build/${debug ? 'Debug' : 'Release'}-iphoneos` * } * } * @example: () - * ({ isDebug, target }) => { + * ({ debug, target }) => { * if (target === 'ios') { * // try these two folders * return [ 'platforms/ios/build/device', 'platforms/ios/build/emulator' ] * } * } */ - getCordovaBuildOutputFolder?: (context: { debug: boolean; target: 'ios' | 'android' }) => string | string[] | undefined; + getCordovaBuildOutputFolder?: (context: { debug: boolean; target: string }) => string | string[] | undefined; } ``` diff --git a/docs/src/pages/quasar-cli-vite/developing-cordova-apps/cordova-plugins.md b/docs/src/pages/quasar-cli-vite/developing-cordova-apps/cordova-plugins.md index 9951faab6cc..97f476c2ab6 100644 --- a/docs/src/pages/quasar-cli-vite/developing-cordova-apps/cordova-plugins.md +++ b/docs/src/pages/quasar-cli-vite/developing-cordova-apps/cordova-plugins.md @@ -5,7 +5,7 @@ desc: (@quasar/app-vite) How to use the Cordova plugins in a Quasar app. You can hook into the native device APIs by using [Cordova Plugins](https://cordova.apache.org/docs/en/latest/#plugin-apis). -## Cordova Plugins +## Cordova plugins A few examples of such plugins: @@ -22,9 +22,9 @@ A few examples of such plugins: - Vibration - Statusbar -## Deviceready Event +## `deviceready` event -You'll notice that some Cordova plugins are usable only after the `deviceready` event has been triggered. We don't need to worry about it too much. Quasar listens to this event and takes care of our root Vue component to be mounted **after** this event has been triggered. But if you need some plugin's own variable and that is initialized after `deviceready` you can follow the example of using the plugin device below +Some Cordova plugins are usable only after `deviceready`. In Cordova mode, Quasar waits for this event before mounting the root Vue application, so component setup and lifecycle hooks can use initialized plugin APIs. ### Caveat @@ -51,7 +51,7 @@ Let's take a vue file for example: ``` -The reason is simple. Quasar listens for the event then mounts the root Vue component. But before this, the Vue files are imported into the `/src/router/routes.js` file, so the code outside of the default export gets executed. +Module-level code can still execute while Vue files are imported, before the application mounts. Avoid accessing Cordova plugin globals at module scope. If module-level initialization is unavoidable, listen for `deviceready` explicitly as shown above. ## Using a Cordova Plugin @@ -71,9 +71,6 @@ cordova plugin add cordova-plugin-battery-status Now let's put this plugin to some good use. In one of your Quasar project's pages/layouts/components Vue file, we write: ```html // some Vue file -// remember this is simply an example // only look at how we use the API -described in the plugin's page // the rest of things here are of no importance - @@ -114,10 +111,6 @@ cordova plugin add cordova-plugin-camera Now let's put this plugin to some good use. In one of your Quasar project's pages/layouts/components Vue file, we write: ```html -// some Vue file // remember this is simply an example; // only look at how we -use the API described in the plugin's page; // the rest of things here are of no -importance -