
Issue number: resolves #28534 --------- <!-- 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. --> Page views in Ionic need to be rendered as a child of `ion-router-outlet` in order for page transitions and swipe to go back to function correctly. However, Angular always inserts components as siblings of the insertion point. Previously, the insertion point was `ion-router-outlet` (the host element). This meant that page views were mounted as siblings of `ion-router-outlet`. We then added code to move the component inside of `ion-router-outlet`. This caused two issues: 1. A DOM tree mismatch during hydration (the linked issue) because hydration is expecting the page view to be a sibling of the router outlet, but Ionic moves the view around in the DOM. 2. A performance issue where all components effectively have `connectedCallback` fired twice. This callback runs when the component is added to the DOM. On initial mount, `connectedCallback` for each component runs. Once the page view is moved, the elements are removed from the DOM (thus causing `disconnectedCallback` to run), and then added to the correct location in the DOM which causes `connectedCallback` to run again. ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - IonRouterOutlet now renders a `ng-container`. This appears as a comment in the DOM inside of `ion-router-outlet`. This comment is used as the injection point for adding new views. The new views are added as siblings of the comment, but since the comment is inside of `ion-router-outlet` then the views themselves are inside of `ion-router-outlet` too. ## Does this introduce a breaking change? - [ ] Yes - [x] No This doesn't cause any known breaking changes. However, the placement of views is pretty critical to the functionality of Ionic, so I wanted to ship this in a major release so we have a solid public testing period before the code is considered stable. We already have test coverage that verifies page views are mounted in the correct order, so I did not add more tests for this. <!-- 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.6.2-dev.11704390532.1202188d Testing: 1. Clone and install dependencies for https://github.com/bashoogzaad/ionic-ssr-test 2. Run `npm run dev:ssr`. 3. Open app in a browser. Observe that error noted in https://github.com/ionic-team/ionic-framework/issues/28534#issue-1995002926 appears. 4. Install dev build. 5. Run `npm run dev:ssr`. Observe that the error noted in the original issue does not appear. Note: The Angular SSR package does not support Web Components. As a result, there are other errors you will encounter. However, I still think it's worth fixing this issue a) in the event that the Angular SSR package adds support for Web Components and b) to get the performance gain of not having to re-mount components.
@ionic/angular
Ionic Angular specific building blocks on top of @ionic/core components.
Related
License
Testing ng-add in ionic
- Pull the latest from
main
- Build ionic/angular:
npm run build
- Run
npm link
fromionic/angular/dist
directory - Create a blank angular project
ng new add-test
// Say yes to including the router, we need it
cd add-test
- To run schematics locally, we need the schematics-cli (once published, this will not be needed)
npm install @angular-devkit/schematics-cli
- Link
@ionic/angular
npm link @ionic/angular
- Run the local copy of the ng-add schematic
$ npx schematics @ionic/angular:ng-add
You'll now be able to add ionic components to a vanilla Angular app setup.
Project Structure
common
This is where logic that is shared between lazy loaded and standalone components live. For example, the lazy loaded IonPopover and standalone IonPopover components extend from a base IonPopover implementation that exists in this directory.
Note: This directory exposes internal APIs and is only accessed in the standalone
and src
submodules. Ionic developers should never import directly from @ionic/angular/common
. Instead, they should import from @ionic/angular
or @ionic/angular/standalone
.
standalone
This is where the standalone component implementations live. It was added as a separate entry point to avoid any lazy loaded logic from accidentally being pulled in to the final build. Having a separate directory allows the lazy loaded implementation to remain accessible from @ionic/angular
for backwards compatibility.
Ionic developers can access this by importing from @ionic/angular/standalone
.
src
This is where the lazy loaded component implementations live.
Ionic developers can access this by importing from @ionic/angular
.