ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
51.08k stars 13.51k forks source link

bug: build breaks Ionic components #28756

Closed sander-spruit closed 10 months ago

sander-spruit commented 10 months ago

Prerequisites

Ionic Framework Version

v7.x

Current Behavior

Developed an angular/ionic application which serves properly and works. However, once build no errors are reported and the build succeed. However, in practice the build does not work and Ionic components are lacking functionality. No console errors are showing.

Example of incorrect output;

Schermafbeelding 2023-12-21 204846

Expected Behavior

Ionic should load properly. Example of what page should look like.

Schermafbeelding 2023-12-21 204939

Steps to Reproduce

  1. Create a new angular project, could be i.e. the tabs demo
  2. Add an Ionic element to that page i.e. a ion-input.
  3. Build the project with ion build --prod
  4. Upload the project to a random web server

Code Reproduction URL

http://bit.ly/3NDCCqD (Edit from Sean: https://admin.spruit.events/#/tabs/tab1, never trust a bit.ly link)

Link is based on reproduction steps, not screenshot

Ionic Info

Ionic:

Ionic CLI : 7.1.5 (C:\Users\SanderAkkermans\AppData\Roaming\npm\node_modules\@ionic\cli) Ionic Framework : @ionic/angular 7.6.2 @angular-devkit/build-angular : 17.0.7 @angular-devkit/schematics : 17.0.7 @angular/cli : 17.0.7 @ionic/angular-toolkit : 9.0.0

Capacitor:

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

Utility:

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

System:

NodeJS : v20.10.0 (C:\Program Files\nodejs\node.exe) npm : 10.2.3 OS : Windows 10

Additional Information

Dependencies used;

    "@angular/animations": "^17.0.2",
    "@angular/common": "^17.0.2",
    "@angular/compiler": "^17.0.2",
    "@angular/core": "^17.0.2",
    "@angular/forms": "^17.0.2",
    "@angular/platform-browser": "^17.0.2",
    "@angular/platform-browser-dynamic": "^17.0.2",
    "@angular/router": "^17.0.2",
    "@capacitor/app": "5.0.6",
    "@capacitor/core": "5.5.1",
    "@capacitor/haptics": "5.0.6",
    "@capacitor/keyboard": "5.0.6",
    "@capacitor/status-bar": "5.0.6",
    "@ionic/angular": "^7.6.2",
    "@ngx-translate/core": "^15.0.0",
    "@ngx-translate/http-loader": "^8.0.0",
    "ionicons": "^7.2.1",
    "moment": "^2.29.4",
    "ngx-quill": "^24.0.4",
    "rxjs": "~7.8.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.14.2"
liamdebeasi commented 10 months ago

How are you importing your components? It looks like the ion-input component is not being registered in the sample you provided. This makes me think that your application is importing from both @ionic/angular/standalone and @ionic/angular which developers should not do (since it causes issues like this).

sander-spruit commented 10 months ago

That did it (although I looked into it endlessly.

Switching

import { IonicModule } from '@ionic/angular';

@Component({
  imports: [ExploreContainerComponent, IonicModule],
})

to

import { IonInput, IonHeader, IonToolbar, IonTitle, IonContent } from '@ionic/angular/standalone';

@Component({
  imports: [ExploreContainerComponent, IonInput, IonHeader, IonToolbar, IonTitle, IonContent],
})

fixes it.

Why does this not show any error reporting? And why does it work with serving?

liamdebeasi commented 10 months ago

There is no treeshaking/dead code elimination when serving, so IonInput was likely being defined as a result of a side effect. Once you build for production, Webpack will do treeshaking and see that you aren't actually importing IonInput anywhere in your application and remove that code from your build.

There isn't a great way to automatically detect this when mixing imports between @ionic/angular and @ionic/angular/standalone because they are two different build systems of Ionic. As a result, we recommend developers only import from one or the other. If you are using VSCode you can add the following setting to prevent it from suggesting @ionic/angular imports: https://github.com/ionic-team/starters/blob/main/angular-standalone/base/.vscode/settings.json. I believe you can do something similar for JetBrains products too.

I am going to close this since the issue is resolved, but let me know if you have other questions.

bennyvenassi commented 10 months ago

Hey there, is this really the only solution to Import every component by its own instead of the IonicModule? While using a lot components this isn't really pretty. e.g. my imports for a simple Page: import { IonInput, IonHeader, IonToolbar, IonTitle, IonContent, IonLabel, IonGrid, IonCard, IonSpinner, IonRow, IonCol, IonCardTitle, IonCardContent, IonText, IonItem, IonButton } from '@ionic/angular/standalone';

imports: [CommonModule, FormsModule, ReactiveFormsModule, IonInput, IonHeader, IonToolbar, IonTitle, IonContent, IonLabel, IonGrid, IonCard, IonSpinner, IonRow, IonCol, IonCardTitle, IonCardContent, IonText, IonItem, IonButton]

liamdebeasi commented 10 months ago

Yes, this is the recommended solution. You can optionally define import groups to import related components to help cut down on the number of separate imports:

import-group.ts

import { IonCard, IonCardContent, IonCardTitle } from '@ionic/angular/standalone';
export const CARD_COMPONENTS = [IonCard, IonCardContent, IonCardTitle];

home.component.ts

import { CARD_COMPONENTS } from '../import-group.ts';

...

imports: [...CARD_COMPONENTS]
ionitron-bot[bot] commented 9 months ago

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.