Why does simple website crash on mobile (iOS Safari and Chrome, at least)? - ios

I have a website that is very simple, but very long -- a lot of text that could be scrolled through. It's a documentation site, and considering the nature of the content (a lot of short similar entries) I decided to show everything at once, so the user could either scroll from entry to entry or navigate via a sidebar index. It's a common documentation model that I like (e.g. Underscore, Backbone, and LoDash).
The site is here: http://davidtheclark.github.io/scut/. You could look at the pre-production code here: https://github.com/davidtheclark/scut/tree/master/docs/dev.
And here's the problem: For a number of users this site consistently crashes their iOS browsers. Not all users (not me); but for those that do experience the crash, it seems to recur consistently. (The site may also crash some people's Android phones, I don't know: haven't heard from any Android users.) I am hoping someone can help me diagnose and possibly fix this problem.
Part of the difficulty I have is that I cannot reproduce the crash myself -- not on my own iOS devices, not on the Xcode simulators. Because the site is not at all resource-heavy (~70KB load) and involves very little JavaScript, and because of the effects of a few prior attempts to fix this, I'm guessing that the problem involves memory usage -- that iOS browsers are crashing because the site is demanding too much memory. But I'm not sure that's the issue, and if it is I'm not sure how I can fix it.
I'm not sure what to try next, and I'm hoping some savvy StackOverflow whizzes have advice. What is it about this site, which seems so simple and basic to my eyes, that is making it so memory-demanding that it is crashing browsers?
Is it just too long? Is there CSS that is too difficult to render? Are there JavaScript memory leaks?
I'm interested both for the sake of this particular site and so that I can learn to anticipate-and-prevent and/or diagnose-and-fix similar problems on other sites in the future.
Feel free to look at or contribute to [the Github issue](in this Github issue, as well.
Addendum
Here are some things to know about the site that might be relevant:
The HTML doc is large relative to other sites' HTML docs. Unminified it looks to be ~225KB. (I notice that LoDash docs are even bigger -- does that site crash people's phones?)
The served HTML doc is minified.
Served CSS and JS are also minified.
The site uses Prism.js for syntax highlighting.
The site uses Overthrow to make the 2-scrolling-columns layout work on tablets.
<aside id="help-content"> is fixed and translated off-screen; it slides in when you click a [?] like the one by any utility's "use-name".
An iOS Crash Log
These look to me to be the potentially relevant lines of a crash report from an iPhone running Chrome and crashing on the site (I'm not sure whether they are actually relevant or not because I haven't developed iOS apps and don't know the ins-and-outs of these reports):
Free pages: 5674
Active pages: 117674
Inactive pages: 55121
Speculative pages: 3429
Throttled pages: 0
Purgeable pages: 0
Wired pages: 60906
File-backed pages: 23821
Anonymous pages: 152403
Compressions: 356216
Decompressions: 121241
Compressor Size: 16403
Uncompressed Pages in Compressor: 49228
Largest process: Chrome
[...]
Chrome <2a759438c2253e3baededaa0d13feb56> 166479 166479 200 [per-process-limit] (frontmost) (resume)

I think I fixed it!
The problem, as suspected, was rendering/painting caused by CSS layout. At phone-size, I had been hiding the content of each entry until it was selected; and the method I had been using to hide them, and remove any trace of them from the layout, included position: absolute. I didn't initially use display: none because of typical concerns about wanting to not see content but keep it there, for various readers and reasons. I threw those concerns aside and changed the layout so that the entries were hidden with display: none and shown with display: block -- and that seems to have fixed the crashing.
I think the absolute positioning was stacking a huge amount of content in the corner of the screen, and although it wasn't visible, it was demanding memory.
What clued me in to trying this was an answer to another related question, linked to above by #tea_totaler: https://stackoverflow.com/a/14866503/2284669. It says:
What tends to help me a lot is to keep anything that is not visible at this time under display: none. This might sound primitive but actually does the trick. It's a simple way to tell the renderer of the browser that you don't need this element at this time and therefore releases memory. This allows you to create mile long vertical scrollers with all sorts of 3d effects as long as you hide elements that you are not using at this time.
I think that my other hiding method was not releasing memory, despite its other advantages (which were possibly irrelevant to this particular site anyway). I'm sure it became a problem only because the site was so long.
That's something to consider, though, when you want to hide an element: rendering/memory demands.

On my site it was caused by elements with the css property -webkit-backface-visibility: hidden
removing this property fixed all crashes!
see iOS: Multiple divs with -webkit-backface-visibility:hidden crash browser when zooming

I ran an audit with Chrome on the site. It suggested this:
Remove unused CSS rules (44)
44 rules (10%) of CSS not used by the current page.
css-built.min.css: 10% is not used by the current page.
audio, canvas, video
audio:not([controls])
[hidden]
abbr[title]
dfn
hr
mark
q
sub, sup
sup
sub
svg:not(:root)
figure
fieldset
legend
button[disabled], html input[disabled]
input[type=checkbox], input[type=radio]
input[type=search]
input[type=search]::-webkit-search-cancel-button, input[type=search]::-webkit-search-decoration
textarea
table
.older-docs
.older-docs>li
.older-docs>li:not(:last-child):after
*, :before, :after
fieldset
textarea
:not(pre)>code[class*=language-], pre[class*=language-]
:not(pre)>code[class*=language-]
.namespace
.token.regex, .token.important
.token.important
.older-docs
.changelog dt
.changelog>dt
.changelog>dt:after
.changelog>dd
.changelog-i-list
:target>.entry-body
.sub--h
.example--css.is-active
.preload .help-content-c
.help-content-c.is-active
.help-content.is-active
The task manager on Chrome shows that the page takes up about 2x as much total memory than other sites, such as stackoverflow and dropbox. I would recommend dividing up the features into separate pages instead of one long page. By separating the features it would improve the server's efficiency and the browser's load time and memory usage. There would be less JavaScript and CSS running on each page and smaller amounts of data would be sent from the server. Having all the features on the home page is inefficient. For example, if a user only needed to look up how to make a Font Icon Label they would have to load other sections of the page that are not needed and take up memory.

Sorry for just making a guesses but I see two potential causes in your stylesheet which could be resulting in crash
1.) Using data-url for background image rendering such as here
.github,.source {
background-image: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%22100%22%20height%3D%22100%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M85.714%2050q0%2014.007-8.175%2025.195t-21.122%2015.485q-1.507.279-2.204-.391t-.698-1.674v-11.775q0-5.413-2.902-7.924%203.181-.335%205.72-1.004t5.246-2.176%204.52-3.711%202.958-5.859%201.144-8.398q0-6.752-4.408-11.496%202.065-5.078-.446-11.384-1.563-.502-4.52.614t-5.134%202.455l-2.121%201.339q-5.19-1.451-10.714-1.451t-10.714%201.451q-.893-.614-2.372-1.507t-4.66-2.148-4.799-.753q-2.455%206.306-.391%2011.384-4.408%204.743-4.408%2011.496%200%204.743%201.144%208.371t2.93%205.859%204.492%203.739%205.246%202.176%205.72%201.004q-2.232%202.009-2.734%205.748-1.172.558-2.511.837t-3.181.279-3.655-1.2-3.097-3.488q-1.06-1.786-2.706-2.902t-2.762-1.339l-1.116-.167q-1.172%200-1.618.251t-.279.642.502.781.725.67l.391.279q1.228.558%202.427%202.121t1.758%202.846l.558%201.283q.725%202.121%202.455%203.432t3.739%201.674%203.878.391%203.097-.195l1.283-.223q0%202.121.028%204.967t.028%203.013q0%201.004-.725%201.674t-2.232.391q-12.946-4.297-21.122-15.485t-8.175-25.195q0-11.663%205.748-21.512t15.597-15.597%2021.512-5.748%2021.512%205.748%2015.597%2015.597%205.748%2021.512z%22%2F%3E%3C%2Fsvg%3E");
background-repeat: no-repeat;
}
2.) Also -webkit-transition could be the culprit. Read here for more https://stackoverflow.com/a/11833285/900132

Your HTML markup has some errors (such as a div tag inside an h1 tag) that should be fixed before you try to analyze a crash.
I suggest you run it through an HTML validator, for example http://validator.w3.org/check?uri=http%3A%2F%2Fdavidtheclark.github.io%2Fscut%2F&charset=%28detect+automatically%29&doctype=Inline&group=0
The div inside h1 apparently caused a cascade of errors that the validator had to suppress to continue.
When I have browser crashing problems, HTML validation is always my first step. Then I try seeing what might be wrong with the javascript if correcting the HTML didn't help.

I just read this post and tried http://davidtheclark.github.io/scut/ on my iPad. Chrome crashes immediately, although sometimes shortly shows the home page. Safari renders the home page correct and many other pages, but clicking on the "about > installation" link at the left makes it crash right away (well, once it displayed OK, but clicking again crashed it). All of this is pretty consistent.
The errors are indeed due to LowMemory and it's the browser process that uses the most memory. The crashes happen at around 150000 pages (4KB/page? => 600MB???).
That being said, I'm afraid I don't have an answer to your question. Hope it helps at least a little bit.
Kind regards,
/Sigiswald

Removing position: sticky; helped me and my mobile safari crashing issues. Not sure exactly why.
body:before{
position:-webkit-sticky;
position:sticky;
}

In my case the crashing was caused by using CSS filter: blur(2px) to create a colored "glow" effect.
I fixed it by creating the glow in photoshop and using a PNG file to render the glow on my website.
This not only fixed the crash but created a nicer, more even glow that also didn't re-render in strange ways when zooming and scrolling.

Related

Why is this page loading so slowly as an iframe, but normal when visited directly?

I have a set of iPads (3rd gen) running iOS 9.3.5. This is the highest they support. I am attempting to replace the functionality of a custom iOS app with an equivalent web application. The site is built in Angular 11, targeting es2015, and I've declared iOS > 9 in the browser support file. The majority of the site performs exactly as I would expect for such old devices. The linchpin of the whole thing is this third party form that needs to be filled out that is served up as an iframe, and it performs so, so horribly.
Here is the code of component HTML with the iframe (URL changed for privacy):
<div class="row header"><a class="restart" (click)='restart()'>Start Over</a><a routerLink='/welcome'><i class="fa fa-times close-x"></i></a></div>
<iframe src="https://notarealsite.com" (load)="waiverLoaded()"></iframe>
The waiverLoaded function is a simple boolean flip to detect the embedded page reloading upon completion so that I can route to a different component in my app. The performance is unchanged if the iframe is the only element on the page. Other pages that play nice when embedded do not suffer a performance drop like the waiver does, so I have to assume it's something in the code of the waiver page.
The original custom iOS app uses a webviewer to load the page, and it loads in 2 seconds or less. The same performance can be seen by visiting the page directly in Safari. In both instances the responsiveness of the dynamic form is reasonable given the age of the devices. When loading the page via an iframe the performance tanks. We're talking 30-45 seconds of loading, and sometimes up to a full second delay between tapping a button or field, and the form reacting.
I have attached the device to my computer and used the remote inspector in the MacOS Safari to view the timeline. The majority of the initial load time is the several 1-2 kb image files used by the form like the scroll bar and some icons. Usually one of these items ends up taking 20-25 seconds all for themselves. When interacting with the form there's an XML resource that appears in the timeline every field change or button press, and that is what takes around a second or two before the page is up to date again.
I'm not well versed in troubleshooting web application performance like this, and this is my first real Angular application that I've built, so I might be missing something painfully obvious. What can contribute to such a difference in performance between a page being visited directly, vs being placed in an iframe?
Some additional info:
The performance is the same between running locally via npm serve or built and deployed to my local server.
I have tried hosting it via HTTP and HTTPS in case it was some security hangup, as the form is only delivered via HTTPS. However I only have a self-signed cert at the moment.
I have seen no discernable difference in load times between the two methods on my other devices, including an iPad Air running iOS 12.5.2.
There is a warning in the console about jQuery support on iOS 9.3.5 being outdated, but it occurs in both scenarios.
Additional Troubleshooting
I've tried to look into some of the suggestions I've received. I've checked the timings and headers on the slow loading elements in Safari in the following configurations:
In the iframe on my app on the iPad.
Visited directly on the iPad.
In the iframe on my app on my MacBook Pro.
Visited directly on my MacBook Pro.
On my laptop the performance is nearly identical. Comparatively, on the iPad the actual load times of all the elements is within a millisecond or two of their times on my laptop. What ends up being notably different is the latency between request and response for the elements.
The latency when visiting directly is higher than on my laptop. When loading through the iframe all the timings increase fairly proportionally. A time of 750ms jumps to 4s. A time of 6s jumps to 30s.
Lastly, a real oddity to me, is the super high latency image for some reason results in a 302 to Cloudflare, but only on the iPad. It doesn't matter if it's through the iframe or direct. Both devices are using the same WiFi network. I can't think of a reason for the redirect to happen unless the destination site is handling the iPad differently somehow. Changing the UserAgent in Safari on my laptop to match the iPad doesn't result in the same redirect.
So I've confirmed that even outside of the iframe the site in question behaves differently on iOS 9.3.5 than on newer versions, and compared to my computers.
Please post your code for us to diagnose and help. In general there is more overhead for an IFrame my suspicion is the jQuery handler or cookie policy, to be sage I also listed other items to check.
It looks like you already checked the previous unsecured elements which was an issue. Both in the network graph and the calls, double check there are no dependencies or URL calls of the Iframe of unsecured elements then it wont display, it used make multiple round trips if Https had mixed content between secure and non-secure stuff, there's a ticket for A new TLS issue.
Once you fix that ensuring its hosted/called securely, clear the cache, cookies, data completely and reloading the page fixes the problem even on mobile browsers.
Redirects/Bouncing Your order of loading scripts/css, if there are dependent scripts and they are not cached it could be blocking, or if its redirecting back to HTTP this will also slow it down.
For IOS mobile apps only (doesn't apply here) - if you are using the 3rd gen, check the default for Cookie Security policy (HTTPCookieAcceptPolicy) for UIWebView has changed to NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain
Animations Are slow in safari Iframes
You have the click event in your code, could be the issue
..."Turns out that any non-anchor element assigned a click handler in jQuery must either have an onClick attribute (can be empty like below):"...
Put the following element declaration cursor:pointer or tap event

Getting strange Capybara issues

So I'm using capybara to test my backbone app. The app uses jquery animations to do slide transitions.
So I have been getting all kinds of weird issues. Stuff like element not found ( even when using the waiting finders and disabling the jquery animations ) I switched from the chrome driver back to Firefox and it fixed some of the issues. My current issues include:
Sometimes it doesn't find elements if the browser window is not maximized even though they return true for .visible? if I inspect w pry. (this is a fixed with slide w no responsive stuff )
and the following error:
Failure/Error: click_link "Continue"
Selenium::WebDriver::Error::StaleElementReferenceError:
Element not found in the cache - perhaps the page has changed since it was looked up
Basically, my questions are:
what am I doing wrong to trigger these issues.
can you tell me what if I have any other glaring issues in my code?
and when using a waiting Finder, do I need to chain my click to the returned element to ensure it has waited correctly or can I just find the element and call the click on another line:
Do I have to chain like this
page.find('#myDiv a').click_link('continue')
Or does this work?
page.find('h1').should have_content('Im some headline')
click_link('continue')
Here is my code: http://pastebin.com/z94m0ir5
I've also seen issues with off-screen elements not being found. I'm not sure exactly what causes this, but it might be related to the overflow CSS property of the container. We've tried to work around this by ensuring that windows are opened at full size on our CI server, or in some cases scrolling elements into view by executing JavaScript. This seems to be a Selenium limitation: https://code.google.com/p/selenium/issues/detail?id=4241
It's hard to say exactly what's going wrong, but I'm suspicious of the use of sleep statements and a lot of use of evaluate_script/execute_script. These are often bad signs. With the waiting finder and assertion methods in Capybara, sleeps shouldn't be necessary (you may need to set longer wait times for some actions). JavaScript execution, other than being a poor simulation of how the user interacts with the page, don't wait at all, and when you use jQuery, actions on selectors that don't match anything will silently fail, so that could result in the state of the page not being correct.
You do not have to chain. Waiting methods in Capybara are all synchronous.

jQuery Mobile freezes while scrolling

While scrolling my jQuery Mobile enabled site on a mobile device (at least iPhone 4 and 5), it almost always freezes for a few seconds, sometimes significantly longer. Usually it eventually just crashes and I have to kill Safari (or Chrome) from memory.
I'm having trouble identifying the cause. I know they state there are issues with transitions, and I tried adding .ui-page { -webkit-backface-visibility: hidden }, but it didn't help.
I'm guessing it might have to do with one or more scripts that are running. My scripts file essentially contains a set of scripts that run for both desktop and mobile, and two more sets that run exclusively for desktops and mobiles respectively. The common set is wrapped in a conditional ready function, $(document).ready for desktop and $(document).on('pageinit) for mobiles.
Also, based on the device, all the scripts are either loaded in the footer for desktops and the head for mobiles. However, the main scripts file is loaded in the footer for both. The scripts wouldn't work on mobiles otherwise.
Not sure if iOS preventing DOM manipulation on scroll is conflicting with something.
I would just link the site, but professional confidentiality and all that.
I'm not asking you to just guess what the cause may be, but I would really appreciate an outline of some fundamental principles of developing with jQuery Mobile to optimize performance.
According to the documentation (navigate to "scrollstart"), it is expected that DOM manipulation is frozen during scroll in iOS devices, even in iOS 7.

JavaFX embeded browser memory leak

I am using embedded browser in JavaFX. On my webpage, using Javascript, I dynamically create lots of checkboxes + some other components and remove them from the DOM afterwards. What is strange, after performing every "create/remove" cycle the memory usage is growing. Maybe it could be related to the click events attached to my elements? It seems like a memory leak, I have no idea how could I fix this. In regular browser like Chrome everything works fine.
I don't have much experience with finding memory leaks but I've been meaning to use Plumbr to test my JavaFX app for those - maybe you can use that?
You might have to sit there and keep clicking on stuff or script lots of interaction for Plumbr to notice the leak, since it seems to be focused on JSP apps which have a lot of simultaneous users.

MODX Revo: How can make pages load fast?

I'm working on a site with modx revo. I'm really annoyed by the slow loading op pages. There's a 2sec wait for a page load om my localhost ánd I have a SSD. I've been looking around to find out how to make pageload faster.
I do have alot of getResources-/Gallery (9 total) calls and two Wayfinder calls. I've read it had to to with those, so I got rid of all the getResources and changed them to customs snippets that do only what I need them to do, build a 3-4 item menu. It's still slow, only few hunderd ms slower.
The Galleries (5) are only 3-4 images. I also use babel that checks every resource id for it's translation counterpart.
I'm wondering if it has anything to do with my wampserver (v 2.2) settings...
Now that I've summed it all up, I does look like a heavy page. Will I get long pageloads with any CMS this way?
Any help/hint/tips are apreciated!
You might want to "cache" all snippet tags without using the exclamation mark [[! ... ]].
Here is a blog about caching guidelines: http://www.markhamstra.com/modx-blog/2011/10/caching-guidelines-for-modx-revolution/
Here is a current discussion about speed performance: http://forums.modx.com/thread?thread=74902#dis-post-415390

Resources