V3 to v4 migration done - performance degraded

Hi,

So I just spent every night for two weeks to migrate my app from V3 to V4. I have mixed feelings about this… And wonder if I need to tweak some more things.

Because right now, the performance has been really degraded from v3 to v4 ! I mean :

Total initial boot time
v3 : 6s
v4 : 10s

hot reload with serve
v3 : 2 - 3s
v4 : 12 - 15s
(I saw many recommandations regarding this issue, to go and install Node v10 for example… Will try it out tonight)

Loading my biggest page (.ts file is approx. 450 lines)
v3 : ~2s
v4 : ~5s !!!

Add to this, overall performance feels more sluggish. For example, going from tab1 to tab2 has a small delay that feels a little slower than v3. Also, elements in the page that triggers navigation seems to take a little more time before triggering - ion-button or ion-fab-button don’t need tappable property, right ?

So, it was not hard to migrate but a real hassle, as it was expected - but I did it in good faith, thinking I would improve my app performances. Either I was wrong to think this, or there are some more things to do in order to obtain the desired result - in case it should be documented in the migrating guide ( I followed every step and every single point of the Breaking changes.)

Now, let’s ask some questions with some code !

app-routing.module.ts :

const routes: Routes = [
  { path: '', loadChildren: './tabs/tabs.module#TabsPageModule' },
  { path: 'home', loadChildren: './pages/home/home.module#HomePageModule' },
  { path: 'detail/:id', loadChildren: './pages/detail/detail.module#DetailPageModule' },
  .....
];
@NgModule({
  imports: [RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })],
  exports: [RouterModule]
})
export class AppRoutingModule {}

First things first, could PreloadAllModules be one of the problematic points ? In Ionic v3 I wasn’t using Lazy Loading much, only for a few pages, so I decided to follow recommandations when migrating and everything is lazy loaded now if I did things right - but I told myself, PreloadAllModules should be the right bet to get both faster boot time and still good performance when opening a page.

tabs.router.module.ts :

const routes: Routes = [
  {
    path: 'app',
    component: TabsPage,
    children: [
      {
        path: 'home',
        children: [ { path: '', loadChildren: '../pages/home/home.module#HomePageModule' } ]
      },
      {
        path: 'my-list',
        children: [ { path: '', loadChildren: '../pages/my-list/my-list.module#MyListPageModule' } ]
      },
      {
        path: 'actions',
        children: [ { path: '', loadChildren: '../pages/actions/actions.module#ActionsPageModule' } ]
      },
      {
        path: '',
        redirectTo: '/app/home',
        pathMatch: 'full'
      }
    ]
  },
  {
    path: '',
    redirectTo: '/app/home',
    pathMatch: 'full'
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class TabsPageRoutingModule {}

This routing is imported to be used used by TabsPageModule. I know what you could say - “you should add children to your tabs so the navigation stack works.”. The format is just like I want it - having main pages in tabs but when navigating to another page, falling back to the main router. It works… It’s just slow.

The rest of the app is mostly the same as it was in V3 - except I took a lot of time to migrate my scss to css4 variables, which in fact reduced my overall custom styles.

I would take any advice on how to test and check what is causing the app to slow down as well.

Thanks and good luck !

5 Likes

Could you try to boot my app on the same phone as you notice the 10s?

I personally saw an improvement with v4 but your metrics will confirm it or not, better speak about a test made on the same device.

Once we will have a metric I guess we would be able to have a deeper look, if the results are different, or ask our self where are the problem if both app are slow.

2-3 sec for v3 was really good, for me it was already a bit slow. but to be fair, that isn’t, in v4, an Ionic issue strictly. As Ionic now relies on the CLI of the vendor, in our case I guess Angular, if the live reload is slow it’s because the live reload of Angular v7 is slower than before.

And yes I also read that Nove v10 was improving it, couldn’t confirm as I’m up-to-date with Node since a long time.

I wrote a paper on how to lazy load a particular module and not all modules, don’t know if that could help but just in case: Preloading modules in Ionic v4. I’m currently migrating my mobile… | by David Dal Busco | Medium

2 Likes

Hey man, thanks for helping :slight_smile:

So, here is my report, sir !

First, I installed NodeJS v10, reload time improved to ~7s. That’s better - but still far from what I had with Ionic 3, or what I had in previous apps in, respectively, Ionic v1, Angular 2 and Angular 4. I know it’s mostly an angular question, but I wonder if there is something in Ionic apps structure that could have an impact on this matter.

I added tappable to every buttons, just to check… And surprisingly the app feels more responsive now, on par with my V3 app for most actions. That’s better.

About boot time now. Your app, on my phone, takes ~5s to boot - which is good enough ! I think trying to compile with --prod is the first step here, to see if it improves things drastically. Will try it when I have 2 minutes to rebuild it.

Now, remains the big question of my big page, which freezes the app for 5 seconds when loading - are Chrome dev tools enough to check what’s going on ? I would like to be able to compare this version with the previous one and see why it as gone from 2s loading icon to 5s freeze. I will try your article tonight, also.

Also, BTW, ionicons are completely out of the picture on my phone. I see them with serve but not after building the app. But I found several advices regarding this online that I still need to try before asking “OMG GUYS WTF IS GOING ON WITH ME :’(”

Have a nice day :slight_smile:

Cool, I think your last msg is relatively positive and encouraging, glad to hear you were able to make some progress!

Side note: yeah always test speed and boot using --prod, it’s a must

Keep me posted

Couldn’t wait so tried the --prod build and it does improve things tremendously. What is strange is, my V3 app is ~6-7s without it and ~5-6s with it, while my v4 app is ~6s with it and, as I said, ~10s without… Well, it’s good anyway, 6s is good enough also.

1 Like

There is probably still space for even more improvements but cool to know it’s already better :slight_smile:

Well, now that you dropped it, you will need to explain yourself, sir ! :stuck_out_tongue: What to look at in order to work towards more improvements ?

I used to maintain a feed about app boot time, I guess a lot things there are still actual: App boot time: current state and best practices

But summarized I would say:

  • always --prod
  • lazy loading
  • check your assets, smaller size the better
  • inclusive your fonts, if you ship fonts with your app
  • lazy load also third party libraries (in case you inject your own scripts in index.html)
  • check your dependencies, do you need all these libraries? for each library, check that only what needed is bundled (typical example: if you use moment, double check that only the i18n you need are contained in your app and not these of all the world)? check all your “import”, when you import do that import only what needed or the all lib? etc.
  • double check that your own code is executed with promises and observables, there there isn’t any blocker code and that you do the maximal work after the app is booted

just a couple of quick thoughts…

2 Likes

How to lazy load large 3rd party js libs - like three.js ?

never worked with that library so don’t know, sorry

I could also advice to use https://www.npmjs.com/package/source-map-explorer to have a look at the bundle, handy to find which library/code is big or not

Oookay, so. Sorted my issues with back button and with ionicons thanks to people here and on github :slight_smile:

On the important stuff, I used Chrome performance tab in dev tools to try and understand why this big page was taking so long to get there. Well, I have a couple of ion-select in that page, containing big lists (~200 options). Removing them from the page divides the needed time to open the page by 3, as well as the scripting time according to Chrome.

<ion-item no-padding>
  <ion-label position="floating">{{'ELEM' | translate}}</ion-label>
  <ion-select formControlName="elem">
	<ion-select-option *ngFor="let key of elemKeys" [value]="key.toUpperCase()">{{elem[key]}}</ion-select-option>
  </ion-select>
</ion-item>

So a couple questions arise :

  • Why does this slows down the page so much ?
  • Why it didn’t in Ionic v3 ?
  • What is the answer to the ultimate question of life, the universe, and everything ?

I also still need to try your techniques for lazy loading only select pages and improve boot time even more.

Honestly I don’t know. What you could try to do is to reproduce the problem in a starter blank app. If you face the problem there too I would then suggest to open an issue in the Ionic repo and to provide the starter project to reproduce the problem.

You could also have a try to that without ion-select respectively if you use only html tags, do you face the problem too?

1 Like

Welp it looks like there is a problem, but not a huge one, with ion-select. I tried three approaches.

  • ion-select has the poorest performance but the best UI for mobile, lacking a good UI for desktop though. With two ion-selects of about 250 elements, my page took 1.3s scripting time on desktop - much more on mobile, approx. 5s.
  • Regular html selects has the better performance but it’s still not that great, taking ~800ms scripting time on desktop. The UI is, obviously, very poor for a mobile experience.
  • input with a datalist has a nce UI for both platforms, is slighly slower than select but still significantly faster than ion-select about scripting time, but it fits poorly out of the box in an Ionic items list. It would need to be styled, which is not a problem. I think that it’s the best option in v4 for large lists.

What still puzzles me is that in v3, all of those were significantly faster. there is something wrong under the hood here.

About ionicons, it’s fixed for me. If it can help someone, look here : https://github.com/ionic-team/ionic/issues/17019#issuecomment-452828443 - also be sure tu npm install --save ionicons.

Still has a few things to explore but mostly I now achieved the same level of performance I had in v3. Knowing it will get better with time makes me feel I was right to take the leap, ultimately :slight_smile:

1 Like

Could you open an issue in the Ionic Github repo and provide your example and metrics? I think that would be helpful to improves the performance

I’m happy to hear that, to infinity and beyond :wink:

2 Likes

Maybe using virtual scroll will help? We have generally seen poor performance with long lists of anything even with v3, and using virtual scroll helps a lot in both v3 and v4.

The thing to check here is if your list is only slow to load, or is it also slow to scroll with all these items. Virtual scroll helped us with load speed, but even more with the list scroll performance.

Well, I’m not sure it would help here - we’re talking about ion-select which is in its own little modal. Also, it’s not a huge list - ~250 items is something pretty usual I think, basically a list of countries ! Also, only loading time - aka scripting time is slow, scrolling was smooth.

@reedrichards I will try to find a little time this week and put together a repo, yes !

1 Like

Hey @JerryBels! I noticed exactly the same behavior with the ion-select but I don’t have a solution yet. If you’ll find a solution please provide it here (I will do it as well). Thanks! :slight_smile:

Well, for me nothing worked for good, as I said the best was to use an input with datalist… For now I simply managed to show a loader when asking for this page and dismiss it when the process is finished. If I had to try something so it would work better, I would probably handle this with a modal, using a list with ion-searchbar - https://ionicframework.com/docs/api/searchbar/ - and returning the selected element. But I absolutely don’t have any more time to spare for it, right now :frowning:

So I’m working on other aspects of my project and will come back to it at the end, if nothing have been improved I will probably go for the modal solution.

Although I am unable to address the first two questions, I felt an answer for the last, What is the answer to the ultimate question of life, the universe, and everything, should still be provided for others to reference.

In short, the answer is 42. But the question is more complicated.

2 Likes