iOS Safari Web Crashes & Fixes Part 1
This week I was tasked with figuring out why certain pages on our site crash on iOS Safari on iPad OS 7.1+. The page I started on was a product listing page. This was a very large page with hundreds of products being rendered. I was pretty sure this was due to the device using up all it's available memory and crashing. So using an app called "Airwatch Agent" I was able to monitor the current amount of free memory. As I was using the site I would continuously flip back to this app and get a current read on the amount of memory available. There's got to be a better way to do this using Xcode instruments or something but this got the job done. Using this method I could watch the memory quickly go down to 0 and the browser would crash.
My first step in debugging this issue was to add in some breakpoints and narrow down exactly what javascript is executed just before the crash. The browser was crashing when 180 products were being added to the DOM in a product list page. My thought was that one of the following was happening:
- The process of mixing our massive data object with our handlebars template was consuming all the memory. The result was an string of HTML roughly 360,000 characters long.
this.template(this.model);
- The process of adding this giant string of HTML to the DOM was causing the browser to crash.
this.$el.html(myGiantStringOfHTML);
- Something with the CSS styles applied to this HTML was causing the crash.
It's easy to distinguish the first two as I can use breakpoints to separate these two pieces being executed. But for the last two it's a little more difficult.
First, I decided to break up the templating & DOM manipulation into chunks of 25 products separated by an alert. My thought was that if it didn't try to create this 1 massive string and dump it into the DOM all at once it wouldn't use up all the memory. And the alert allowed me to throttle how fast or slow it went as well as alert out how many items it was up to. This failed. After 130 products and 140 products the browser crashed on the iPad AIR and the iPad Mini 2 respectively. This left me scratching my head. At this point it had to be the CSS. Right?
Second, What I did was go in and rip out everything in my template to stop the crashing and then start adding HTML back block-by-block until the crash started happening again. I anticipated that it would begin crashing as soon as the product images were added back into the template. 180 images would take up a lot of memory right? I was wrong. I didn't get too far into adding HTML back before it started crashing. And it was the HTML below I was looking at.
`
<div class="product-container>
At this point it had to be CSS. Since the "product-inner-container" was the last thing I added when it started crashing again I focused on the CSS that targeted that item. Here was the CSS:
.product-inner-container { -webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; -ms-backface-visibility: hidden; -o-backface-visibility: hidden; backface-visibility: hidden; height: 320px; overflow: hidden; padding-top: 16px; position: relative; width: 100%; }
The "backface-visibilty" property looked fishy. I knew this property relates to 3D transforms and since we weren't doing any 3D transforms on these elements I started with ripping this out. The crashing stopped! I then reverted all of my javascript and other CSS changes back leaving only the removal of the "backface-visiblity" and sure enough the crashing was fixed.