Clarification on Ionic /components folder

My guess is no, although I believe they should. They’ve been operating under the belief that Angular modules are too complicated and the Ionic team doesn’t particularly like them. While there are some aspects of the way Angular handles nested routes and lazy loading that certainly are complicated, they at least help encapsulate features into reusable modules. And as long as Ionic uses Angular as it’s base, I think it needs to accept that as the way to use it. They’ve said they will support it, but I highly doubt they will make it the default behavior of their CLI, which is certainly their prerogative. I believe they are just targeting simpler apps and to them that means no modules, just some pages, components, and services. And I don’t think their completely wrong in that belief, it just isn’t what I use Ionic for.

3 Likes

I’m not thrilled with “eager” and “lazy” being a binary choice. What I initially expected out of all of this was:

  • N classes can be bundled together into a module
  • The build system defaults to N=1 and makes modules for each class
  • If the programmer wants, they can easily choose which to lump together
  • Any time DI or navigation goes to instantiate an object, it looks to see if its code is present (similar to how CPU executable code or VM/disk page caches work). If it’s there, we are ready to rock and roll. If it’s not, we load it and stick it in the cache for successive instantiations.
  • Code for each class only appears in one place in the app package.

In any event, as long as people are allowed to opt in and out of the lazy loading, that’s fine. All I can really say is that if people are concerned about binary size and performance, they need to thoroughly profile their app with and without lazy loading in order to make an informed decision. For some apps, it’s probably an improvement. For the one where I was investigating this, it was a pessimization that significantly increased code size without measurable benefit to startup time. It’s worth noting that (at least for me) the switch from Angular 2 to Angular 4 on its own made significant improvements on both fronts, so anybody who’s remembering the plethora of “my app takes forever to get off the splash screen” threads should first try sticking with eagerly loading everything as an initial benchmark.

2 Likes

woah…I’m gone for few days…

What seems to be the issue/Question/etc?

I’ve been curious about this as well. I noticed this issue you opened, and this comment from @danbucholtz that makes me fear moving forward at this point in time with LazyLoading in Ionic. https://github.com/driftyco/ionic/issues/10980#issuecomment-291971521

I’m glad to see that there is movement to support more flexibility in lazy loading, but my fear is encountering a major breaking change to make that happen, that will cost us a lot in development time down the road, since the IonicPage and DeepLinking API in v3 hasn’t been adopted by many users at this point.

We feel we adopted Ionic v2 too early, and it really bit us hard a few times in the last project we released.

While the current v3 release isn’t marked with a beta suffix, based on community feedback it seems IonicPage and DeepLinking may be in a beta-like state.

Just to chime in here,

Many of the concerns/issues we’ve seen would have to any framework that implements code splitting.
There’s a lot of popular libraries out there that have issues with being lazy loaded, like Moment.js.

I’ve been strongly suggesting people look at things like date-fns instead, as it’s easier to lazy-load and shake.

As for lazily loading groups of pages, like how the angular router does things, we’ll be adding support for that soon.

As for the comments of V3 noting being marked as “beta”, we made decision to not ship lazy-loading by default because the issues with third-party libs. For most users, lazy loading “just works”. While a limited/smaller example, my demo app work well with lazy loading and has a much faster start up time that previous releases.

Also note: we’re working on improving dead code removal right now so that we can make informed recommendations about lazy loading and best practices with regards to shared components.

I think a relatively common stumbling block is that the CLI page and component generators seem not to have gotten that memo. They spit out module.ts files (and at least in my environment, broken ones).

More of just a discussion of known issues and the best ways to work around them for now is all, in addition to opinions on folder/app stucture considering the future improvement to lazy loading. That was my take anyway :slight_smile:

1 Like

steps:

  1. generated component using: “ionic g component hello

  2. in hello.module.ts: modified “IonicModule.forChild(Hello)” to “IonicPageModule.forChild(Hello)

  3. in app.module.ts:
    import { HelloModule } from "../components/hello/hello.module";
    and added:
    HelloModule into @NgModule imports[]

  4. added: into ionic home page, got:

Failed to navigate: Template parse errors:
‘hello’ is not a known element:

  1. If ‘hello’ is an Angular component, then verify that it is part of this module.
  2. To allow any element add ‘NO_ERRORS_SCHEMA’ to the ‘@NgModule.schemas’ of this component. ("

Ionic Menu Starter

[ERROR ->]

"): ng:///HomeModule/HomePage.html@48:2

also tried to use components.module.ts to load custom components, all same error!

very frustrated, all my inoic2 custom components do not work in ionic3 after upgrade.

Please help!

Okay, because of some (known) issues with lazy loading, the only way to get your custom components up and running with lazy loading is adding the components.module as import to every page.module where you’re planning to decide to use one of the components. It delivers you some duplicate code so please bare that in mind. So: add your ComponentsModule to the imports of page(.module) where you want to use the component(s). Think that should do the trick.

Thank you luukschoen

I still cant sort it out, here is my components.module.ts:

import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { HelloModule } from './hello/hello.module';

@NgModule({
  declarations: [
  ],
  imports: [
    HelloModule,
  ],
  exports: [
  ]
})
export class ComponentsModule {}
and imports in app.module.ts:

import { ComponentsModule } from "../components/components.module"
.....
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp),
    AngularFireModule.initializeApp(firebaseConfig),
    ComponentsModule,
  ],

Same error that:
Uncaught (in promise): Error: Template parse errors: 'hello' is not a known element: 1. If 'hello' is an Angular component, then verify that it is part of this module. 2. To allow any element add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. 

I also tried NOT using lazy loading, and import and add into [declarations] like it used to work in ionic2, but it's not work anymore in ionic3....

I’m wasnt talking about loading the ComponentsModule into your app.module, but I was talking about importing your ComponentsModule into yourSpecificPage.module file. So, put it into the imports of your yourSpcificPage.module.ts :slight_smile:

You forgot to export whatever the Hello component is called out of ComponentsModule.

Can you please explain this a little bit more? Cant I have a module created with two components imported?

You can, but every page that imports it will get a separate duplicated copy of the code for both those components.

Thought i’d show you what we are doing for the time being, albeit, we do NOT know if this is the correct approach:

We created a ./components directory in our ./src directory.

In it we have all of our custom components like this one for example:

./src/components/my-custom-component/
my-custom-component.html
my-custom-component.scss
my-custom-component.ts
my-custom-component.module // which is implemented like this:

import { NgModule } from '@angular/core';
import { MyCustomComponent } from './my-custom-component';

@NgModule({
  declarations: [
    MyCustomComponent,
  ],
  exports: [
    MyCustomComponent
  ]
})
export class MyCustomComponentModule {}

NOTE: we create all our custom components in this way but we do NOT import any of our component modules in our app.module. Instead, we only import a component module in the pages where they are needed like so:

./pages/my-page/
my-page.html
my-page.scss
my-page.ts
my-page.module // in it we import a component module like this:

import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { MyCustomComponentModule } from '../../components/my-custom-component/my-custom-component.module';
import {MyPage } from './my-page';

@NgModule({
  declarations: [
    MyPage,
  ],
  imports: [
    MyCustomComponentModule,
    IonicPageModule.forChild(MyPage),
  ],
  exports: [
    // MyCustomComponentModule, // UPDATE: exporting the component module here is not necessary
    MyPage
  ]
})
export class MyPageModule {}

And then in the template my-page.html …

<my-custom-component></my-custom-component>

We have tested this and it works … Can anyone confirm this implementation is OK?

Issue with this seems to be when you want to use the same component in multiple modules - it will ask you to create a shared module.

For more details take a look at: 'ion-icon' is not a known element

As far as I can see, the final post in the thread you linked is the definitive answer.

Hi there,

Is there a definitive, documented way, in order to create a custom component in IONIC 3, and add it to a LazyLoaded page?

Seems like there is no definitive answer, and it’s an obscure subject.

Thanks,

Autoreply::

Check this out, it works (both methods) are correct:

**

Ionic and Lazy Loading Pt 2

**

http://blog.ionic.io/ionic-and-lazy-loading-pt-2/

NOTE: IonicModule and IonicPageModule are completely unrelated things with totally different function.