apache / cordova-android

Apache Cordova Android
https://cordova.apache.org/
Apache License 2.0
3.59k stars 1.53k forks source link

Misc assets not displaying after device/dom load #877

Open jacksonkr opened 4 years ago

jacksonkr commented 4 years ago

Bug Report

Problem

When the app display (after the splash screen) sometimes default fonts are shown and static images aren't loaded. If you close the app an reopen, or if you can trigger a page refresh with the console, then all assets are present.

What is expected to happen?

All static assets such as fonts and images would be loaded on deviceready / domready.

What does actually happen?

see "problem"

Information

This is a react JS project using cordova

Command or Code

cordova build ios then run the app

Environment, Platform, Device

9.0.0 (cordova-lib@9.0.1)

Version information

$ cordova info
cordova-lib@9.0.1 with:
  cordova-common@3.2.0
  cordova-create@2.0.0
  cordova-fetch@2.0.1
  cordova-serve@3.0.0

Environment: 
  OS: darwin
  Node: v10.15.0
  npm: 6.12.0

Plugins:
  cordova-plugin-appcenter-analytics
  cordova-plugin-appcenter-crashes
  cordova-plugin-appcenter-push
  cordova-plugin-appcenter-shared
  cordova-plugin-compat
  cordova-plugin-device
  cordova-plugin-file
  cordova-plugin-file-transfer
  cordova-plugin-statusbar
  cordova-plugin-whitelist
  cordova-plugin-zip

...

"platforms": [
      "ios",
      "android"
    ]

Checklist

breautek commented 4 years ago

You've posted this in the cordova-android repository, but state that you use cordova build ios.

Does this actually occur on android or just iOS?

FYI, I have actually seen this issue on my iOS apps but it's a rare occurrence with no clear reproduction, but usually seems to happen after the app has been in the background for awhile. I've never seen the issue occur on android. My cordova projects is also using React web.

jacksonkr commented 4 years ago

@breautek Oh damn, thanks for pointing that out. I'm not positive it's happening on android but let me test that out real quick..

breautek commented 4 years ago

Let me know, I can just transfer the issue to cordova-ios.

jacksonkr commented 4 years ago

@breautek I got sidetracked - just tested and this happens on both android AND ios. My suspicion is that the assets in question are not required for DOM ready to fire. That said, the assets in question are part of the static assets that are uploaded to the device so they are theoretically available immediately.

Short of doing a manual refresh of the entire page (which is arguably poor UX) I'm not sure how to go about this one. Potentially checking each img and font reference to see if it exists after DOM ready and then triggering a redraw of that specific element if a local copy of it's particular asset is found.

Thoughts?

breautek commented 4 years ago

My suspicion is that the assets in question are not required for DOM ready to fire.

This actually is starting to sound like a different issue than I described earlier. Can you describe exactly what is happening?

The issue I mentioned I assumed it was coming from the experimental local webserver plugin as sometimes assets fails to "download" with an actual http error. My issue that I described had nothing to do with the DOM ready.

Also, there is no such thing as a DOM ready event, but I think you either mean deviceready or DOMContentLoaded events.

DOMContentLoaded fires when the DOM is finished parsing. static assets are loaded in parallel of DOM parsing, so they may or may not be loaded in when this event fires.

deviceready event fires when your cordova plugins are finished initializing. It to is completely independent of dom assets and may fire before they are downloaded/loaded in.

So both events don't care about assets, so you can't really use them to determine if the assets are ready.

Short of doing a manual refresh of the entire page (which is arguably poor UX) I'm not sure how to go about this one. Potentially checking each img and font reference to see if it exists after DOM ready and then triggering a redraw of that specific element if a local copy of it's particular asset is found.

This also doesn't really make much sense. If you had an image asset, it will automatically load once it's ready. Same things with css, or fonts, or any other asset.

jacksonkr commented 4 years ago

1) I used DOM ready a bit losely (from jquery days) but yes that would be equiv to DOMContentLoaded

2) For whatever reason the asset loading hangs severely. The only way I'm able to get everything to display is by clicking a link or something that refreshes the page (eg anchor link "#link")

It's really a bizarre issue. This happens on simulators as well as physical handset devices. Even from xcode .ipa builds that were sent to hockeyapp / appcenter.

Also I checked the safari web console when running into this on a device and there were NO warnings or errors in the logs.

What information can I post that would help track this pesky issue down?

jacksonkr commented 4 years ago

So this morning I'm using a different browser inspector and I'm seeing:

one-of-the-broken-images.png:1 Failed to load resource: net::ERR_FILE_NOT_FOUND

When you refresh the page (via console or link click) and the errors go away. If there's no simple solution to this I'll write a script for DOM ready to look at font & img references to trigger a reload on those.

EDIT

This works as expected in desktop chrome & safari but not on mobile chrome & safari (via webview)

EDIT 2

It's looking like this only happens with elements with background-image style rules. Using an img tag with a src attribute works fine. This needs to be a background-image because I need to leverage background-size: cover.

breautek commented 4 years ago

one-of-the-broken-images.png:1 Failed to load resource: net::ERR_FILE_NOT_FOUND

This is what I do see in my apps occasionally, only on iOS however. I have yet to see this issue on android. I assumed it was because I am using the experimental local webserver plugin, but I don't see that in your plugin list.

Using an img tag with a src attribute works fine.

This is also kind of consistent with what I've seen, because the only resources that this occurs on appears to be resources coming from css. For me it typically happens on font files.

What information can I post that would help track this pesky issue down?

I have tried debugging this in the past, it's been quite awhile now... but with no luck. My team kind of just threw it in the low priority pile of tickets since it only affected the fonts in our case, and the issue doesn't trigger often. So unfortunately this is an issue that also stumps me.

jacksonkr commented 4 years ago

@breautek I figured this was pretty low on the priority list.

I can verify on my end that it's happening to @font rules in css include background-image rules.

I'm going to create a hack fix for this and will report back so at least people have a work-around until it's properly (if ever) resolved.

breautek commented 4 years ago

to be clear, when I say my team I mean my company. Not affiliated with Apache/Cordova.

jacksonkr commented 4 years ago

My temporary hack:

    if (document.fonts.status === "loading") {
        document.fonts.ready.then(() => {
            const href = window.location.href;
            if (href.indexOf("cordova-fix") <= 0) {
                window.location.href = window.location.href + "#cordova-fix=1"
            }
        });
    }

Thanks to: https://stackoverflow.com/a/32292880/332578

tryhardest commented 4 years ago

@breautek may I ask what you use Local Webserver plugin for? Service workers or testing?

breautek commented 4 years ago

@breautek may I ask what you use Local Webserver plugin for? Service workers or testing?

In my apps, the local webserver plugin is primarily to get around CORS related issues that appears on wkwebview. There are lot of restrictions with CORS if the file loaded from the filesystem, but if they appear to be loaded from a webserver, those problems goes away.

Not exactly convinced that it's related to this issue because I believe @jacksonkr was having the issue without the local webserver plugin.