Media • iOS, OS X • 57:07
Dig deeper into the many enhancements and new features that Safari has added to Web Inspector. Learn how to use them for more advanced inspection, tweaking, profiling, and debugging of your web content on iOS and the Mac. If web technologies are at the core of your web, Mac, or iOS app, this session will show you how Web Inspector can help you get the results you want.
Speakers: Andres Garza, Brian Kadar, Antoine Quint
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript has potential transcription errors. We are working on an improved version.
Well, hello again. For those who have been here in the previous session, this is the second session of our two-part Web Inspectors extravaganza today. My name is Antoine, I'm an engineer on the Safari and WebKit teams and I work specifically on Web Inspector. And so, for those who have been here in the previous session, this is a more advanced session but we will cover some ground that you may have seen from the previous session. We'll try to reduce to overlap so don't worry, but make sure that even if some of the content seems familiar, we always going to go in much greater detail than what we've seen on the previous session.
So Web Inspector is the Safari developer tool. It's the one stop shop for you to inspect, tweak, analyze, and debug any problem you may have with your web page. And it's a tool that runs on the Mac as part of Safari and surely enough, you can use it to inspect pages and Safari on your Mac. But we've set it up so that with remote web inspection, you can always inspect content running on your iOS device and iOS Safari, or even your own app that you wrote for iOS that uses UIWebView.
And the first thing I'd like to do is to go through some of the changes we've made into the user interface across last year. And to get a sense of our progress, let's turn back to a year ago when on this stage my colleague team Hatcher introduced Web Inspector for Safari 6.
And remember that at the time, the banner feature Web Inspector was that for the first time, we added support for remote web inspection. And what that meant is that you could finally inspect your content loading-- loaded, sorry, on iOS devices. That was really a massive breakthrough. And we thought that while doing this would probably gather a whole set of new users that will be a lot more used to Xcode, you know, people that develop app on iOS are using Xcode. So we took the cue of the design lead of Xcode 4 to change the complete appearance of web inspector in Safari 6.
So, that is Web Inspector looked up until Safari 7 is coming out, and we heard a lot of feedback about this user interface. More specifically, we heard that the organization of icons to-- on the left sidebars and on the right sidebars was a little bit confusing and that they were also a little bit small and lacked a little bit of color. It wasn't just super easy to learn about the interface if you weren't already familiar with Xcode or Web Inspector. So we took that comments-- those comments to heart and we worked hard to improve the user interface of Web Inspector in Safari 7.
And so, I'd like to walk you through one major change that we've made and those changes were made to the tool bar. And the tool bar is completely new in Safari 7. And the first thing you'll notice is that to control the display of your navigation sidebars to the left with those three icons, resources, timelines, and debugger. Console is a different panel that we'll go back to later. And these are icons that you can control, you can fully customize them, they're nice and big and have a label by default.
We can turn the labels up, put them to the side, make the icon smaller, and you can fully customize the tool bar to your hearts content. And you can just do that like you would in any other Mac app by just come and click on the tool bar and customize it. It's really simple. OK. Let's move on to the activity to your another brand new thing as part of the tool bar. I've already talked about this in the previous session but let me refresh you memory or introduce it to people who may not have been here.
To the left, you have the first two items, we'll give you information about your resources on your page, the number of resources and the aggregate size for all those resources put together. And these are not just informational. You can just click on those and jump straight to the resources sidebar and start digging into them to find out more details.
Likewise, you can track the low time of your page, the time up to the load events in a rolling counter from the page below to the time the load even fired and click on that to jump to the timeline and find out more about your network load time.
And finally, to the right, we have three icons devoted to the console. You can try plugs, errors, and warnings, and this obviously would take you to the console by clicking on them, and what's even cooler is that since we added filtering support to the console in Safari 7 and Web Inspector, clicking on either of those items will take you to the console and filter the content to match where you just clicked on. So for example if you click on a warning, you'll see only warnings in the console. If you click an error, you'll see only errors. And of course you can filter back to all messages from the console very easily.
And the last item to the right is something that is actually specific to when you're inspecting Safari on the Mac because it's controlling the docking mode of Web Inspector. Web Inspector can run in a stand-alone window like this or it can be docked to the bottom of your page. We've always supported this. But something we heard a lot of feature request for is the addition of a mode where the inspector is docked to the side of the page. So this is something new in Safari 7. You ask for it and you've got it.
So, now let's move on to or the real meat of our presentation. And I wanted to show you a lot of new features. And to do that, I'll ask two colleagues of mine to come up-- come up on stage and show you some great demos, really compelling. They will put a lot of our new features at work in three tasks. And if you've been here before, you'll be familiar with those tasks.
The first one would be inspection tweaking then we'll go and take a look at the performance of our page and analyze it. In this case, it will be layout and rendering specific and we'll finish with some JavaScript debugging. And again, this sounds like the outline of the previous session because we think these are core tasks for you as developers but the content in this session is completely different and we'll be looking at different features. So let's start by taking a look at inspection tweaking. And to me, inspection tweaking is about experimenting with the content of my page. It's about experimenting with the DOM structure, the HTML, but I think most importantly, it's about interacting with the styles.
And the style is really, to me, the bread and butter of Web Inspector. It's usually the first thing I want to do with Web Inspector is tweak the appearance of my page and make sure it's pixel perfect, matches the design I want to achieve, and it's really kind of the stable feature of Web Inspector.
But that didn't let us rest on our laurels and we want to make sure that we had the best experience possible for styles editing and we have a completely refreshed styles sidebar in Web Inspector in Safari 7. So, we still support things that we've always supporting. We still has syntax highlighting, we still have great auto completion where we know exactly what counts the CSS properties supported by WebKit since Web Inspector talks directly to WebKit. We got some awesome great new features.
The first thing, and you'll see that in great details in the demos, is that you can just start clicking anywhere where you see CSS code and just start typing. And as you type, you have auto completion, syntax highlighting, and it just behaves just like you would expect a great text editor to behave except now you're in Web Inspector. It's just a series of many text editors one for each rule. It's just so awesome.
And another thing that we found was commonly used but not as accessible as it should be from the user interface of our previous version is the ability to add a new rule. So we've made that a lot easier. There's a big button in the style sidebar, you can't miss it, and what it-- and we've also made it better such that when you press that button, it will look at the currently selected element and it will try to generate a CSS selector for the new rule that is as specific as it can. So for example, if your element as an idea on it, we'll generate a rule for that specific idea. It's really, really useful.
And finally, at the top of the styles sidebar, we added a way for you to force some pseudo-classes to be applied to our element. And one that I think is tremendously useful is being able to turn on the hover pseudo-class which is something that if you wanted to tweak the hover style of your element, you'd probably have to go back through the page, roll over the element in question, and then see what it does and then go back into the inspector changes, roll over back and so forth. It's just not very convenient. We've made that a lot better. And again, we'll see that in demo right away.
Another thing that I think is really cool about styles in CSS and Web Inspector is that we've made it so that style that may look great in Web Inspector was actually something that came through looking horrible before. And the way we make it look good is that we support pretty printing and this littler button at the right and it's a button you may not even have to use in practice because we automatically identify when we download minified CSS content like this so that we can display it in a much nicer way like that. And so, to walk you through some of those great new features, I'd like to invite on stage my colleague Brian who will give you a great demo of advanced styling and experimentation in a web page.
[ Applause ]
Thank you Antoine. Check, check. Good. So I'm actually really excited to show you these demos today because Antoine spends the entire day working at web content, allow these features go along with my job a lot easier. So to show you, let's pop up in demos that we've been working on. As you can see, it's a very simple photo gallery. I have pictures of me and my very close, very great looking friends.
And as I look at this side, there's a few things that I think I can improve on that I didn't think about when I was actually building and it in my text editor. Friends and I think of that. This header sits up to top as I scroll through the page.
And also this feels very static. I mean that there is a cool little hover effect as I now search of these thumbnails. So, let's focus first on the header. So to get started let's open up the Web Inspector and it causes the event session. We're going to use the keyboard command, Command-Option-I.
So this should look familiar to you. Now the first thing I'm going to do as I reminded you was I want to fix the header. So let's zoom in here into the DOM sheet mode and let's use the arrow keys to drill down into the document and get our header. But go over to the right, you'll notice that we have some preexisting styles associated with the header. But I want to add a new one.
So let's zoom in closer and see how we can use the styles detail bar. Now because it says a free-form CSS editor, I can click anywhere, press Enter and start typing. So because you want to just stick to the top, we're going to adjust the position property. So let's start.
You'll notice the autocomplete format. Now, instead of guessing what the value is because this has WebKit under a hood, I can press Escape and so bring up all the options available to me. So, I can go through it when I want. And in this case, you want to use WebKit sticky.
But there's something you might have missed. So I'm going to press command Z to undo this and I'm going to zoom out. I want to scroll down to the middle of the page so that the header is invisible. And now, watch what happens when I click Escape again.
[ Pause ]
There you go. So as soon I press Escape, it's going to immediately apply the-- immediately apply the change of value to the DOM. So I can move through all these options and quickly see how each of this property is going to fit the layout. So this is the a lot better than going back and forth reaching your editor. So I can nearly get in-- I can get immediate feedback on what the changes going to look like. So in this case, I want to use WebKit sticky, press Enter to create the change and we're done.
Something else, I want to fix is I also have a footer at the bottom of the page. Now, I want the footer to have the same style as the header, so let's go back into our style detail bar. And you notice that I have shared style which is in my header and footer below.
So I'm going to go ahead and cut this because I can do this since it's free-form, click anywhere, paste it in, and let's zoom out and take a look. So now we had the footer stick into the bottom of the page and the headers stick on to the top. So it's looking much better already.
The second thing I want to do is I want to have a nice hover effect when I roll over one of the images. So to do that, let's flat one of the images. And I want to inspect the image element that's on the page. So to do that, I can right click on the image element and choose the inspect element option.
You'll see this fit in directly into that note in the content view. Now, if we go over to the right, we'll see we have some associate styles to this image. Now, when tweaking styles, I like using detail bar. But I like writing new styles directly in the CSS file. And I can get that easily in Web Inspector by clicking on this link to the right.
And this is going to be directly to the area in the style sheet that I actually find that style. So now I can go ahead and then I can start adding to this. So just like one of text editor, I can start typing, just add a hover effect for the image, and notice as I type is going to autocomplete and also syntax highlight for me. So for this, let's add a little zoom animation.
So, I added WebKit transform, we're going to do scale, and let's make it three for 300 percent. So as you roll over the images to the left we can see that. Let's go over there. We can see that it's starting to work. But this is a little, a little jumpy. So let's go back to our style sheet and add a transition. And notice the autocomplete as well and let's do it for WebKit transform. Let's take it 1.5 seconds and let's make it nice and smooth ease in our curve.
So you notice that as I roll over this, I get immediate feedback on the changes that I made directly in the style sheet resources. But I think this could be tweaked a little more and it's really hard for me to go back and forth between the style sheet and then rolling over.
I want a better way to build with a subtly and finest this animation. So, let's go back to the viewer where before we're able to see the style details. To do that, I'm going to use the navigation bar on the top here to go back. And as you can see it brought us to area where I work previously.
So now what I can do is I could use a new hover pseudo-class on the top. And you notice that when I click on this, the animation is going to be applied to the image that I select. So I can click on and off to see the effect but even better I can now see the hover styles that I added in my resource directly in the detail sidebar.
So now I can go ahead and tweak this through where I want it. So let's make it a little faster, maybe a quarter of a second, and also, just the scale. So let's go back, that's a little too big, a little too small to, more point to, that looks just right. Let's click off and take a look.
So it's looking a lot better already. Now, one thing I want to point out to you is that the changes that I made to the CSS in the sidebar are going to be reflected in the source code. So let's click through back to our CSS file and notice that these new properties, the quarter of a second and the scale, all reflected in the CSS file.
So, this is looking pretty good, but what do we do now? How do we save this? Typically, we have to go back to our editor, copy the changes that we made, and then start over. But now in Safari 7, I can simply press Command S, save the file up to my disk. And to show you that it works, I'm going to refresh the page. You can see that all things I made have now been saved and I'm ready to continue. And viola, there you go. And speaking of viola, back to Antoine.
[ Applause ]
Thanks Brian. So let's recap what Brian just showed us on the stage. Using the new styles sidebar easier than ever to make any changes you want to your page. We have the great new free-form CSS editing, syntax highlighting, all of this instant, any change you made just gets reflected on you page, and that's just really amazing I think. And adding the neurals just easier than ever with this big Neural button.
And what I think is extremely compelling especially in a kind of demo like this when we want to tune the transition and the transformer applied to an element when it's hovered, we can just control that so much easier in a much easier manner by just using the hover checkbox in the pseudo-class bar at the top of the styles sidebar.
I think of a future that might seem just so natural now that you see it but if you didn't have it, it would just be so much more painful is your ability to just save files that you've been editing locally so that it get taken into account when you reload, and more importantly, they just apply directly and you can just, you know, those change are done, you do it all in Web Inspector.
And so, by just pressing Command S, you can save your file and it's just save right where it was or it can even save a copy somewhere else if you prefer. So I think that really is a good summary of what Web Inspector lets you do in terms of CSS experimentation, inspection and tweaking. So now let's move on to the next section, performance analysis.
And we're going to focus on layout and rendering. And I think the greatest leap forward ever made in a browser for performance in terms of layout and rendering was something that WebKit pioneered as soon as early as iOS 2 in the former hardware compositing and the ability to have composited layers in your document.
So, let me take a step back for a minute. Let's get out of the floor representation and let's discuss briefly what composited layers are. You may not be familiar with them. Composite layers is a way for your document instead of being a flat surface in terms of rendering to be a collection of smaller layers stacked on top of one another and composited in a very efficient way both in performance and power consumption by the GPU.
And so, let's take for example a simple video player. Imagine that a backdrop image here is a live video and we have controls that we want to customize on top of our video. So, to make sure that video playback is a smooth and power-efficient as possible in Safari, both on the Mac and on iOS, we're making video elements in WebKit always be hardware accelerated and hosted in a composited layer.
So our video is playing and it's kind of on its own space above the rest of the web page. Now, let's imagine that you hover over the video and you want the controls to appear. So you're probably state a great little WebKit transition on them and make sure they start appearing on top of the video. So, as soon as something is animated with opacity or transform, WebKit will automatically create a composited layer for you so that we have the best possible performance as the animation is performed.
But in the end results of that video control hovering the-- being laid out over the video, it means that we have to create a layer for that control as well. Obviously, if you have something displayed in a layer, in this case are video, and something else drawn on top of it, that piece of content laid out over the video will itself need a layer.
And what's kind of cool about layer is not just-- it's not just about animations and transforms. It's also that when we have a smaller logical piece of content to render in this layer for example or controls up here, if we have to make a change that requires a redraw, for example pressing the button, it might turns to button green or something, then we can make those changes in a much small region and make a much more efficient redraw cycle in WebKit.
And so, I'm telling you a lot of information here and it might seem a little bit more little abstract. But there was a great session on this topic last year. It's called Optimizing Web Content in UIWebViews and Websites on iOS, I really urge you to look at that session. It has so much detail information about how layout and rendering happens in WebKit. Section 601, WWDC 2012, you can just watch it from the iOS app as soon as you exit this room. OK, so let's go back to our presentation.
Composited layers, like I said, they're created and managed automatically by WebKit. It's a great optimization made by WebKit and it was such a breakthrough. I don't even think of other browsers are quite caught up with this. And they pose their own kinds of challenges as for you as a web developer. Who think things in layers are not for free? In fact, almost anytime you gain something in performance is always an associated cost often times in memory. And layers will be the same. Something it gets drawn into a layer requires memory to match the content of that layer.
So how do you find out when-- having things in layers might be a problem? Well, this is almost impossible up to now. We have a brand new sidebar in Safari 7 called the layer sidebar and it provides you all the detail information you need about layers in your document.
So let's take a look at what information is contained here. At the top, we have any information for a layer associated to the currently selected element in the DOM. So, of course, you may not have a layer for this element and in that case that panel will be empty at the top, that's fine.
And your elements might have a lot of layers associated to descendants-- descendant nodes of that element. So, we can just list all the layers associated to any element in that selected element subtree right there in the style sidebar panel. And that gives you a great overview of what actually ends up being in layers.
And for each of those things you can track the number of time those layers are painted and the associated memory for that layer. And what's really cool is that since we display this information in the table, you can sort by memory use or by paints and keep track of the things that might be painting or using too much memory in real-time as this list gets updated as you interact with the web page. And we summarize the layer count as well as the memory at the bottom of the panel. So you can just take a look at that number and see exactly how much memory is consumed by layers on your web page or in that specific subtree you're selecting.
OK, so, layers are-- can be associated to all kinds of different content. The most obvious one may be an HTML element, to which maybe a CSS transform is applied. But there are other kinds of content in your web page that you can't even see in the DOM that might still create a layer.
And one of those things are pseudo-classes. And you might have used before ::after or ::before or first letter first line, those types of things. And what this lets you do purely in CSS is actually something that we call generated content. And for example, I love to use an after rule such that I can add and overlay over an image that might be semi-transparent when the mouse is not on the element and removes itself when the mouse is over.
So I can create interesting effect without having to change the DOM structure. But imagine that this content and that after selector is actually composited itself. Well, that creates a layer. And you can identify it very easily by looking for any layer that has a P icon next to it. P stands for pseudo-class.
And what about reflections? Well, reflections themselves do not require a layer to be generated. But imagine you're implying a reflection to a video. A video is always hosting a layer. So, in order to provide a reflection for that video, we need to create a layer for that reflection. And again, those things live completely outside the DOM. And if it weren't for the layer sidebar panel, there would be no way for you to find out about those layers and diagnose any issue laid to them.
So what about jumping from a layer to the actual element that this layer is associated with? Well, we did something that's just very intuitive. You can just hover over the layer in the sidebar and a little Go To arrow will pop up, you'll see them all over the place in Web Inspector to jump to the associated content and clicking on it will take you to that element and regulate in the DOM. And then you can maybe change the stuff for the element or do whatever you want that may change this behavior, use less memory, or what have you.
And the final thing that I think is just incredible is that, like I said,, WebKit has its own set of reasons and it does the best it can to generate layers when they're needed is not something you have control over directly is just a great optimization by WebKit .
But the reason why something might be composited can be very obscure. But what's great about this sidebar panel is that if you select one of those layers, it will show you right away why we composited that layer in WebKit. So for example, here are fairly obscure reason that have probably would not have worked out by myself.
The layer associated to that element, well, the element overlaps another element that's being composited in a layer. And so, just like I explained in the overview, because it's laid out over another element that's in a layer, it needs to be in its own layer. How could I found that out if-- without that sidebar panel? Well, this is exactly what the layer sidebar is for. And so to find out more about the layer sidebar and more about diagnosing and fixing issues related to performance of layout and rendering, I'd like to invite on stage Andreas to give us a great demo.
[ Applause ]
Thank you Antoine. I'm going to ahead and reopen the photo gallery that Brian was just showing us. And here we go. So thanks to the latest enhancements Brian has made. This is really starting to come together. But we got to remember this is a website. So not only it's going to be viewed on different screen sizes like an iPhone or an iPad but in case of the desktop, a user might even choose to resize the window. So for that and in order to have a great user experience, we want to had and build this photo gallery using a responsive layout. So let's take a look at that.
As you'll notice, as I resized the window, the layout does in fact adjust to the new screen size. But in terms of performance, things are not looking really good. Things are laggy and in fact, I wouldn't say this is a responsive layout. So let's go ahead and try to fix that. But instead of me trying to get what's wrong with that, I'm going to go ahead and open the inspector. I'm going to go and jump right into the timelines view.
For those of you who are not familiar with timelines, they allow you to record any activity that's going on while you're interacting or loading your website. These include stuff like network requests, layout and rendering, and JavaScript events. So let's go ahead and start recording a new timeline by clicking on this button right here.
Now that we're recording, let's switch back to our photo gallery and resize the window. So notice, immediately as I start interacting with my website, the time is updated with any activity that was recorded. Let's go ahead. I can continue interacting with this page but I think I got enough data for now. So let's go ahead and stop recording.
Again, using the same button I use to start, I'm going to go ahead and hide the timeline side panel so we get a little bit more room here. And you immediately notice on the top part of this view, we get a graphical timeline and really easy to quickly visualize everything that was going on.
In the bottom part, we get additional details of all of the events that were recorded for-- while we are-- of all the events that are recorded. These include stuff like start time, duration, and in case your event was triggered by your JavaScript code, you even get the function name, the line number, and if I hover over one of this, we even get the entire call stack that led to this event being trigger. Isn't this really cool?
[ Applause ]
So, let's go ahead and take a look at the different types of events was going on. And something that immediately pops out to me is that the single function, this called layout photos, that seems to be trigging most of these events. When I see some stuff like layout here, some style going on against some layout, but let's go ahead and focus on what's going on with styles.
And to do this, I'm going to go ahead and at the top of this table, we got these awesome controls here that allow us to filter the data in this table. So I'm going to ahead and select invalidate styles. While holding the command key, I'm also going to click on Recalculate Styles. So as you can see, the table immediately updated to just show me those two types of events.
So again, let's browse through data and we can immediately detect a pattern here. And it seems that the layout photos is constantly invalidating styles and recalculating styles. And this seems to be happening over and over again. And as I mention before, we can even see the exact line number that this is happening on. In this case, it seems that line 58 is triggering the recalculation, and line 64 is triggering the invalidation. So let's go ahead and click on the layout photo right here to jump right into the code. And here we go, let me zoom in.
So you'll notice, line 58, let's go ahead, and it seems that I'm inquiring an offsetWidth. So this is clearly what's triggering the recalculation. And if we jump back to line 64, if you remember correctly, in here we're setting a style. So when we set a style, the browser has to go ahead and invalidate any cache styles.
So if you look closely, all of this is happening inside of for loop. So the next time I go into this for loop and hit this offsetWidth, the browser is going to have to, again, recalculate the side. So clearly, this is what we were seeing in that-- in the timelines where over and over we're calculating styles and invalidation styles.
But before I go ahead and make any changes, wouldn't it be great if we had a concrete measurement that could tell me how long this function is taking to execute? That way, when we do make changes, we can have an actual metric to validate whether those changes improve things or made things worse. So let's go ahead. And I'm going to use a really handy Console API I use all the time. And what I'm going to do is I'm going to type console time at the beginning of the function.
I'm going to put a console timeEnd at the end of the function. As you might have guess, what these APIs do is they measure the time between the two calls and print that out to a console. But something you might have notice is I didn't have to go back to my text editor, find the corresponding file, find this layout photo function and edit my code there. I did all of this directly from the web inspector.
And just like with CSS files when working up the local file system, not only can I edit the files in line but I can go ahead and Command S and save the file back to my file system. I think this is a really awesome feature. So let's go ahead and save our file. And I know I'm going to print some to the console so let's go ahead and switch to the console using the keyword Shortcut Option Command C, that's the way in here, and let's go ahead and reload that page using Command R.
As you'll notice, we immediately get that timing function so we can see that the layouts photos is taking around 210 milliseconds to execute. This might not seem like a lot to some people but we got to remember we should always try to minimize our JavaScript execution time. And in fact, I'm pretty confident we can bring this number down. And let's go back and jump to our code, and to do this I'm going to use the navigation bars up here.
[ Inaudible ]
Let me use a console. So here we're back to our code and let's go ahead and analyze what's going on. If you remember, we're querying the offsetWidth and if you look closely, we're using the offsetWidth to determine how many photos we can put fair well. And base on that, we go ahead and determine the photo width and the height. But if you look closely, we're not relying on any photo's data to do these calculations. In fact, these are pretty static calculations that can just go ahead and move out of the for loop. So I'm going to just do that.
And by doing this, we're no longer going to recalculate style on every loop. So let's go ahead and save this, again, Command S, reload our page. But before I do that, switch back to the console again, zoom in, and let's reload our page. And there you have it.
That minor change actually made a huge improvement, not only that we make that optimization but we have a concrete data that can help us validate this. So we went from 200 milliseconds to just under 10 milliseconds. So that's good. But let's go back to the resizing, but that's what we're trying to solve here.
I'm going to zoom out a little bit, let's go to the Inspector for now. And I'm going to resize the window and see what happens. As you'll notice, things might be a little bit better but they're still not [inaudible]. So let's go ahead and see what other optimizations we can make.
And as you know, we're working with a lot of images here, when we're doing some CSS transforms. And in fact, to do all the layouts of the photos, we're using CSS transforms as well. So I'm a little bit concern about in terms of memory and in case the browser might be creating in the layers. So I'm going to go ahead and make use of a brand new feature in Safari 7 that allows me to quickly visualize all of the layers in my page. To do this, let me bring up the Inspector again.
And let's switch over to the Resources tab. And in the DOM tree, there's a brand new button in the upper right corner. But instead of me explaining what it does, let me zoom out and show you exactly. So I'm going to toggle it and I know it's a little bit hard to see so let me zoom in.
What this does, it actually drag borders around all of the layers within your page. So this is a really cool way that you can quickly visualize all of the layers within your document. In this case, if you look closely, it seems that we're generating, there are being layers composited for each photos. This is sort of unexpected. At least it wasn't my intention, sorry.
So, before I go ahead and make any changes, I think it would be great if we can go and analyze how many layers we have and why the things are being composited. So for that, I'm going to go ahead and open up the layer side panel, this brand new layer side panel over here. And we can immediately see the list of all of the layers for this document. And as expected, we can see all the photo wrappers are being composited. We go all the way to the bottom.
We can even see then the exact layer kind of layers. In this case we have Nighty and they're consuming a total of 11 megabytes. This might not seem like a lot but we got to remember that in mobile devices, memory is restricted. So we should always try to memorize-- minimize our memory footprint. So, now that we've seen how many layers we have, let's go ahead and see exactly why layers are being composited for each photo. So to do that, I'm going to go ahead and select one of the photo wrappers here.
You immediately see that the reason this is being composited is because the element has a 3D transform. So now that I know why this is, let's go back to our photo gallery. And as I mentioned before, we think 3D transforms or transforms to position all of these photos because we have a feature of the photo gallery that we haven't shown you yet. So you might have noticed that in the upper right corner, we have a shuffle button. And instead of me explaining what it does, let's go ahead and click it and see, see them in action.
As you'll notice, as I click this button, the layout of the photos is rearranged and they are animated to their new position. So this is why we're using CSS transforms. But you'll notice we're not doing anything fancy. I don't know what's going on with the performance here but we're not doing anything pretty of anything fancy. So I think it's safe to go ahead and remove that 3D transformation and convert them to just use 2D transforms.
So I wrote this code and I know exactly what file need to change. So I'm going to go ahead in the Resources, Open photo.js, and here we go. This is the line of code that's setting up that 3D transform, so I'm going to go ahead and convert this to a regular translate. And again, I'm editing right in the Web Inspector so Command S to save, save this file, and let's reload the page.
And you'll notice something you can immediately see is that there are no longer borders being drawn around each photo. So this means we did something. And layers are no longer being composited for each photo. But just to be absolutely sure, let's reopen this layer side panel once again.
And sure enough as expected, we went down from, I think it was 90 layers to just two layers and let's see how that deal with memory. And we went down from, I think, it was 13 megabytes to just 300 kilobytes. So this is great. But before I go and see how that affected the resizing, let's make sure we didn't break any system functionality.
Let's go ahead and try to shuffle again and make sure that's still running as smooth as before. So I'm going to click on it, and you'll notice that things are still looking pretty good. And I know it's a little bit fast here, but if you notice closely, as an animation is happening, WebKit is smart enough to composite layers for all of these elements so that animation still runs as smooth as before. So this is good.
So, let's go ahead and resize the page and hopefully this would fix our performance stages. So I'm going to go ahead and resize the page. Notice, things are immediately better. In fact, I would say that this is now in fact a responsive layout. So with that, I'm going to hand it back to Antoine. Thank you.
[ Applause ]
Thanks Andreas. I think this is the coolest demo we've made today because it puts together so many of the new features we've had in Web Inspector and let's us do things that would be virtually impossible to make with any other tool. Web Inspector is the only tool that let's you check performance-related issues that might be originated due to the use of layers.
So let's recap what we just saw. The great new layer sidebar something completely in Safari 7 let's us inspect at a glance list of layers we have and we can even use the new composited borders button in the navigation bar to turn on borders on any composited element in the page.
And only to drill into more information, the layer sidebar which lets us find out about the number of panes or the memory used and even find out why specific layer was composited in the first place, such that if it were in unexpected behavior, we could go about fixing it using the style sidebar.
And in this demo, Andreas managed to bring the tool number of layers from 90 to just two layers just suing those great techniques. And Andreas also showcased some great improvements we've made to the timelines panel. Recording all this information about layout and rendering, it might be a lot, so the first thing you can do is filter down to just the types of layout and rendering operations that are of concern to you.
And then as you select a specific row in that DataGrid, you immediately can figure out what kind of JavaScript code led to the execution of that layout. So for example here, we know that it came from the AppInit and we can just start drilling down through those functions to figure out why we eventually call it layout photos. Such a great feature. You can just jump straight to where the performance issue might be.
I think since we're in the advance session and I'm talking to a group of developers, I think everybody are going to be interested in ways you can boost your productivity while using Web Inspector. And a great way to do that is to learn more about a Console API. Andreas used a console time and console.timeEnd methods to time a code segment. This is really cool.
There are other methods you can call on console that could make your life easier when dealing with performance analysis. For example, console that mark timeline. What it lets you do is add a green vertical dash line to the timeline recording so that you can visually see when your piece of code is being run.
Another great thing we could have done in this demo but we didn't is that instead of calling time and timeEnd, we're going to call it profile and profileEnd. And what this would have done is start an instrumentation process where it keep track of all the JavaScript calls made during that specific interaction and present it in a great DataGrid within the timeline sidebar. We didn't have time to feature profiling too much in this session this year, but if you come to the lab, we'll be able to show you a lot more about profiling if you're interested.
OK. So I think that we did a good job of showing how we can deal with performance analysis and fix those kinds of performance-related issues in Web Inspector in this section. Now let's wrap this up by taking a look at debugging in Web Inspector. I'm going to invite on the stage, again, Brian, to show you the final demo.
[ Pause ]
Thank you, Antoine. So, Andreas did a really awesome job showing you how you can use a timeline to help profile of [inaudible] in performance and layout associated with their JavaScript code. But sometime, their JavaScript code just doesn't work, at least mine quite often. So, let's take a look at the previous example we're working at.
This is looking pretty good so far but one feature I want to add is that when you click on a photo, it just zoom in full screen like a nice photo gallery should. And I went ahead and I added some code to do this but it doesn't work. And you'll notice that when I click on the photos, nothing happens.
So usually when something goes wrong, the first thing I do is I blame Antoine. The second thing I do is I open up Web Inspector and take a look and see if there's any information to tell me that something has gone wrong. So let's do just that. Now you'll notice in the top right, in the top of the activity there is a pretty obvious glaring red error. And this tells me that indeed something is going-- gone wrong. And as I click on a photo, it'll increment that count.
[ Inaudible ]
So as I click on a photo, it's going to increment that number. So that tells me that there's obviously a problem with the Java that's being called as a result of clicking on a photo. So let's zoom out and let's-- and we already have console open. I can also get to that by clicking on the red icon.
And if I zoom in here, you'll notice that we have an error and it's telling me that we're trying to call an undefined function. So let's go straight into the code and take a look at what's going on. I do that by clicking a link on the bottom right.
I'm going to zoom out a little bit and take a look. So, let's take a look at code here and see if we can get an idea of just looking at the code what's trying to happen here. So clearly we add eventless near to the element before you click on it, and in the function handler, we're trying to call a method that notifies that a photo was selected. But this doesn't give me a lot of information so let's set turn out the debugger which you can get too by toggling on the top here.
And let's set term breakpoints on and let's do it for all uncaught exceptions. Now, if you had exceptions that were at in a try/catch statements, you would also be able to use the all-exceptions. So without reloading the page, I'm first going to press command K to clear this error count. I'm going to click on another image.
And as you can see, the debugger braked right at the area where we expected. So now that the debugger stopped at the point where the error is being thrown, we have the opportunity to look at the context and see what's happening here. So when you look at the top right, we have a scope chain which provides information about the variables and arguments in the method. But nothing looks obviously wrong here. There's no neular undefined. So, I can't really get a sense about what the problem is. So let's close this. Safari 7 is a much better way to go about doing this.
I can simply roll over-- I can simply roll over any element here. And I'm going to get information, let me zoom out of it. I can get information about any variable here live. This is a really great way to visualize the code and walk through it and see what kind of information we're getting and see where the error happens. So as you can see, this is the event that triggered the function. I can roll over the idea and see that we're going to get the correct idea of the photo. This is the information about the photo.
But as we expect, the notify method is undefined. So let's keep it going through the left here and roll over this. And we zoom out and we see that this keyword represents the element. So, this is a very subtle JavaScript [inaudible] that I ran into all the time. And we know that a function is called-- an event list in our function is called in a context of the object that triggered the event. So in this case, this keyword refers to the element that we clicked on, not the object that contains the method.
So let's go ahead and continue the-- let's play through. And we can have-- let's do a simple fix for this. So I'm going to use bind which is going to bind this scope of the method to the object that contains the notify what's selected method. I'm going to save it, use a command S.
And let's refresh the page. So now when I click on the photo, boom, it zooms in. So it's looking pretty good so far. But you'll notice that some of these photos have comment icons on a corner. So when I click on it, we shall load in some comments.
But you'll notice we're not quite safe yet. We have another problem run into. So clearly, what's happening here? So we have four comments but they're all showing up with undefined data. So my hypothesis here is that we're either not getting the right data or not running it correctly.
So let's look at how we can inspect-- how we can debug this problem. Now, what I want to do is I want to see the associated data that this-- that's being used to render these comments. So to do that, I'm going to right click on one of these elements and click on inspect elements.
That's going to bring up these comments in the-- in a DOM tree. And let me scale this a little bit so you can see what I'm going to do. Now, I'm going to bring up the quick console and show you shorthand. Let's clear this out. Now I can use dollar sign 0 and what this does, this is going to reference the currently selected element in the DOM.
So if I press Enter, you'll see that this comment is the same as the comment that I selected. Now, as a debugging technique, I actually associated in JavaScript the info, the data model that this comment used to surrender itself on the element itself. So as I start autocompleting, you'll see there's info object associated with it.
So inspect this object, we'll see that we are actually getting valid data here. So we have the avatar URL, we have a comment text, and we also have a date. But for some reasons, it's not showing up in the code. So, let's take a look at our JavaScript file.
I'm going to use the search here in the top and I want to search for comment code. So let's see. I think it's called Comment, and you see the search bar, such a nice list of wherever the word Comment was in our entire working directory. So in this case, I want to go to this method, Comment, Prototype, Set Info.
And this [inaudible] is really great because we can see-- we can compare to a data that we're getting and a data that we're expecting. So seeing the top, we're sending the image here and we're sending the text from the data, and we're sending the timestamp. But in reality, these are the wrong variables. Here is this avatar. Up there is its image and so on.
So, this is a common scenario where sometimes data might change in the backend and you're not trying to update it on the front end. So let's quickly go in and make these changes and see if it works. This should be comment and this should be date. Again, I'm going to press Command S to save. I want to zoom back out and take a look.
Refresh the page. Let's click on the same image. And there we go, the color is showing up. OK, so I think we're almost done. And let's take a look at some more photos here. Let's take a look at our trip to Thailand. How about this guy? So again, the color is looking good. Let's scroll down. So we'll notice that something else is wrong. So, just when we thought we were done, obviously another bug pops up, that happens once in a while.
So the previous problem was specific-- was happen to all the comments, but this problem is specific to an individual comments. Now, we can use a [inaudible] technique that we used in the last demo, but let me show something that much cooler. So I'm going to go to the search my resources for a method called render comments. Now this is a method that I wrote, so I know what it's called. So let's search for it.
So let's click the right using the search. I'm going to escape out the quick console. And let's take a look at this method. So this method is called when the full screen view shows up and it loops through all the comment data, it creates a new comment which renders the HTML content.
And I will set the info on it which the data we're getting from server. So what I want to do is I want to click on the debugger and I want to set a breakpoints right at the point when the data is being set. This way I can inspect the data right before it get sent to the comments and rendered.
But the problem here is that I don't want to have to run this debugger for every single comment. So I have to go to the first comment, the second comment and so on until I got to this one here. So this is a great usage of something called conditional breakpoints. And let me show you how that works. Let me turn on breakpoints here. Zoom out a little bit.
So you see that, the breakpoint that I click, that I use, that I add by clicking on the gutter here is on the debug panel on the left. So if I right click on this, I can go to edit breakpoint. Now, this allows me to add a conditional expression that will be evaluated right before this method is reached and-- the debugger will only break on it if this condition is evaluated to be true.
So a conditional expression could be anything that you put and stuff in If statements. So in this case, let's try to find an identifiable characteristic about these comments that we can use to add a condition. So in this case we have text "Too Much Fun". So let's select that. We'll just type in instead.
So let's use a regular expression match to see how this works. So, toomuchfun.test, and we want to test it against this line, so let's try this again. So we want to test it against the data and the comment. So let's do commentinfo.comments, remember the correct variable name from the last mistake, press Enter, then we're good. So let's see how this works.
Let's click off this again. And let's click on the same photo here. Now you notice that it correctly stopped at the breakpoint, but we zoom out you see that it actually rendered all the comments beforehand. So this stop only at the comment that was in question which is really a great way. If there was a thousand comments here, that'll be a real pain to go through each one of them.
So using conditional breakpoints, you can easily get to only the problem that specific that you want to find. So, using the popovers, we can now easily go over the code and see what's going on. So here I have our comments arrived. I don't know about you but this is the coolest thing ever. Could I get some applause for this? This is great.
[ Applause ]
Thank you.
[ Applause ]
I mean, I can visually go through the code and just-- it's just so natural. Let me get back to the info, and as you can see, you know, James wrote these comment, added some rogue HTML into the comment which is why it's getting rendered in correctly. Now, this is a really serious issue. This-- the sites won't allow me to cross scription-- scripting attacks and this is something that we'd have to taught to our server about to try to sanitize the content. So, this is a serious issue that using conditional breakpoints helped us out. And with that, back to Antoine.
[ Applause ]
Hey, thanks Brian. So, the debugger sidebar is the way you can always track where your breakpoints are, what this data's recall stack is when you're breaking into the debugger, and using the scope chain, you can always find out these different values of the local variables and their occurring call.
And with conditional breakpoints, you can pinpoint specific instance within a loop or any kind of other condition to just break what it matters. And what I think is really cool about this feature is that imagine you're actually debugging content that's not even local. It's content from the server, there's no way you can edit, edit the file to tweak the breakpoint and just break under certain conditions, this is really where the edit breakpoint, conditional breakpoint setting is just really vital 'cause there would be no other way to do it otherwise. And the popovers, they just work whether you're hovering a simple property or even a chain of properties, it's just really fantastic for real-time debugging.
And again, taking a look at productivity, there are some Command Line APIs that would be really useful to you. So, for example, there are 0 currently selected node, there are 124 last, second to last, and et cetera selected node, comma and underscore, dollar underscore, the value of the last expression in the debugger in the console and even short hands for often used methods such as querySelector and querySelectorAll which you can go with dollar or dollar-dollar.
And we have a whole list of those in the documentation which you should really go and check out. So this was it, the new style sidebar panel made inspection tweaking a breeze, performance analysis with the new layouts, layer sidebar as well as the great timelines view just made it so easy to identify what went wrong, get to the initiator, look at the call stack, and find exactly what piece of JavaScript calls the performance issue, and finally, popovers, conditional breakpoints, all new features in Safari 7 that makes debugging JavaScript code so much easier.
So you can keep up-to-date with our development with Web Inspector by going to nightly.webkit.org and you can download the WebKit nightly and build with the snapshot of WebKit everyday. And race bug as you encounter them, go to bugs.webkit.org/new-inspector- bug will always track in them and trying to fix them as soon as possible.
And if you have any issue you want to discuss in person-- not exactly in person but live, you can just connect to IRC and freenode.net and go to the #webkit-inspector channel and find us there. And finally, because we have open source Web Inspector today, you can contribute directly to the features and the code of Web Inspector to make it just a little bit better.
And so, for more information, you can type [inaudible] or documentation again, you will have to check it out, developer.apple.com/mac, look for the Safari Web Inspector Guide, webkit.org, [inaudible], great places to find more information and get answers to your question. These are some related sessions about performance, CSS features, and introductory talk to Web Inspector if you miss that. Thanks very much.
[ Applause ]