Building Mobile Applications with Ember
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 37 | |
Author | ||
License | CC Attribution - ShareAlike 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this | |
Identifiers | 10.5446/34689 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
EmberConf 201636 / 37
4
5
7
10
11
13
14
15
16
17
20
23
24
25
26
27
29
30
31
32
00:00
VideoconferencingCodeMobile WebBuildingContent (media)Software developerHybrid computerComputing platformDefault (computer science)Data managementComputer iconTouchscreenService (economics)Keyboard shortcutSoftware testingInstallation artOpen setLink (knot theory)Optical disc driveServer (computing)Canonical ensembleJava appletFunctional (mathematics)Client (computing)MathematicsMultiplication signBitNumberCartesian coordinate systemLibrary (computing)1 (number)BenchmarkContent (media)Computer fileCASE <Informatik>ForestSelf-organizationPlug-in (computing)Scripting languageKeyboard shortcutProjective planeFlagReading (process)Touch typingMultilaterationTouchscreenCodeSocial classComputing platformBuildingCore dumpService (economics)DampingIntegrated development environmentRow (database)Sampling (statistics)Machine codeTwitterRenewal theoryMobile appTraffic reportingSoftware testingPlanningRevision controlStructural loadSoftware developerDefault (computer science)Mobile WebExistenceSingle-precision floating-point formatReplication (computing)ResultantComputer iconConfiguration spaceDifferent (Kate Ryan album)Office suiteMoment (mathematics)Directory serviceRankingRight angleLevel (video gaming)Point (geometry)Web browserReal numberGraphical user interfaceCommon Language InfrastructureServer (computing)Software repositoryCheck digitWeb 2.0Task (computing)HookingTerm (mathematics)Data structureView (database)Generic programmingBootingComputer animation
07:04
BuildingUniform resource locatorService (economics)Module (mathematics)Integrated development environmentHash functionEvent horizonMobile WebGroup actionKeyboard shortcutLink (knot theory)Pointer (computer programming)Default (computer science)Computing platformComputer iconRootEuclidean vectorMenu (computing)Touch typingThresholding (image processing)BuildingTerm (mathematics)RoutingPlug-in (computing)Uniform resource locatorSoftware developerEvent horizonRevision controlMobile appRaw image formatLink (knot theory)Cursor (computers)Error messageComputing platformKeyboard shortcutDrop (liquid)Service (economics)Connectivity (graph theory)Multiplication signChemical equationContext awarenessCodeLine (geometry)TouchscreenStandard deviationMobile WebView (database)Client (computing)Volume (thermodynamics)Web browser2 (number)Pattern recognitionComputer iconMathematicsProxy serverType theorySoftware repositoryHookingWeb 2.0Cartesian coordinate systemDifferent (Kate Ryan album)CASE <Informatik>Group actionMedical imagingDimensional analysisKey (cryptography)Endliche ModelltheorieHash functionSelectivity (electronic)Configuration spaceTouch typingGraph coloringPointer (computer programming)Subject indexingOpen setPixelRight angleoutputWordLattice (order)Computer fileSoftware frameworkDefault (computer science)System callIntegrated development environmentWhiteboardGame controllerBitAffine spaceMoment (mathematics)Functional (mathematics)Digital photographyAndroid (robot)Scaling (geometry)Interactive televisionElectronic mailing listMoving averageProduct (business)Slide ruleLibrary (computing)SurfaceRoundness (object)File viewerPersonal digital assistantSocial classComputer animation
13:56
View (database)Android (robot)Keyboard shortcutFunction (mathematics)Default (computer science)Price indexLiquidInfinityWeb browserIntegrated development environmentConsistencyRead-only memorySpeicherbereinigungType theoryLeakGroup actionBitoutputMemory managementRevision controlConnectivity (graph theory)WritingLibrary (computing)Mobile appConnected spaceWeb 2.0Set (mathematics)Semiconductor memoryGroup actionRule of inferenceCASE <Informatik>Computing platformClient (computing)Multiplication signTime zoneSpeicherbereinigungTerm (mathematics)Keyboard shortcutElectric generatorInfinityAndroid (robot)View (database)Plug-in (computing)TouchscreenLeakHybrid computerType theorySpacetimeRaw image formatSoftware developerLoop (music)Line (geometry)Medical imagingDivision (mathematics)Point (geometry)VarianceCartesian coordinate systemCodeElement (mathematics)Different (Kate Ryan album)Pointer (computer programming)PlanningWeb browserService (economics)Overlay-NetzQueue (abstract data type)Configuration spaceVariable (mathematics)Conservation lawFigurate numberControl flowLiquidForm (programming)MathematicsIntegrated development environmentInterior (topology)Fraction (mathematics)Right angleJava appletScripting languageSource codeWeb pageGoogolNumberMachine codeState of matterTraffic reportingComputer animationLecture/Conference
20:49
Normed vector spaceSalem, IllinoisBefehlsprozessorJava appletScripting languagePointer (computer programming)Element (mathematics)Memory managementEuclidean vectorAlgebraic closureFunction (mathematics)Network socketThread (computing)Social classGoogolSoftware developerWeb browserSinguläres IntegralVelocityReal-time operating systemSpeicherbereinigungMemory managementMultiplication signProfil (magazine)CASE <Informatik>Element (mathematics)Normal (geometry)Web pageFunction (mathematics)Social classPosition operatorRow (database)2 (number)Electronic visual displayResource allocationGreatest elementAlgebraic closureFunctional (mathematics)Existential quantificationDataflowClient (computing)Term (mathematics)WindowMobile appPoint (geometry)Entire functionSemiconductor memoryObject (grammar)Web 2.0WebsiteGraphical user interfaceOperator (mathematics)Thread (computing)TouchscreenView (database)TimestampNeuroinformatikRepresentation (politics)Transformation (genetics)Software developerSource codeLine (geometry)Slide rulePresentation of a groupConnectivity (graph theory)Cartesian coordinate systemBitIntegrated development environmentVarianceServer (computing)Web browserCovering spaceContent (media)Library (computing)Different (Kate Ryan album)Reading (process)Type theoryVelocityClosed setPattern languageEvent horizonTranslation (relic)Spectrum (functional analysis)Video gameCore dumpAndroid (robot)Plug-in (computing)SummierbarkeitProcess (computing)Right angleCone penetration testSampling (statistics)Query languageForm (programming)MereologyMoment (mathematics)Replication (computing)Machine codeComputer fileScripting languageOpen setPerspective (visual)Electronic mailing listComputing platformArithmetic meanSheaf (mathematics)Absolute valueForcing (mathematics)Context awarenessComputer animationLecture/Conference
28:44
Asynchronous Transfer ModeSet (mathematics)VideoconferencingService (economics)Event horizonXMLComputer animation
Transcript: English(auto-generated)
00:13
Hey everybody, as you just heard, I'm Alex. We're gonna be talking about building mobile apps with Ember. Apologies if I yawn on stage. I think everybody's kind of having trouble
00:21
staying awake at the moment, so it's not you. So who am I, a programmer? I've been on Ember for about three years now. Before that, like everybody, I started with Java and C. Spent a couple of years writing Go as well, which I still really enjoy doing. And my second ever Ember app was a code over-based application, which is what kind of started this fascination. I promise this will be the only plug.
00:41
I work for a company called Isle of Code. We basically specialize in building Ember code over a hybrid application. So that's what we do. We're mostly based in Toronto. We have an office in Chicago now as well. We also do some of the more generic Ember work. Always hiring, always looking for new people to work with. So the reason I want to do this talk today is I feel like a lot of people have gone and built
01:01
Ember code over applications before, or you've built something in code over, and it just didn't work right. It just felt that little bit out of reach. You couldn't do what it is that you needed to do. You've got to put GIFs in. So what we're going to talk about today, there's a little bit of a preamble just in terms of what we're doing. We're going to talk about how to actually build the Ember and code over application together,
01:21
what tools we used, what add-ons are out there. A little bit about the basics as well. You know, how do we handle splash screens and icons within Ember and the basic changes we need to make to our Ember app. Then we're just going to close off with performance and how do we make these things at least feel as close to native as possible. So why do we want to do this? Obviously because Ember, Ember is fun.
01:41
It's nice to write. But one of the reasons I always talk about with clients and I just like to float as well is it's much easier to go and find a single Ember developer than it is to go and find developers for every platform. And if you're technical, maybe that's not so much of a problem. But at least for us, a lot of people we work with aren't technical and recruiting is a very big problem for them as a result. So we want to make that as simple as we can.
02:02
So just quick show of hands. Most people here know the difference between Cordova and PhoneGap? Okay, not many. So for those who don't, it would be fair to say that PhoneGap implements Cordova. Cordova is that core engine that wraps a web view and creates a native application. It also has the CLI and the basic plugin ecosystem.
02:21
PhoneGap is Adobe's basically proprietary service on top that gives you build services, some extra add-ons, some extra plugins and stuff like that. Historically, it was always called PhoneGap, but basically when the Apache Foundation stuff started, some trademark things happened, they needed to change. I'm not going to touch that discussion. Every time I do it, the trolls come out on Twitter.
02:40
So last point in the preamble is that, you know, building a good mobile app is basically just writing good code to start with. There's no real magic bullet because we're dealing in mobile, especially when we're dealing in Cordova, which is basically just a web browser anyway. I think a lot of people just get used to being lazy because the desktop does let you away with just some worst practices. I used to always make the point as well
03:00
that, you know, a desktop was far more powerful than a mobile phone. But I think we've all seen the benchmarks now where mobile Safari is actually outperforming desktop Chrome in a lot of JavaScript benchmarks. That's not necessarily the case anymore either. So getting into the real content, how do we build these apps? So in the old days, this is how I started.
03:20
We'd build just a kludgy makefile that would go and run Ember build, copy things over and run Cordova build for us. Then later came this library called Ember CLI Cordova, if you've heard of it before. What it did was it automated what that makefile did. It let you run your Ember CDV build and it would go and build both applications for you. And it also included library load, which you could do in Cordova, but it made it easy to do that
03:41
while you're running an Ember server. So a couple of weeks ago, we decided to fork that repo. We'd been helping out maintaining it and writing new features in it for the last six months or so. We decided to create a fork. And the reason for that was twofold. One is we'd been doing some broader platforms work and we needed just to destroy backwards compatibility and you can't really do that with an established repo.
04:01
Then as we started hacking more and more, we just started adding a lot of new features and a lot of the things that we'd wanted to see in CLI Cordova for a long time. So that's why we did the fork. And what have we changed? So we refactored all of the internals and tasks so it now follows your canonical Ember add-on structure. You know, we actually inherit from tasks instead of anonymous functions. By default, it doesn't include any assumptions
04:21
as to how you're writing Ember. So there's no in-built assumption that using mobile touch or hammer time or anything like that, that's on you. The only assumptions we make are how you're going to wrap Cordova. We've also added hook support, which we'll talk about a little bit later. Splash screens and icons are first-class citizens now. We've added some Cordova device and platform services, which I'll tell you about.
04:41
And we're also starting to work on a plugin ecosystem specifically for Cordova. So we're taking those core Cordova plugins like camera, writing an Ember service that will bind them so that you don't need to worry about writing your custom stuff. And we're also working on something so you can run your Ember CDV install your Ember add-on and it will install both the Ember add-on and the Cordova plugin for you so you can pair those two things together.
05:01
If you have an existing Cordova application and you want to try this out, all you need to do is move your Cordova directory to ember-cordova slash cordova. Everything else is going to work as you expect. So what are we working on next? Just more plugin bindings. We're fixing the tests. Unfortunately, they were pretty broken before we did the fork, but we're working on cleaning those up as quickly as we can.
05:21
As I said, more and more plugin bindings. So to get started is pretty simple. We run ember new mobile project. Just do an ember repo, then ember install ember-cordova. By virtue of running that install, it is going to install Cordova for you as well and it is going to init your Cordova directory as well. Right now, because it's a much younger repo, we have a very tight assumption
05:40
as to where you're going to place that Cordova package. So installing this just adds a couple of commands to your ember-cla. All of the ember-cordova commands are just ember-cordova or ember-cdv if you prefer to do shorthand. So obviously, we have a build command. What build will do is it will run your ember build for you. It will then symlink your dist directory
06:00
to your Cordova's www directory and then it's going to run Cordova build. It will actually pull out a Cordova application for you and you can pass whatever flags you normally would there, right? Platform, environment, whatever you're looking for. Some of the other ones worth noticing is Cordova prepare. Every time I talk to Cordova developers, it's interesting how people handle Cordova plugins.
06:20
You know, I've seen people do bash scripts that try and install every plugin that they want. I've gone to projects that have a readme that says if you clone this repo, install these 10 plugins, please. If you weren't aware, whenever you add a platform or a plugin to Cordova, you can actually append a save flag. Not save dev, but save. And what that will do is back it up in config.xml for you. Then you can run Cordova prepare and it will actually go and reinstall every plugin
06:42
and every platform for you. It is the canonical way to handle that and that's what that command will do for you. If you're wondering why that's a config.xml, it's honestly just because Cordova predates NPM and there is a plan to migrate to package.json relatively soon. Last two commands worth noting, ember-cordova serve will actually boot library load on the phone for you.
07:01
There are some conflict flags if you want to know more about it, just go to the readme. And ember-cordova as well. So if you want to run a roll-cordova command, you can just proxy straight through to the repo without needing to type cd ember-cordova. So if you're truly lazy, you can do that as well. So in terms of the hooks we've made available, we have before and after build, before and after prepare. So at the moment, we're mostly using these
07:21
for things like warning a client that they're maybe doing a production build and they need to change something or selective index HTML modifications but those hooks are there for you to use. Lastly, I'm going to talk about intooling. Did we just lose slides? Here we go. Last thing we're gonna talk about intooling is remote inspection.
07:40
So if you weren't aware, there's this great little package called ember-cli-remote-inspector. What it will let you do is as you're running your Cordova application on the phone, you can still run ember-inspector. So you can still get inside and see what's going on. It's completely worth having a look at. So now we're getting the fun stuff, handling the basics. How do we actually build this application? What does it look like? So the first thing you need to change
08:01
is your location type must be a hash. That's an assumption built into ember-cordova. It will actually warn you if that's not the case, so you'll be pretty safe. That's because Cordova uses file-based URLs. You need the hash in there. Another thing you'll need to change, especially if you're developing for iOS, if you're developing for mobile web and Safari, you already know this, is you need to make sure that your data ember actions
08:22
have a cursor pointer. The reason for this is by default, Safari, mobile Safari specifically will only raise touch events instead of click events. So if you have a click to touch polyfill, it's actually not going to fire. So if you change this, what happens is Safari will recognize that the cursor pointer is something that it should register on, and all of a sudden your actions are going to work again.
08:41
Where this applies is anything that's not an a-link or a button, it's generally just safe to add that to your CSS and keep moving. Last little CSS hack you're going to want to do is this thing up there, I'm not going to read that. But by default, a browser will highlight a link that you've clicked. By default, a mobile application does not. That's what this piece of CSS handles.
09:00
It will make sure a link that's been clicked will just retain its original styling. So in terms of handling splash as well, as I said, splash is a first-class citizen in our repo, so it will go and install the code over splash plugin for you. Then there are two ways that you can actually dismiss your splash screen. I'll get into how you package them in a second as well. By default, we propose that you just import
09:21
the splash screen mix-in, and what that will do is on your application routes after model hook, it will go and hide the splash screen. So that's something that will probably save you a lot of time. And icons are coming next week. This is something that we're hoping to have out by the time I was talking at AmberConf, but we kind of really only decided to have this ready about seven days ago, and we've pulled all-nighters
09:41
basically every day since to try and get it out. So that's coming soon. Basically what we're doing is making sure the icons will be handled by default, and then instead of using your icon at 2x names, we're actually going to have iPhone 6 or iPad 2 or whatever it is you're packaging for, just so if you're not used to working in this environment, it's a little bit simpler. That's what this is going to look like.
10:00
So the splash screen you can already do today, but just in your standard config file, go and add code over, path to icon, path to splash screen, and what devices you want to support. The way the splash screen will work as well is that if you're going up and you're scaling up to a bigger device, it's going to figure out what the colors were just on the left and right most pixel and scale out that way.
10:20
It's not actually going to scale your image up, so you'll retain your original dimensions. So one of the other things you're going to need to do pretty frequently is understand what platform it is you're dealing with. So this is something that we just completely forked over from Ionic. It's something they did really, really well in our opinion. So we've created a platform service, and what that will do is let you know
10:40
whether you're running an iOS, whether you're running on an iPad, whether it's Android, crosswalk, running in a web view of browser or something like that. So like anything, you just inject that platform service, then you'll see some function. If this is iOS, we're going to go and do something different. That might not seem very helpful, but you're going to find a lot of cases where you want to slightly change something because it's iOS or Android, and having that recognition makes it very, very easy.
11:03
By the way, all of these services work with your standard Ember getters and setters and promises, so it's built to work with Ember versus just returning something straight up. So we've also gone and added a Cordova service, and this is for if you need to bind to things that are happening inside of Cordova, right?
11:20
That somebody pressed the volume up button, that the battery is low, the battery is critical, anything like that. So what you do again is you can inject the Cordova service. There's also a mix-in if you prefer to consume it that way, and then you'll see we just subscribe. So we'll subscribe to Cordova volume up, and then we can go and do whatever we want to do. I know that this example shows a route, but again, you can inject this wherever you want.
11:41
If you prefer to handle that in a component or a controller, knock yourself out. If you're wondering what events are available, that's basically what you'll have. So one of the other things we need to do is figure out how to handle touch events. So generally, we'll do something
12:00
that implements hammer. I'm gonna show you a hammer example in a second. If you're native to Ember, you can obviously go and use your hammer times or your mobile touches, or depending on what Ember version you're dealing with as well. I'm going to show you a raw hammer example though, just so you can kind of get a feel for what you can change. As you can see, I actually took this screenshot with a transparent background. I'm throwing some horrible error in the background.
12:20
But you'll see we just start a new hammer manager, and we're registering a tap, a press, and a hold, or a pan, sorry. We're registering a tap as a single one, so we can actually get a double tap, a triple tap, whatever it is we're looking for. You know, if we want a press, we're defining that as holding for 800 milliseconds. And a pan, we drop the listeners and we're going to fire events just as if somebody clicked.
12:43
So one of the other things you need to be aware of as well is how Device Ready works in this platform. If you're not familiar with what Device Ready is, it's something that fires in Cordova to say, hey, Cordova's finished booting, we're ready, it's now safe to go and run whatever it is we want to run. And a lot of times, JavaScript developers are afraid of using Device Ready
13:00
because they're worried they'll drop the listener after Device Ready's already fired. Device Ready's actually a special case in the sense that even if you drop a listener once the device is ready, it's going to fire immediately for this reason. So where this really applies to you is if you're building an initializer around the plugin. Great example would be push notifications, where you need to register API keys. You can't do that until the device is ready,
13:20
but your Ember app may be booting at the same time. So make sure you go to every initializer and just wrap it around some type of Device Ready hook. Works just like any other listener. So one of the other things that you're going to want to do all the time is interact with the keyboard. You might want to close the keyboard in certain cases, open it, or just have an awareness of what's going on.
13:41
Again, we've gone and forked the Ionic keyboard plugin. It's pretty, pretty good. And you can see, we go here, keyboard on didShow, on didHide, you can also call keyboard.show or keyboard.hide. And while we're talking about keyboards, this is one of the more important points when you're dealing in hybrid. A lot of people assume that image to the left is correct,
14:02
that when the keyboard is open, our viewport size doesn't change. That's actually not the case. Once the keyboard has popped open, you're going to find that your viewport size has changed relative to how much space the keyboard's using. And this just thrashes a lot of developers because all of a sudden when you reflow, everything on the screen gets 30% smaller or 40% smaller
14:20
and you're wondering what's going on. So how do we handle this? For Android, it's relatively simple. You just want to add these two settings to your config XML, and that's going to make sure that instead of the keyboard resizing the viewport, the keyboard's going to overlay the viewport, which is exactly what we want in most cases. For iOS, that's a little bit more complicated, so you probably just want to go and use the keyboard plugin we've written.
14:42
It's all documented in the README. This was actually worked on by Chris, mostly, or RunSpired, and what he did was he went and made sure that when the body container, or basically when the keyboard is open, the body container will maintain state for you. So you're going to be completely protected from that. So two tools left before we get to performance.
15:00
Just use LiquidFire. I feel like it's been talked about all day, so I'm not going to go into the example, but what I will tell you is that when you're dealing in a Caudova environment, LiquidFire runs completely fine. There's no choppiness. It's as smooth as you'd want it to be. And again, Yehuda kind of spoke about this this morning, so I'm not going to go too deep into it, but infinite scroll, use smoke and mirrors. It works completely fine on the phone again.
15:21
In fact, you really do want to be using something like that for a phone. So getting into the fun bit now, which is performance, right? How do we make sure that these apps actually are efficient? How do we make sure that they're maybe comparing to the performance of a native application? So the first thing you probably want to look at is this library called Crosswalk. If you're not familiar with what Crosswalk is, it's actually built by Intel.
15:41
Initially, they were trying to do this as kind of a Caudova competitor, but now it's something people package much more with Caudova instead. It's explicitly for Android. The downside is it will add about 20 megabytes to your size or your application size. I don't really think that matters, to be honest, but if you're dealing with crappy 3G connections when people are downloading, that might be a bit of a problem. But it gives you two gifts.
16:00
The first gift it gives you is it actually standardizes the in-app browser on Android. If you weren't aware, different versions of Android come packaged with completely different versions of the in-app browser, but unlike, or not the in-app browser, the web view, but unlike iOS, we're actually allowed to change that. It's not against Android's terms of service to put something better into our application. And especially on Android 4.4, you're going to find that it's actually
16:21
a terrible web view. It's really slow for JavaScript. You're going to find about a five to 10X performance speed or performance boost just by implementing crosswalk on those devices. The other thing it gives you is you're going to find, because of the difference in web views, your CSS rules are going to pass slightly differently based on what Android platform you're dealing with. Once you install crosswalk, you're dealing with a consistent platform.
16:40
Again, you don't need to start changing your CSS based on the platform. Another one I always bring up is just know which web view you're dealing in. Especially in iOS, you have two, your UI web view and your WK web view. If you're not familiar, the WK web view is the newer one and it actually implements the newer Nitro engine, which is far more performance. So I found that just by implementing a WK web view
17:01
if I'm allowed to has led to about a 20% performance boost in just any application that I'm shipping with Amber. So make sure you upgrade that. I always forget which version of iOS it is, but basically if you're dealing with anything older than a five, you can go and implement a WK web view. That should have had a lot of cases where clients have asked to just come in and do a performance audit for them. And we've fixed every problem just by going and upgrading the web view.
17:23
Another thing that really will hit you on mobile more than other platforms is that using too much memory has really negative implications. So if you're not aware, you generally wanna make sure that your, especially your heap size isn't getting bigger than about 25 to 50 megs. You'll hear a lot of Coder Dev say that when you get to 25 megs, you're starting to hit your danger zone
17:40
and once you pass 50 megs, you're just gonna fall off a cliff and things are going to break. Again, very much especially on Android. Android is the worst platform for this and it's the one you need to accommodate the most. If you're not familiar, the reason for this is that garbage collection generally requires about six times the amount of memory you're using to actually be effective. So it's not that we're using 50 megs, we're going somewhere between 300 and 350
18:01
and that's not something we really have available on the phone. If you're interested in reading more on that or you wanna see a source, that is exactly where you'd go. So just to talk a little bit more about memory leaks as well, again, you're probably leaking on desktop if you're finding that it's leaking on the phone. It's just going to hurt you so much more
18:21
when you're leaking on the phone. So in V8, which is your Android's web view, you're going to find that there are two types of garbage collection going on, your young generation and your old generation. Most things stay in the young generation, right? They get collected, then they go away. It's something I always forget, but roughly 90% of things will never make it to the old generation. The old generation collection is very expensive.
18:41
So what you're going to find is some collections are going to take less than 10 milliseconds, then all of a sudden your app's going to freeze and it's gonna take a really long time and you don't know what's going on. Probably an old generation collection and what you need to understand is that every time you're declaring a variable, you're basically starting to fill up that queue. So you should be conscious about not creating variables you don't need.
19:01
So this is an arbitrary leak example and then I'm gonna show you one that actually happens in Ember. This won't happen in Ember because obviously your component's going to get destroyed when it goes out, but if you're writing raw JavaScript, if you do var node and we presumably have a div called node on the page, then we create a second reference to it on line two and then we create our body
19:20
and we remove that node from the HTML. So we assume right now that we've just completely cleared up our memory, right? But we haven't because we're maintaining references to that node so even the DOM fragments aren't going to be cleaned up until we remove all of the references to that node. So on line five, we do node equals null. We're still not going to be garbage collected because we still maintain one reference to that node.
19:40
Once we do node again equals null, we've all of a sudden cleared up. So to show you this example, excuse the crappy code in the for loop. I basically copied a leak example from Google that completely bloated up a div with memory and the reason for this was so I could get a heap size of about 50, 60 megs just to kind of really see the difference. But what you're going to see is that up the top,
20:01
you know, we have, you know, var p equals this p. This is not how I'd normally code by the way. This was just a really fast example on a plane. Then we're going and creating an element called detached and then we're setting those on the component, right? This dot set p, this dot set detached. What you're going to find is even though you've removed that node from the DOM, so again you'd hope it's being cleaned up, once you transition away from that screen,
20:22
that is still going to be maintained and your heap size is going to be as big as it was before. You know, that's not going to be collected and you're just going to start leaking and leaking and leaking. So make sure, especially be paranoid about on your destroy component hooks or whatever, that you're going through and nulling references to things, especially, you know, where this hurts people is if you go and put a reference to say a submit button
20:42
or some, you know, fragment that you're going to keep interacting with in the component, make sure you're nulling that on the way out or you might have some troubles. So how do we figure this out? If you're not familiar, I tend to still use the Chrome profiling tools. Mostly because, again, Chrome is the least efficient platform for this. We kind of want to profile the one that needs the most help. So just pop open your normal spectrum,
21:02
press profiles and take a heap snapshot. What that's going to do is go and kind of collect what's been going on and give you an output. I'm going to show you what that looks like on the next page or sometimes what I do is if I'm actively developing and testing the page, I'll go to the record heap allocation down the bottom. That's just going to give you a real time snapshot of what's been going on and generally as I'm developing in two screens,
21:22
I just keep my eye on the left screen to see if something's spiking in a way I don't expect and that's more preventative, right? I'm not really looking for anything that's wrong but I'm trying to figure it out before it happens. So once we've got our heap profile, I generally switch to the containment view. It doesn't really matter which one you're using. It just kind of removes a lot of stuff you maybe don't want to be looking at.
21:41
Then you'll see I went into window, clicked down and detached and we have all of these nodes that have just not been garbage collected. At this point, they're completely off in nodes. They're not going to be collected. It's just going to sit in our apps memory the whole time. So go and run the heap profiler as much as you can and you don't even need to necessarily know how this works yet. You really should read into it but if you're seeing that read and you're seeing a lot of detached nodes,
22:01
it means you probably have a serious problem. Another example of this that's probably biting you all the time if you weren't aware, again this comes from our blog, is if you'd go and register custom jQuery listeners. We have jQuery on the element swipe and then we're binding some type of swipe handler. If you don't actually unbind that listener
22:20
on your will destroy element or on some type of cleanup, again that listener is just going to be hanging around forever. It's obviously not going to fire but that piece of memory you took isn't going to be cleaned up until somebody completely force closes and reopens the app. So you've got to be really careful about stuff like this. One easy way to find out is to go and name your closures for better profiling.
22:40
So what I mean by that, again I've put sources on the bottom of the slide so if you're interested in reading more, you can just click through. You'll see on line four, var LC equals function, that's a completely anonymous function. On line 11, we've called it function LC. What that means is in our Chrome profiles, it's actually going to show up as LC. So we can start to see the impact and I wouldn't really encourage that you go
23:02
and start naming everything if that's not your normal dev flow much as if you're worried that something's maybe not performant or maybe not as efficient, this is a really easy way to go and identify that. Another really fast point here, app size does matter a lot in terms of how big is this compiled Ember application that you're shipping.
23:21
For Android, anything from 500 to 750 kilobytes is generally safe. Once you're getting over that, you're just going to find degrading performance in V8, especially on the phone. For iOS, that's less of a problem. Two megabytes is being completely fine for me prior. And again, if you kind of want to read more into how that works, just go down the bottom there.
23:41
Another little tool we're going to use all the time, and again, you're probably realizing that a lot of this is just your standard web-based stuff. It's almost like we're using a tool that just wraps a website in a native application for us. So window performance is something that you should be using if you don't know. What it does is it lets you register timestamps in your app to kind of see how long things are taking. I've seen people do a pattern before
24:01
that is getting timestamps or date stamps and then minusing them from each other. That's actually not an accurate way to measure time because if your thread's busy or something else is going on, you're not always going to get an accurate to the second representation. Window performance is built to give you that. You can also just run window performance mark if you want to mark certain events and see what was happening at this time, right?
24:21
User press submit, user press bulk upload, whatever it is we're trying to do. Another performance thing that's so important on VOPL but maybe doesn't hit you on desktop, you've got to make sure you're coalescing your requests. Obviously, if you're using Ember data, please make sure your coalesced final request is turned on. That's something that will just thrash the phone otherwise.
24:41
And you're probably going to find pretty quickly that you're going to want to move to WebSockets because it is a little bit cleaner, especially on a phone anyway. You're going to start needing to push content down. I've had very little apps that we've built where a client hasn't eventually come back with a spec of I want you to push something back down to the phone all the time. So start thinking about that ahead of time and maybe just use WebSockets earlier.
25:01
So I'm starting to speed up so we can get to some of the last points. Workers and threads, again, there was a worker presentation earlier this morning so I'm not going to kind of cover too much content here but within a Cordova environment where workers will really help you, they're obviously completely isolated, right? They can't access our Cordova plugins, they can't access our window objects but I use them a lot for bulk passing operations.
25:22
A good example I had recently was we had a spec we needed to download an entire user's contact book, kind of mangle it and then send it back to a server. Once we downloaded from the Cordova contact book, all of that mangling and kind of resubmitting the Ajax requests happened in a web worker and that was completely fine. We took the performance from about 45 seconds down to about eight seconds
25:41
just by spawning that off onto a new thread. So it's completely worth looking at. One of the most important things is reflow. Just again, a quick show of hands, who here knows what reflow is? Okay, about half. So if you didn't know what reflow is, it's one of the most expensive operations that your phone is going to be throwing
26:00
but again, this happens in your desktop Chrome and desktop Safari as well. It's the browser needing to go through and geometrically recompute what's going on, where is it, what do I need to repaint, et cetera. It's something that you really want to be conscious of and avoid as much as possible and what causes reflow? Any time you resize the browser window, you're reflowing. Any time you use our computed styles in JavaScript,
26:22
any time you start manually touching the DOM, you change a class, you add new context, you add new data and any time we change an element's classes. So the TLDR here is it's not necessary that you're going to stop reflowing. That's basically impossible but maybe you're going to start looking at cases where you were toggling classes and realize that that's not what you're wanting to do.
26:41
Maybe you're going to realize that you're toggling a class but the component gets destroyed three seconds later anyway so let's just not cause that double whammy. How do we stop reflow as well? Use your CSS transforms. I've sometimes seen developers, they want to drag an element across the screen so they're doing position absolute, top zero, left zero and then top 10, left 10.
27:00
We're reflowing every single time. If you use a translateX, translateY functions, you're going to find that that doesn't reflow at all so that's why sometimes developers get so excited about that. Another really good case, sometimes once you've learned about reflow, you'll find developers who go ahead and put display none elements because they don't want to show them, they don't want to remove them
27:20
because they think it would be expensive but you're still causing a reflow with display none because you've changed a class. Visibility hidden is another special case where once you trigger it, you're actually not causing a reflow. So if you're in that scenario where you want to take something off the page but you know the component's going away in the next 30 seconds, couple of minutes anyway, generally speaking, visibility hidden it, you're going to get what you're looking for.
27:41
You're not going to cause a reflow but it's going to go off the page. So last point, if you need to do animations, again, I've seen some people do jQuery animate, I've seen people handle it before. We generally recommend that people use velocity.js if you've heard of it. One of the great things I have on this front page is a benchmarking tool where you can run all of the different animations libraries
28:01
and run the same animation and see how they perform. So on the front page here, what I'm doing is we have 250 circles and we're just going to animate them with jQuery left to right. And isn't that smooth? So what velocity does is,
28:20
just imagine because we don't have a lot of time, the intonals are much more efficient so when we run the same animation, way better. So hopefully you've just kind of got a basic overview on how we build these code over applications and just some basic performance tips. That's it, thank you very much.