-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bug: Angular application (Zone.js) + cordova.js file #2896
Comments
Any thoughts on this ? |
Yes, for Cordova compatibility Capacitor generates a file at the top of In modern Angular apps, it appears zone.js is bundled into the |
It's also a problem with Angular and Cordova project, what I usually do is changing the import order (but I don't know if it's the correct thing to do to fix this kind of problem). I'm pretty sure I can reproduce the problem with an Ionic project too. |
We're experiencing a very similar issue in our app that we're in the middle of migrating from Cordova to Capacitor. My Ionic: Ionic CLI : 6.12.3 Capacitor: Capacitor CLI : 2.4.5 Utility: cordova-res : not installed System: NodeJS : v12.18.0 (/usr/local/bin/node) In certain cases it seems like Angular change detection is not running when it should. It's not an issue using Cordova or a Web deployment. Using the basic workaround in this blogpost (also effectively referenced in the OP) seems to fix the issue. My investigation so far corroborates the blogpost. Here's my working theory at this point: Ionic Angular with CordovaUsing Ionic Angular with Cordova the script load order is the following from the generated <body>
<app-root></app-root>
<script src="runtime.js" defer></script>
<script src="polyfills.js" defer></script>
<script src="styles.js" defer></script>
<script src="cordova.js" defer></script>
<script src="vendor.js" defer></script>
<script src="main.js" defer></script>
</body> Zone.js is present in Without any JavaScript patching,
Ionic Angular with CapacitorAs noted earlier in this thread, with Capacitor the content of Since the load order has changed, A similar issue that was a result of the Solutions?That As I mentioned above, the solution in the referenced blogpost worked for me while doing local debugging. Specifically, it's adding this code before window.addEventListener = function () {
EventTarget.prototype.addEventListener.apply(this, arguments);
};
window.removeEventListener = function () {
EventTarget.prototype.removeEventListener.apply(this, arguments);
};
document.addEventListener = function () {
EventTarget.prototype.addEventListener.apply(this, arguments);
};
document.removeEventListener = function () {
EventTarget.prototype.removeEventListener.apply(this, arguments);
}; My understanding is that this workaround makes it so that even when For the particular change detection problem I'm seeing in our app, I seemingly only needed the The challenge is having a way to get this code to run before While the particular change detection problem in our app can be "fixed" by adding the workaround after At this point I'm considering using https://www.npmjs.com/package/patch-package to add the workaround to
However, that means our app will work differently than almost all other Capacitor apps and who knows what issues could arise over time that are specific to our "fork." Also, we really don't want to maintain a package patch going forward. It would be awesome if the workaround was added to Capacitor or if there was a clean, first-party way to configure this. I know that'd take some time and would probably be a v3 item (we're on v2 right now), so hopefully I can come up with a way to work around the issue now and at some point be able to drop the workaround. If there's interest in a PR to implement the workaround I've shown above I will happily create one. Thank you so much! Kevin |
@KevinKelchen Did you find any safe workaround of the issue? On a first glance, adding the patch script in the solved my immediate problem, however, as pointed in your great overview above it may break cordova plugins in an unexpected ways as it is getting executed after cordova js. |
Hi Ventzy, 👋 Thank you for the kind remark! We went ahead with the patch as described in my message and have been running with it for the last 1.5 years in production in a non-trivial Angular app. We have not found any issues using the workaround thus far. 🤞 It'd of course be preferable for the change to be made to Capacitor itself. However, in the meantime and based on our experience, I'd hope that the workaround would be solid for you. Take care, and hope all goes well, Kevin |
Hello and happy new year! Chiming in from ionic-team/ionic-framework#26566 I've encountered a related problem. UPD: it breaks test = false;
constructor(private platform: Platform) {
// Platform.ready() promise will never resolve, thus:
this.platform.ready().then(() => {
console.log("Platform ready"); // This will never show up in logcat
this.test = true; // This will stay false
});
} Since our app broke from the start, we've decided stay with workarounds I've provided below. Just to be safe :) I also would like to provide safer, though requiring a bit of boilerplate, workarounds. I hope they will work for you as well. For additional info, see ionic-team/ionic-framework#26566 ProblemChanges in Example code: @HostListener("document:click")
onDocumentClick() {
this.documentClickCount++; // This field won't be updated in a template in an Android app
} NgZone.run() workaroundThis one is easier to use since you just need to wrap your code in it. constructor(private zone: NgZone) {}
@HostListener("document:click")
onDocumentClick() {
this.zone.run(() => this.documentClickCount++);
} ChangeDetectorRef workaroundThis one is faster than However, you'll need to call constructor(private changeDetectorRef: ChangeDetectorRef) {}
@HostListener("document:click")
onDocumentClick() {
this.documentClickCount++;
this.changeDetectorRef.detectChanges();
} |
I've run into this exact issue, and it has indirectly caused a hard to debug issue with firebase-js-sdk. After updating to Firebase v9, we had to use the After a bunch of debugging, it turns out the monkeypatch I added to fix issues with Angular
The above monkeypatch is problematic with Capacitor, as capacitor loads My FixI've updated my monkeypatch to include the same logic that is within Capacitor's <script>
window.addEventListener = function () {
(window.EventTarget || Window).prototype.addEventListener.apply(this, arguments);
};
window.removeEventListener = function () {
(window.EventTarget || Window).prototype.removeEventListener.apply(this, arguments);
};
document.addEventListener = function () {
// Duplicating functionality from Capacitor.js native-bridge.ts, otherwise when cordova.js calls addEventListener for 'deviceready' will not immediately fire if 'deviceready' has already emitted.
// Need to duplicate capacitor logic because capacitor injects native-bridge.ts code at the top of the head, so this function overwrites it.
// @see https://github.com/ionic-team/capacitor/blob/89cddcd6497034146e0938ce8c264e22e7baba52/core/native-bridge.ts#L152
const [eventName, handler] = arguments;
if (eventName === 'deviceready' && handler) {
Promise.resolve().then(handler);
}
// We don't care about back button error checks or default 'backbutton' action as we have @capacitor/app plugin installed, and set a listener within app.component.ts
(window.EventTarget || Document).prototype.addEventListener.apply(this, arguments);
};
document.removeEventListener = function () {
(window.EventTarget || Document).prototype.removeEventListener.apply(this, arguments);
};
</script> |
Bug Report
This issue can interest also https://github.com/ionic-team/ionic
Capacitor Version
Capacitor 1.x and 2.x
Affected Platform(s)
Current Behavior
Angular application (with or whithout Ionic Angular) is broken by the "cordova.js" injected in head scripts of
index.html
. This can create several problem as described in the following issue from the Angular repository.See: angular/angular#22509
In my case, when I'm in a several "router-oulet" deep and hit the back button, the previous child component will be created but not rendered correctly (no life cycle hooks are called like ngOnInit).
Expected Behavior
In my case, the previous child should be created and rendered correctly (life cycle hooks should be called).
Sample Code or Sample Application Repo
https://github.com/AlanRaz/capacitor-angular-issue
Reproduction Steps
npm i && npm run build && npx cap sync android && npx cap open android
Follow the navigation button (in green) then when you arrive to the step 2, just hit the back button (in red).
You can see that the component are no more rendered correctly and see in the console log that the constructor is called but the ngOnInit are not called.
Other Technical Details
This is also a problem with older Angular versions.
See: angular/angular#22509
Other Information
It took me a while to found this issue because I didn't know that Capacitor added the
cordova.js
at run time in the header of theindex.html
.What we use to do in old Cordova/Angular app to resolve this was to follow (https://github.com/angular/angular/blob/master/packages/zone.js/NON-STANDARD-APIS.md#others) and put the scripts in this order:
I don't know witch solutions will be good in termes of design and maintainability.
index.html
:But, I think it's really not explicit for the end-user.
cordova.js
.I don't know if this workaround can have side effect on other web libraries (or other libraries to have the same problem).
The text was updated successfully, but these errors were encountered: