ionic-framework icon indicating copy to clipboard operation
ionic-framework copied to clipboard

bug: Angular: Components that are lazy loaded for the first time are not hydrated immediately

Open dexster opened this issue 1 year ago • 2 comments

Prerequisites

Ionic Framework Version

  • [ ] v4.x
  • [ ] v5.x
  • [X] v6.x
  • [ ] Nightly

Current Behavior

Disclaimer: This may be expected behaviour to prevent layout shift but I cannot find any documentation regarding this and solutions on how to get around this.

When navigating to an angular route with an ion-list (will possibly apply to any ion component) in an ion-card, all contents of the card do not display until the ion-list has been fetched from the server. This is especially noticeable on slow connections.

"preloadingStrategy: PreloadAllModules" does not solve this issue

Expected Behavior

Available ion-card content should be visible while lazy loaded components are fetched from the server.

Steps to Reproduce

Open the code reproduction URL below. Once opened, set your network performance to "Slow 3G" in Chrome dev tools. Click the "Show list" link. Observe the "Page load start" text displays immediately. The "Card content" text only displays once the ion-list has loaded.

In view-message.page.html, comment out the in the and uncomment the above the card
Reload the app starting from the home page. You may want to reset your network to "No throttling" while doing this Set the network back to "Slow 3G" Observe that "Card content" loads as soon as the page opens when clicking the "Show list" link

Code Reproduction URL

https://stackblitz.com/edit/angular-ivy-rnqahb?file=src%2Fapp%2Fhome%2Fhome.page.html

Ionic Info

All info is in the stackblitz demo

Additional Information

I can make the load earlier as you can see in the home.page.html commented out code on lines 6-8 but this does not seem like a proper solution. Is there a way to render card content without waiting for ionic components to be fetched?

dexster avatar Jul 15 '22 16:07 dexster

@dexster thanks for reporting this issue!

The behavior you are observing is the effect of the lazy-hydrated bundle from Stencil that is used in our @ionic/angular package.

Web components are lazily requested and defined, as they are used in the DOM. Since you are lazy loading the modules for routing, ion-list is not requested in the DOM until that route is resolved.

Unfortunately, there isn't a great workaround here other than including the element in the DOM and hiding it, like you have done in your commented out example.

In v7 we are moving away from the lazy-hydrated bundle for Angular and moving to the custom elements build, which is currently leveraged by @ionic/react and @ionic/vue. With that, you should not have any delay in rendering in your scenario, as web components are either defined upfront on bootstrap or upon DOM request (without a hydration cycle from Stencil).

I'll leave this issue open and classify it, as I do believe our efforts in the next major release should resolve this. In the event I am wrong, other team members can add their thoughts of appropriate workarounds/configurations to avoid this problem.

sean-perkins avatar Jul 15 '22 17:07 sean-perkins

Thanks for the feedback.

The main issue I am having is the ion-card not displaying until inner components are loaded. Preloading the components upfront does help but wouldn't it be preferable to not prevent the card from rendering while inner components are hydrated/loading? I use ion-cards in previous screens so it's already loaded. Or does the whole card/list become the lazy hydrated bundle you mentioned?

If this is already part of your efforts you mentioned then I'm happy to wait.

FYI,

Apart from adding a few preloaded ion components to my page with "display: none" I also had to do this so that my loading spinner worked correctly otherwise I would navigate to a page and no spinner was shown because it was busy loading when it should have been spinning

  preloadLoaderHack() {
    this.loadingController
      .create({
        spinner: 'circular',
        showBackdrop: false,
        cssClass: 'pre-load',
      })
      .then((loader) => {
        loader.present();
        loader.dismiss();
      });
  } 

dexster avatar Jul 18 '22 20:07 dexster

I see this still happens with v7.

dexster avatar Jun 13 '23 12:06 dexster

@sean-perkins any timeline for utilizing custom elements build in Angular library? This would also allow using the new esbuild/vite compiler with Angular.

hakimio avatar Jul 04 '23 15:07 hakimio

Hi everyone,

We recently released Ionic components as Angular standalone components in Ionic 7.5.0 which makes use of the new build system Sean mentioned in https://github.com/ionic-team/ionic-framework/issues/25646#issuecomment-1185747390. The documentation for this feature is available here: https://ionicframework.com/docs/angular/build-options

This build system doesn't use hydration, so the original issue should not occur when using Ionic components as standalone components. I recommend using this feature if you would like to avoid hydration. I am going to close this issue, but let me know if there are any questions.

liamdebeasi avatar Oct 26 '23 19:10 liamdebeasi

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[bot] avatar Nov 25 '23 20:11 ionitron-bot[bot]