Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: [v7.5] angular standalone overlays do not load in production build #28385

Closed
3 tasks done
moose4lord opened this issue Oct 19, 2023 · 24 comments · Fixed by #28560
Closed
3 tasks done

bug: [v7.5] angular standalone overlays do not load in production build #28385

moose4lord opened this issue Oct 19, 2023 · 24 comments · Fixed by #28560
Labels
package: angular @ionic/angular package type: bug a confirmed bug report

Comments

@moose4lord
Copy link

moose4lord commented Oct 19, 2023

Prerequisites

Ionic Framework Version

v7.x

Current Behavior

While refactoring an app for Ionic v7.5 using Angular standalone components, I noticed loading and toast components don't render when deployed to an Android device. They work fine in a web app, but not on Android.

I need control over when the loading and toast components get dismissed, so I use LoadingController and ToastController components. Here's a minimal code example:

export class HomePage {
  constructor(
    public loadingCtrl: LoadingController,
    public toastController: ToastController
  ) {
    this.presentLoading();
    this.presentToast();
  }

  async presentLoading() {
    const loading = await this.loadingCtrl.create({});
    await loading.present(); // show loading indicator

    setTimeout(() => {
      loading.dismiss(); // close loading indicator
    }, 8000);
  }

  async presentToast() {
    const toast = await this.toastController.create({
      message: 'Dismiss in 4 seconds',
      duration: 4000
    });
    toast.present();
  }
}

This should display a loading spinner and a toast for a few seconds when the app starts. Works fine as a web app, but the loading spinner and toast don't display at all on Android.

Interestingly, if I add <ion-loading> and <ion-toast> tags to the home.page.html file, the problem disappears and the components render fine on Android. I don't need to actually trigger the <ion-loading> and <ion-toast> components, just add them to the code.

Expected Behavior

LoadingController and ToastController components should display properly when using Angular standalone components on Android.

Steps to Reproduce

Download the Git repository and run the code as a web app and as an Android app.

Code Reproduction URL

https://github.com/moose4lord/loadingBug.git

Ionic Info

Ionic:

Ionic CLI : 7.1.1 (/usr/local/lib/node_modules/@ionic/cli)
Ionic Framework : @ionic/angular 7.5.1
@angular-devkit/build-angular : 16.2.6
@angular-devkit/schematics : 16.2.6
@angular/cli : 16.2.6
@ionic/angular-toolkit : 9.0.0

Capacitor:

Capacitor CLI : 5.5.0
@capacitor/android : 5.5.0
@capacitor/core : 5.5.0
@capacitor/ios : not installed

Utility:

cordova-res : not installed globally
native-run : 1.7.3

System:

NodeJS : v18.18.0 (/usr/local/bin/node)
npm : 9.8.1
OS : macOS Unknown

Additional Information

No response

@ionitron-bot ionitron-bot bot added the triage label Oct 19, 2023
@liamdebeasi liamdebeasi self-assigned this Oct 19, 2023
@liamdebeasi
Copy link
Contributor

Thanks, I can reproduce this. The problem is that the controller isn't defining the underlying component. When you run a production build (and therefore treeshake out unused code) the overlay components are removed from the build since they aren't actually used.

We need to implement something similar to Vue and manually call defineCustomElement:

defineCustomElement();

@liamdebeasi liamdebeasi changed the title bug: [v7.5] Using Angular standalone components, toast and loading components don't render on Android bug: [v7.5] angular standalone overlays do not load in production build Oct 19, 2023
@liamdebeasi liamdebeasi added package: angular @ionic/angular package type: bug a confirmed bug report labels Oct 19, 2023
@liamdebeasi liamdebeasi removed their assignment Oct 19, 2023
@ionitron-bot ionitron-bot bot removed the triage label Oct 19, 2023
@moose4lord
Copy link
Author

moose4lord commented Oct 19, 2023

Ah, I see what you mean. You don't need to deploy to Android to see the issue, just run ionic serve --prod.
Good catch. I look forward to the fix.
Thanks

@singatias
Copy link

singatias commented Oct 23, 2023

I have the same issue with ModalController using angular 16 /w ionic 7, the modal works in dev but when adding the production flag nothing happens, the promise from this.modalController.create doesn't do anything, no errors and the promise is never completed.

edit: is there any solution for now? I have to deploy a new version a app for my customer since is app cannot be download on the google play store until I'm able to release a new version.

@KyleSmith0905
Copy link

Agreed, would love to have a permanent fix.

I've discovered that, as a temporary fix, you can add the following line to your angular.json file:

{
  "projects": {
    "app": {
      "architect": {
        "build": {
          "configurations": {
            "production": {
              "buildOptimization": false,
              ...
            }
            ...
          }
          ...
        }
        ...
      }
      ...
    }
    ...
  }
  ...
}

This will turn off build optimization for production builds.

When this bug is fixed, please reverse this change!! ⚠️⚠️⚠️⚠️⚠️⚠️
This is a temporary and dangerous solution.

@singatias
Copy link

Agreed, would love to have a permanent fix.

I've discovered that, as a temporary fix, you can add the following line to your angular.json file:

{
  "projects": {
    "app": {
      "architect": {
        "build": {
          "configurations": {
            "production": {
              "buildOptimization": false,
              ...
            }
            ...
          }
          ...
        }
        ...
      }
      ...
    }
    ...
  }
  ...
}

This will turn off build optimization for production builds.

When this bug is fixed, please reverse this change!! ⚠️⚠️⚠️⚠️⚠️⚠️ This is a temporary and dangerous solution.

That's a better solution than releasing with a debug build of the webview!

@liamdebeasi
Copy link
Contributor

liamdebeasi commented Nov 1, 2023

As a temporary workaround you can also do the following in app.component.ts for each controller you are using:

// if I were using the modalController, I would import from ion-modal
import { defineCustomElement } from '@ionic/core/components/ion-modal.js';

...

constructor() {
  // this registers the underlying Web Component and ensures it gets included in the final build
  defineCustomElement();
}

You'll need to alias the import if you are using multiple controller. Something like the following should work:

import { defineCustomElement as defineModal } from '@ionic/core/components/ion-modal.js';
import { defineCustomElement as defineLoading } from '@ionic/core/components/ion-loading.js';

The benefit of this approach is you can still get an optimized build.

@singatias
Copy link

You can also do the following in app.component.ts for each controller you are using:

// if I were using the modalController, I would import from ion-modal
import { defineCustomElement } from '@ionic/core/components/ion-modal.js';

...

constructor() {
  // this registers the underlying Web Component and ensures it gets included in the final build
  defineCustomElement();
}

You'll need to alias the import if you are using multiple controller. Something like the following should work:

import { defineCustomElement as defineModal } from '@ionic/core/components/ion-modal.js';
import { defineCustomElement as defineLoading } from '@ionic/core/components/ion-loading';

that's even better, thanks I will try it

@LennonReid
Copy link

LennonReid commented Nov 10, 2023

    await loading.present();
    // 111 won't appear in the console due to the LoadingController issue
    console.log(111);

I confront the same issue that prevents my code from executing and causes me to spend a lot of time debugging. After much troubleshooting, I discovered the root of the problem was related to the LoadingController. Then, I found this related issue and found the workaround.

By the way, it's crucial to confirm that you're utilizing the @ionic/angular and @ionic/core versions—preferably 7.5.4 or the latest—to take advantage of the provided workaround. I encountered an issue with the loadingController, causing a black background consistently on @ionic/core version 7.5.2.

Moreover, I suggest including relevant keywords such as LoadingController, AlertController, ModalController, etc., in the issue title. This will make it more convenient for developers facing similar problems to identify and engage with the issue efficiently.

However, I worry this bug will affect more developers as they migrate to the angular standalone approach. I sincerely hope the Ioinic team can resolve this soon before it becomes a major blockade for the community.

@petem24
Copy link

petem24 commented Nov 17, 2023

Same issue here on a new project. During the setup wizard Ionic recommends using the new standalone approach as well.

"buildOptimizer": false,

Fixed with this for now. Hoping the Ionic team can fix this ASAP

@danielsogl
Copy link
Contributor

@liamdebeasi any update on fixing this issue in the next bugfix release? The workaround you provided is working but it feels a bit hacky imho

@adedayojs
Copy link

adedayojs commented Nov 20, 2023

I have been facing this issue since two days ago and was about to open a ticket for this.

Suprisingly adding an empty <ion-modal></ion-modal> works for me

Update::

You don't have to do this everywhere you want to create your modal. Using the tag once you can call your modal anywhere and it works

@hakimio
Copy link

hakimio commented Nov 20, 2023

@adedayojs other stuff like alerts and toasts still don't work with your workaround.

@liamdebeasi
Copy link
Contributor

Here's a dev build with a proposed fix if anyone is interested in testing:

npm install @ionic/[email protected]

@adedayojs
Copy link

@adedayojs other stuff like alerts and toasts still don't work with your workaround.

The same approach can be used for the respective overlay components. I however think there is already a pull request #28560 attending to this

github-merge-queue bot pushed a commit that referenced this issue Nov 20, 2023
…28560)

Issue number: resolves #28385

---------

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

Overlay controllers do not register their respective overlays
components. This results in the overlay not appearing.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Each standalone overlay controller manually calls
`defineCustomElement` for their respective overlay component to ensure
the component is loaded/registered.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->


Dev build: `7.5.6-dev.11700492285.1581ed02`
@liamdebeasi
Copy link
Contributor

Thanks for the issue. This has been resolved via #28560, and a fix will be available in an upcoming release of Ionic Framework. Please feel free to continue testing the dev build, and let me know if you run into any issues.

@moose4lord
Copy link
Author

I upgraded to @ionic/angular v7.5.6, released just a few hours ago, and the loading and toast controllers are working properly now in production. Nice job!
Thank you.

@kumadam
Copy link

kumadam commented Nov 24, 2023

After upgrade v7.5.6, I am getting below error. When I remove ModalController from tabs.page.ts it's ok.

src_app_pages_feed_feed_page_ts.js:2 ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(Environment Injector)[ModalController -> ModalController]:
NullInjectorError: No provider for ModalController!
NullInjectorError: R3InjectorError(Environment Injector)[ModalController -> ModalController]:
NullInjectorError: No provider for ModalController!
at NullInjector.get (core.mjs:8890:27)
at R3Injector.get (core.mjs:9334:33)
at R3Injector.get (core.mjs:9334:33)
at ChainedInjector.get (core.mjs:14018:36)
at lookupTokenUsingModuleInjector (core.mjs:4608:39)
at getOrCreateInjectable (core.mjs:4656:12)
at Module.ɵɵdirectiveInject (core.mjs:11801:19)
at NodeInjectorFactory.TabsPage_Factory [as factory] (tabs.page.ts:21:22)
at getNodeInjectable (core.mjs:4862:44)
at createRootComponent (core.mjs:14273:35)
at resolvePromise (zone.js:1193:31)
at resolvePromise (zone.js:1147:17)
at zone.js:1260:17
at _ZoneDelegate.invokeTask (zone.js:402:31)
at core.mjs:10757:55
at AsyncStackTaggingZoneSpec.onInvokeTask (core.mjs:10757:36)
at _ZoneDelegate.invokeTask (zone.js:401:60)
at Object.onInvokeTask (core.mjs:11070:33)
at _ZoneDelegate.invokeTask (zone.js:401:60)
at Zone.runTask (zone.js:173:47)

@liamdebeasi
Copy link
Contributor

Please file a new issue and include a reproduction.

@LennonReid
Copy link

After upgrade v7.5.6, I am getting below error. When I remove ModalController from tabs.page.ts it's ok.

src_app_pages_feed_feed_page_ts.js:2 ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(Environment Injector)[ModalController -> ModalController]:

NullInjectorError: No provider for ModalController!

NullInjectorError: R3InjectorError(Environment Injector)[ModalController -> ModalController]:

NullInjectorError: No provider for ModalController!

at NullInjector.get (core.mjs:8890:27)

at R3Injector.get (core.mjs:9334:33)

at R3Injector.get (core.mjs:9334:33)

at ChainedInjector.get (core.mjs:14018:36)

at lookupTokenUsingModuleInjector (core.mjs:4608:39)

at getOrCreateInjectable (core.mjs:4656:12)

at Module.ɵɵdirectiveInject (core.mjs:11801:19)

at NodeInjectorFactory.TabsPage_Factory [as factory] (tabs.page.ts:21:22)

at getNodeInjectable (core.mjs:4862:44)

at createRootComponent (core.mjs:14273:35)

at resolvePromise (zone.js:1193:31)

at resolvePromise (zone.js:1147:17)

at zone.js:1260:17

at _ZoneDelegate.invokeTask (zone.js:402:31)

at core.mjs:10757:55

at AsyncStackTaggingZoneSpec.onInvokeTask (core.mjs:10757:36)

at _ZoneDelegate.invokeTask (zone.js:401:60)

at Object.onInvokeTask (core.mjs:11070:33)

at _ZoneDelegate.invokeTask (zone.js:401:60)

at Zone.runTask (zone.js:173:47)

When upgrading to v7.5.6, I faced a similar issue by not adopting the standalone approach.

Consider incorporating the standalone approach importing from ionic/angular/standalone, rather than ionic/angular—or,alternatively, downgrade to version v7.5.4 for resolving this issue.

I hope this suggestion proves helpful.

@adedayojs
Copy link

For some reasons, The modals work now in production by default. Toast however don't work in production yet (they work in dev mode). Is anyone facing this issue also?

@hakimio
Copy link

hakimio commented Nov 28, 2023

@adedayojs toasts work fine for me in production. ToastController has been fixed.

@adedayojs
Copy link

hakimio

Thanks it works fine. I wasn't importing from the standalone version.

@hakimio
Copy link

hakimio commented Nov 28, 2023

If you are using eslint, you can add the following rule to make sure you always import from standalone:

"@typescript-eslint/no-restricted-imports": [
  "error",
  {
    "paths": [
      {
        "name": "@ionic/angular",
        "message": "Please import Ionic standalone components instead: `import {IonButton} from '@ionic/angular/standalone'`.",
        "allowTypeImports": true
      }
    ]
  }
]

Copy link

ionitron-bot bot commented Dec 28, 2023

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators Dec 28, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
package: angular @ionic/angular package type: bug a confirmed bug report
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants