Rebuilding Tumblr as a Single Page App
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 | 28 | |
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/33647 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
00:00
Mobile appHome pageSingle-precision floating-point formatVideoconferencingCodeMenu (computing)ComputerBlogCache (computing)Bootstrap aggregatingSoftware frameworkMultiplication signRemote procedure callCodeGame theorySoftware2 (number)BlogScaling (geometry)BuildingMilitary baseWeb applicationDigital photographyFunctional (mathematics)MultiplicationQuicksortSet (mathematics)Cartesian coordinate systemBootstrap aggregatingHacker (term)TwitterInternetworkingFacebookNumberSingle-precision floating-point formatRadical (chemistry)Scripting languageSound effectNeuroinformatikElectronic mailing listInteractive televisionMechanism designTerm (mathematics)Query languageFood energyMobile appProcess (computing)Data structureXMLUMLComputer animation
03:42
Different (Kate Ryan album)WebsiteWeb applicationSoftware frameworkWeb 2.0Hacker (term)CodeMobile appSingle-precision floating-point formatHome pageBitPower (physics)Address spaceAbsolute valueDivisorMultiplication signComputer animation
04:17
Point (geometry)Cartesian coordinate systemMachine codeProjective planeComplete metric spaceWeb 2.0Web applicationSocial classMobile appProduct (business)Order (biology)Hacker (term)FrequencyRegular graphHome pageMobile WebNumberMultiplication signBootstrap aggregatingAtomic number
06:01
Software frameworkDisk read-and-write headPoint (geometry)Order (biology)PrototypeTheoryElectronic mailing listSource codeLevel (video gaming)Computer animation
06:49
Cartesian coordinate systemSoftware testingBuildingData storage deviceSimilarity (geometry)Single-precision floating-point formatPhysical systemHome pageMobile appPoint (geometry)Disk read-and-write headHydraulic jumpBitPrototypeElectronic mailing listStress (mechanics)Power (physics)CuboidMultiplication signLevel (video gaming)Integrated development environmentScripting languageProcess (computing)Projective plane
08:53
Mobile WebTouchscreenObservational studyReplication (computing)Web applicationMultilaterationMobile appTouchscreenPresentation of a groupWeb 2.0Operator (mathematics)Home pageConsistencyObservational studyCartesian coordinate systemView (database)Touch typingPoint (geometry)InformationDifferent (Kate Ryan album)Context awarenessCASE <Informatik>CuboidWeb browserMultiplication signQuicksortMobile WebData centerConnectivity (graph theory)Electronic mailing listReal numberData storage deviceRight angleAdditionNatural numberBitLine (geometry)Connected spaceGoodness of fitHoaxUniform resource locatorSoftware frameworkFunctional (mathematics)Level (video gaming)Bus (computing)outputComputer iconFrame problemRoundness (object)Software development kitBootingModul <Datentyp>
13:21
Cloud computingLiquidConcurrency (computer science)Euclidean vectorMathematicsDistanceMobile appService (economics)Web 2.0MetreWeb browserSingle-precision floating-point formatInheritance (object-oriented programming)Roundness (object)MathematicsRight angleCartesian coordinate system2 (number)Utility softwareCASE <Informatik>QuicksortVacuumRouter (computing)Level (video gaming)Multiplication signAddress spaceHome pageAsynchronous Transfer ModeExpected valueAuthenticationDistanceStatisticsConnectivity (graph theory)PhysicalismSocial classPosition operatorConcurrency (computer science)Order (biology)NumberLecture/Conference
15:50
LiquidAuthenticationSimplex algorithmComponent-based software engineeringEuclidean vectorElectronic visual displayMobile appWeb browserData storage deviceElectronic mailing listPrincipal idealComputer fileService (economics)Symbol tableWeb 2.0Multiplication signTap (transformer)Token ringData managementCartesian coordinate systemGame controllerGroup actionLoginAmenable groupBus (computing)Digital photographySocial classNumberConnectivity (graph theory)Regular graphFigurate numberSlide ruleType theoryCuboidStandard deviationModul <Datentyp>MereologyAuthenticationProcess (computing)Subject indexingCross-site scriptingElement (mathematics)Physical systemFunction (mathematics)RoutingOpen setSoftware bugReverse engineeringLiquidEmailWorld Wide Web ConsortiumAuthorizationSign (mathematics)LaserComputer animation
20:03
Euclidean vectorHexagonElectronic visual displayConnectivity (graph theory)ACIDElement (mathematics)Procedural programmingSlide ruleComputer animation
20:41
Concurrency (computer science)Flash memoryError messageCartesian coordinate systemMobile appLine (geometry)Service (economics)NeuroinformatikCommon Language InfrastructureCuboidEmailMessage passingCategory of beingQueue (abstract data type)Multiplication signInterprozesskommunikationConcurrency (computer science)Web applicationConnectivity (graph theory)System callStudent's t-testSpacetime
22:38
Game theoryMaxima and minimaGroup actionMessage passingVideo game consoleFunction (mathematics)Multiplication signWebsitePattern languageState of matterLoginComputer animation
23:21
Concurrency (computer science)System callInformationGroup actionCodeConcurrency (computer science)Task (computing)Wrapper (data mining)Multiplication signInheritance (object-oriented programming)Context awarenessRoutingDrop (liquid)Category of beingFunctional (mathematics)Cartesian coordinate systemConnectivity (graph theory)Physical systemProcess (computing)Roundness (object)TouchscreenStatement (computer science)Operator (mathematics)Software testingMathematicsForm (programming)1 (number)Lecture/Conference
25:05
CodeBitEndliche ModelltheorieConnectivity (graph theory)Menu (computing)Group actionTouchscreenRoutingHookingFunctional (mathematics)Buffer overflowLogicLink (knot theory)Operator (mathematics)Computer animationLecture/Conference
26:10
Group actionCartesian coordinate systemEinbettung <Mathematik>Perfect groupGroup actionStandard deviationPoint (geometry)Computer animation
26:51
Group actionEuclidean vectorSubject indexingPrice indexData analysisSemantics (computer science)Chromosomal crossoverUniform resource locatorEinbettung <Mathematik>Group actionSource codeConnectivity (graph theory)Mixed realityRight angleOpen sourceGraph (mathematics)Utility softwareConfiguration spaceElectric generatorKey (cryptography)Error messageArmModal logicFood energyMathematicsDependent and independent variablesSet (mathematics)Electronic program guideAnalogyCategory of beingData structureEndliche ModelltheorieSystem callCuboidSoftware repositoryMessage passingComputer animation
29:11
Message passingMetropolitan area networkDaylight saving timeExt functorComponent-based software engineeringLogarithmAvatar (2009 film)MIDISpecial unitary groupComa BerenicesBuildingGroup actionSoftware engineeringUser interfaceMetropolitan area networkBlock (periodic table)Greatest elementWrapper (data mining)Semantics (computer science)Mathematical analysisSoftware developerFlow separationCodeComputer animation
29:46
Electronic mailing listComputer-generated imageryUser interfaceComa BerenicesMessage passingLogarithmAnalog-to-digital converterExecution unitMobile WebCodePermutationConnectivity (graph theory)MathematicsLevel (video gaming)Data managementPlanningSoftware developerPerfect groupCartesian coordinate systemBuildingCuboidPower (physics)Social classSemiconductor memoryBlock (periodic table)Right angleInternet forumComputer animation
31:21
TwitterBlogCartesian coordinate systemEndliche ModelltheorieDependent and independent variablesElectronic program guideSoftware developerCoefficient of determinationAdaptive behaviorSerial portArithmetic meanGodTerm (mathematics)Logistic distributionReading (process)Service (economics)Computer animationMeeting/Interview
32:58
BootingNumberMultiplication signCuboidSoftware frameworkCartesian coordinate systemWeb applicationComputer wormSlide ruleState of matterPerformance appraisalEndliche ModelltheorieMedical imagingMereologyProcess (computing)Game theoryComputer animation
33:55
CodeVideoconferencingRSA (algorithm)Core dumpStrategy gameFunctional (mathematics)Software developerCuboidLibrary (computing)Atomic numberMobile WebBuildingRight angleWeb applicationMachine codeCASE <Informatik>INTEGRALDemo (music)Information securitySlide ruleDirected graphIntegrated development environmentSequenceFiber bundleCartesian coordinate systemPrimitive (album)Point (geometry)Heegaard splittingLevel (video gaming)Frame problemScripting languageSoftware frameworkCodeSubject indexingAbstractionNumberEntire functionCross-site scriptingRoundness (object)Control flowSoftware development kitoutputPairwise comparisonLecture/Conference
Transcript: English(auto-generated)
00:13
Hopefully you've had time to pee, do whatever you need to do, and we're good to go for the next session. Hi, my name is Ollie Griffiths.
00:22
I don't know how to use this remote, so let's do that. Okay, yes, this is me. I am a software engineer, and I don't do JavaScript. I'm actually a PHP engineer. I work at Tumblr. Shout out to my PHP folks over there. Yeah, there's not many in here. Yeah, I work at Tumblr.
00:42
I've been there for a couple of years now and moved to the U.S. four years ago. I'm obviously not American or Australian, as I usually get. Yes, so I work at Tumblr. Work on a backend team there. And what is Tumblr? Who here has used Tumblr or knows what it is? All right, that's a pretty good,
01:01
usually I don't get that. Most people are like, yeah, what is it? Like a blogging thing? I don't really know. So this is Tumblr. It's a community-driven application full of all sorts of weird and wonderful things that exist on the internet. It's really centered around communities. It's there to fill the gap between the personalness of Facebook,
01:21
the public presence of Twitter, and the take a photo of everything I eat land of Instagram. So this is some of the stuff that you can get on there, whether you're into comics, computers, home improvements, supercars, sports, even food porn. There's pretty much everything on Tumblr for you.
01:41
Go check it out. So Tumblr, it's a place to be yourself. So cool, that's that spiel out of the way. Let's get on to the cool stuff. Engineering. So at Tumblr, we deal on a massive scale. We've got roughly 147 billion blog posts, 341 million blogs.
02:01
It equates to about 35 million posts a day and about three million cash hits a second. This is like, it's pretty big data. But along with big data and big infrastructure comes a set of pitfalls. We have a fairly high latency outside of the US. We are hosted in the US. It's a US brand born out of New York.
02:22
We have multiple code bases to support. It's a 10 year old application and with 10 years comes a fair amount of legacy code base. And coming with that is an inability to adopt new technologies. It makes it difficult to be agile and we kind of struggle with our web app to provide native app-like functionality.
02:43
It becomes difficult. So this is our stack right now. We are primarily in the front end, Backbone and jQuery based. We have a custom MVC stack that uses Backbone. We have a three to four minute build time which is super fun. If you're trying to build any of our legacy assets,
03:00
you can literally go and get a cup of tea whilst that's happening. And I'll do that now. And we have some custom data bootstrapping. So what am I here to talk to you about? Well, at Tumblr we have a thing called Hack Days. And if your company doesn't do Hack Days, you should absolutely give them a try. They're freaking awesome.
03:20
We love them at Tumblr. They drive innovation and you can basically build whatever you like. You have 24 hours build anything. One year somebody built a interactive mirror. Nothing to do with Tumblr, but it was cool and it worked. Yeah, so you have 24 hours you can build anything. We have prizes and raffles and games. At Tumblr we love them.
03:43
So this is me. My first Hack Day. All bright eyed and bushy tailed. Just started at Tumblr and I thought, okay, what am I gonna do? Tumblr has an API. We have a website. We have apps that are powered off the API. We have a different website that's not powered off the API.
04:00
And it's a completely different code path. So why don't I try building Tumblr as a single page app? So I decided to have a go with Ember.js. I'd had a tiny little bit of experience with it before and figured, well, it says on the website, it's a framework for ambitious web apps. Tumblr is a web app, so why not give it a go? And this is me. 24 hours in.
04:21
Burning in copied and pasted HTML and CSS directly into this brand flashy new application. And it turns out that just copying and pasting your HTML from your current app into a new one, it's a bad idea, don't do that. But luckily Tumblr has a facility for us to be able to take Hack Days beyond a single 24 hour period.
04:42
We call them labs. So labs allow us half a day a week to work on a side project outside of our daily roles at Tumblr. And it's encouraged to bootstrap projects that are outside of the regular product roadmap. So I decided, let's start a single page app. Lab, and this started in October 2015.
05:01
So half a day a week, not very long, started October 2015. And I'm gonna preface this by saying everything that you're about to see is still a lab. It's still a complete prototype, but it's proving a point. So this is the ragtag bunch of guys that started this project with me. They are sitting somewhere over there, fellow Tumblers.
05:22
And we decided the best thing that we should do is to see if we could build a native comparable mobile web app. And what exactly is required in order to be able to do so. So the key point here is making sure that the application that we produce is as close to a native application experience as possible.
05:42
And you shouldn't leave your web users behind. Yes, provide them with a native app if you so wish to, but don't neglect your web experience just for the sake of it. So we decided we wanted to make a first class web experience. So this was October 2015. There were really two major candidates at the time.
06:00
We had Ember, we had React. And we pitted them head to head against one another. We decided these are the two major frameworks that are gonna be able to solve this problem for us. And we decided to build a simple prototype in both. The basic idea of the prototype was to fetch data from the API and render a list of posts. Nothing fancy, just like title, ID, that was it.
06:22
And what would we need to go through in order to get to that stage? Like from step one, nothing like npm install to that point. What do we have to go through? Can anybody name these two characters, by the way? Yes, and? Yes, excellent. Now, I don't know if anybody noticed, but Tumblr has this really weird obsession with Guy Theory.
06:42
And you'll notice he's right there. Can't get away. So we started. We started down this road and this is where it started. We jump in head first into the world of single page apps. And this means everything from understanding Ember's build system to understanding how to do the same thing in React.
07:01
We wanted to build a similar prototype in both. So it kind of felt a little bit like Mr. Krabs here with the fast pace of JavaScript. It's kind of overwhelming. There's a lot of things to learn. But we decided, let's do it. Feet first, jump straight in. We noticed that with Ember, we were able to get up and running
07:21
and be productive from day one. React was a little more difficult. If anybody here has tried to configure Webpack to build React, pre-React create app, which is a godsend, but it didn't exist in October 2015, and this literally took us days to get just to the point at which you could do Ember new
07:41
and have a full setup, build environment, tests and everything. So it was difficult. And because of that, we also looked into the backing data stores that were available for React. And at the time, Redux was still in fairly early stages of adoption. It's kind of difficult to get started with.
08:02
And Ember for us just worked out of the box. It was simple, Ember new, off we go. And in the first day, we had our list of posts being rendered straight away. So eventually, we ended up here. We're aboard the Nebuchadnezzar with immense power beneath our feet. We knew where we were going, we knew what we wanted to do,
08:22
and we knew that Ember was the tool to do that for us. Ember also has one major, major advantage over React, and I cannot stress this enough, and that'd be add-ons. Add-ons provide so much extra for the React ecosystem that React unfortunately doesn't have right now. NPM is not a replacement for add-ons.
08:42
It allows you to add into your application through build pipelines, through providing essentially full applications as an add-on. So add-ons really, really allow you to turbocharge your Ember application. Yeah, right? Portland's cool, by the way. I've got another cool slide later.
09:02
So creating a native comparable mobile web app. So what is actually involved in that? What things do you actually have to do if you want to be able to build something that is as good as a native app? Well, first off, you have offline support, and that was touched on earlier. For a native app experience, you need to have the app boot immediately. It needs to load off the device.
09:21
You cannot be waiting for round trip times to your data center to go and fetch your HTML and assets and so on. So you really should have the app being bootable off the device. No HTTP requests offline is absolutely paramount. Animations. Users have become accustomed to smooth 60 frames a second animations,
09:41
and they provide this sort of skeuomorphic experience to the user where you've got bounces and easing and so on that feels good when you use them. And I remember when iOS 7 was released, and they added all the gesture support and animations and all that kind of stuff, and it made all the apps feel good. The web, not so good. There are some solutions to these,
10:01
but out of the box, it has the tools, but there's no out of the box SDKs that are gonna make it nice and buttery smooth for you. Modular and reusable. This is something that native apps kind of get out of the box. You have a UI kit in iOS where you're able to build reusable views that you can drop in anywhere throughout your application.
10:22
So if you render a post in a list of posts in one screen that you use that same view somewhere else in your application, and it looks the same. Users, they expect consistency throughout your application, and for it being modular and reusable within the application itself, so we're talking about components and things here, that's really, really important. Push notifications.
10:41
We finally got support for this a few years ago, but prior to that, it was like, you shut out of luck, I'm afraid. Push notifications were something only the native apps had. We can do this now, and users are expecting this. They expect to be able to have push notifications. Popovers are a really, really interesting thing.
11:02
Popovers provide in-band context information to your application. So if anybody here has ever used an iPad, which I'm sure everybody has, you'll notice that on the iPad, you can tap on a button and you can see a popover in line because you have much more screen real estate. Well, on a mobile device,
11:21
you don't have that screen real estate. You're transitioning to another page. The difference with web is that you're really not limited to the screen size. The user could start out small and then it could get big. So popovers actually become really, really challenging. Touch and gestures. Another really big thing that was introduced with iOS 7 and that everybody has become used to now
11:40
is that you can swipe to go back and you can do native scrolling. Touch and gesture support is something that the native frameworks provide, and they provide pretty good SDKs for them. The web, again, slightly more difficult. It's all possible, but none of this is easy. And the last thing is home screen apps.
12:01
Users expect to be able to have your icon for your app on your home screen. I mean, why wouldn't they? They wanna be able to quickly access your app and you want users to be able to quickly access your app and use it as if it were a native app. It's interesting because studies show that users don't know or care the difference between a native and a web app.
12:20
Realistically, what is the difference? From the user's point of view, they're clicking on an icon on their home screen and up pops your app. Whether they get that through a web URL, whether they get that through an app store, it doesn't make any difference. And fake news, I made that up. But the sentiment is true. It really doesn't matter where your application comes from. Users expect the same level of functionality
12:43
from a web app versus a native app, but they honestly don't know or care the difference. If I ask my mom, for example, and sorry, mom, I'm gonna throw you under a bus a little bit here, to describe the difference between a web app and a native app, should say that, well, the web app I get to through a web browser and the native app I install through an app store
13:03
where I click on a button on my home screen. But why? Do users even care? Well, I'm pretty sure if they have to download an 80 meg app just to get back to the same place that they were on your website and they're doing that over a 3G connection, I'm pretty sure they care.
13:22
So why are these things important? Well, users become to expect a certain level of polish in your application. And right now, web apps don't really live up to that same expectation. So how can we address that? Well, I'm gonna show you some of the things that we have used throughout our journey with Ember. So add-ons.
13:41
As I mentioned earlier, add-ons really do provide you this extra level of flexibility with your application to be able to use pre-existing made components and utilities and helpers to be able to make your application perform better. So these are the add-ons that we used
14:01
within our application. We've got everything here from animation support to concurrency. We've got auto prefixes so you don't have to keep using your browser prefixes. It'll automatically do those things for you. And these are all community add-ons. These are things that others have made that have made our lives easier. We haven't had to spend the time reinventing that wheel.
14:22
So the first one is offline support. And we're gonna go back to school for a bit. We're gonna do some maths. So the speed of light, three times 10 to the eight meters a second. The speed of light in glass is two-thirds of the speed of light in a vacuum. So you've got a, what's that, 200 million meters
14:42
per second. The distance from the US to Australia is roughly 15,000 kilometers. So speed equals distance over time if you take yourself back to your physics classes. Therefore time equals distance over speed. So if you're in Australia, the single trip from Australia to the US, 75 milliseconds.
15:03
And obviously it's round trip, 150 milliseconds. You've got 150 milliseconds of nothing. And that's working on the best case scenario that all of the routers and switches between Australia and America are instantly fast, which they're not. Verizon actually publishes statistics on this and they published 152 milliseconds,
15:22
so I think my maths is right. So offline support, this was touched on earlier. Super, super important. We're using AppCache in here because AppCache has better support across browsers. It's not as clever as Service Worker. You really need to do a sort of two-pronged approach there. But you can see here that the app is being put into offline mode and it still works.
15:43
You can navigate between different pages. Obviously things like authentication do not work. You have to hit your server for that. And this is what it looks like. You've got a manifest here, you basically just list, these are all the files, hey browser, go store all these offline, and the browser will tell you when that's happened. And you can then decide what you want to do when that's happened.
16:00
You could present the user with a notification saying, hey, how about you add this app to your home screen now that you've downloaded all the assets? So AppCache, great support. Service Worker, not great support. It will happen. It'll be amazing. It'll be great. Animations. Animations are a huge part of your application.
16:22
So we're using an add-on here called Ember Liquid Fire. And what Liquid Fire provides us is a literal drop-in replacement for your standard outlet tag. And it provides you animations out of the box. You have to do almost nothing to actually support it. It's incredible. And as you can see here, we're logging in.
16:41
When you click login, we'll get a nice little slide animation. Hey, that looks like a native app. Cool. So this is what it looks like. You swap out your, let me use the laser. Ooh, yeah. You swap out your regular outlet with a liquid outlet, and you right here configure a transition. And we're saying from the index route to the login route, we want to use a crossfade,
17:02
and we want to use that in the reverse. So if the user clicks forward or back in their browser, they get the reverse. For those of you on this side, we're gonna do a transition from the login route to the dashboard, and we're gonna use the two lefts, like the iOS-style UI navigation controller transition. Next up, authentication.
17:21
Anybody here who has an application that has users has to deal with authentication. So how do we do that? Well, we use an application or an add-on called Ember SimpleAuth. Man, these lasers are cool. Ember SimpleAuth, it provides you with scaffolding to handle your application's authentication and session management. It provides the basic hooks to be able
17:41
to authenticate with the API. It provides the ability to automatically attach outgoing headers, so you can attach like a bearer token for your OAuth 2 header. You can automatically sign outgoing requests for things like basic auth and so on. And it also provides session management such that if the user logs out in one tab,
18:02
they're logged out in all tabs. Now, this isn't something that native apps have to deal with. Like if you log out in a native app, you're logged out. In a web app, the user can have as many tabs open as they want, and you want them to be logged out in every single tab. Being logged in in one when you've logged out in another, that would be bad. Imagine if you were at a web cafe and you'd forgotten to close one of the tabs
18:20
after you've logged out, and now someone has access to all your data, or bummer. Web Components. So off the back of Glimmer, we've had this promise of Web Components for some time, and Web Components is a W3C spec that's still in the process of being finalized, I believe. And as yet, we don't have access to them.
18:41
But we can get very, very close. So we used an add-on called emma-component-css. And this is a fantastic add-on. Eric Brin is somewhere in the audience here. Shout out to him, thank you so much. This has made our lives a million times better when it comes to dealing with CSS. Anybody here who's had to write CSS will know they've accidentally styled an element
19:02
that they didn't intend on styling, because CSS is cascading style sheet and it cascades down through your browser. So accidentally targeting something else in the browser, I'm sorry, that's a feature, not a bug. This is what it looks like. So you have your styles CSS in your component,
19:20
and the add-on will automatically take those styles and also generate a class name, and it prefixes all your styles with that class name. It also adds a class name to your component HTML that's output in the browser. And you'll notice that the class name here matches the class name in the DOM.
19:41
What this means is it's literally impossible to leak a style outside of a component. And this is awesome for that modularity that I was talking about earlier, the ability to be able to reuse components throughout your application, and no, guaranteed, wherever you put this, it's not going to be affected by anyone else's CSS. Of course, you can still affect child components,
20:01
which is why we use the descendant selector. Oh, no, which is why I don't know how to use this. Yeah, you'll notice that we're using the descendant selector here, so that in the CSS that's generated, we know we're targeting the specific elements that are in our component itself, and not accidentally leaking any things further down
20:22
to any components that are used within our component. And this is what it looks like. So it looks pretty much like that. You can see that, I don't know, you should probably have got the idea from the previous slide, but you can see there that the component name that's generated there is the same as the component name that's generated there.
20:41
Alerts and dialogs. So users are accustomed to your application providing alerts and dialogs, either natively or within the application itself. So we used an Ember add-on called Ember CLI Flash, and this is what it looks like. As you can see, error. Thing did not work. We also color the header bar here up here, the toolbar,
21:03
with the Ember computer property that just changes the style there. You'll notice that when this one disappears, that goes green, pretty cool. And you can have sticky messages, which is pretty awesome, so it can stay up there till the user dismisses it. Our user dismissed it. We also extended this add-on to add dialog support. So where you can automatically add dialog messages,
21:23
of course, to your application. This is in line with our standard branding. Our native apps do this. Our web app does this as well. And it provides a pretty simple way of providing flash messages to the user. So we use this add-on, Ember CLI Flash. Shout out to Lauren Tan, wherever she is. Great work on this.
21:41
This has really saved us a lot of time with providing a centralized way of managing flash messages. So if I go through this very quickly, you inject your service, the flash message service. You grab the service, and you push a message onto it. So this is like a notice. And this can be anywhere in your application. Let's say, for example, you have some offline notification message.
22:01
We then built a component, which outputs the flash messages that are on the queue. And the flash message system itself handles auto expiry of the messages, cleaning them up, making them disappear, and so on. Really, really awesome. It just worked out of the box. All we had to do was style it, which was pretty cool. Concurrency.
22:21
There's a talk on this, I think, tomorrow. By Alex. Concurrency is a fun thing. If you've ever done a callback with an Ember component, you will know you get into problems if that component is removed from the DOM. So Ember concurrency helps with that. To be here, we've got a Like button.
22:41
And you can see I'm clicking the Like button. And you can see on the right-hand side here the status messages that I just hacked in there. And you can notice that every now and then, we've got a bunch of grouped up messages here. So every time we click this, we're outputting a console log. And then from the action that's triggered, we're also doing a console log.
23:01
And you'll notice that, although you can't see it, I'm clicking this button curiously right now. And outputting here, we've got multiple stacked messages because it's not doing anything. The actual main action itself that's doing the HTTP request, only one of them is happening per full run of this button. So that timeout for that animation to happen and then disappear, we only allow one action to actually happen whilst that's running.
23:21
Let me show you what that looks like. So this might be easy enough to see. We import task, and we import timeout from Ember concurrency. And we define a property on our component. And what this does is we call the task function, and we provide a JavaScript generator. From here, I'm just calling the data down, actions up.
23:42
This is good. So our action is going to be called on this Like button, and that'll be handled further up the stack. And then we're yielding a timeout here. So what this does is this yield and this timeout is actually yielding a promise. And the task system in Ember concurrency is expecting to receive a promise returned from it,
24:00
and it will pause this function whilst that promise is running. So timeout is just a really simple wrapper around set timeout that returns a promise. And notice we've got this drop keyword on the end here. There are various different ways to configure this, and we've configured it in the drop method. Basically what this does is every time this action is tried to be fired, if there's one already running,
24:20
it'll just drop the existing ones. You can do other things like stack them up, you can cancel existing ones, and so on. But this is the functionality that we wanted. And then from our click handler, we just call perform on the task itself there. Super simple. And it means we don't end up in this call back hell nested callbacks or chained then statements.
24:43
It makes our code very, very declarative and very easy to follow along. So next up, popovers. As I mentioned, popovers are really, really difficult with responsive applications. You have no way of knowing realistically whether or not you should be transitioning to a new route
25:00
and showing a different screen, or whether you should be showing the context information as a popover. So we actually built an in-repo add-on to handle this for us, and this is what it looks like. So we've got our account menu up here. You click on that, we show a popover. And we have logic in the popover to make sure it stays on the screen and doesn't overflow the edges and so on. And if you change the size of the viewport and you go down to mobile size, this now actually
25:21
does a route transition instead of doing a popover. And it turns out this is actually a lot more complicated than it needs to be. Doing this in a nice reusable way has meant a little bit of hacking, but we're using mostly public APIs to do it. So it actually works really, really well. And I don't actually have a code example of this, but if anybody wants to see it, please come and give me
25:42
a shout afterwards. And you basically invoke this in the same way that you do a link to. We created a link to popover helper. And that basically wraps around the popover functionality and it automatically pulls your model from your route hook. So all you have to do is define what is the route, what is the component that I want to render within the popover
26:02
itself, and that's it. It hooks up everything else for you. It'll grab your model. It'll inject it into the component as if by magic. API actions. So who here has used an API that is not a standard REST JSON API?
26:21
I'm expecting to see every single person's hand up in here. I call these restless APIs. It's all well and groovy if you have the perfect RESTful JSON API and Embedator is like, cool, bro, I got your back. If you don't, it's not so easy.
26:41
So our application has some restless endpoints, namely like. That like action you saw earlier is sending an HTTP request to user slash like, and you can see it happening here, and user slash unlike. And Embedator doesn't handle this very well at all. In fact, it doesn't even cover this in any way.
27:02
You are on your own. However, Embedator handles getting the URLs to send HTTP requests to. There is some crossover there, but it just doesn't handle the non-RESTful semantics. So we built an add-on to handle this for us. We call it Embedator actions. It's currently in repo.
27:21
I'm hoping to open source it. But this is what it looks like, and it's super, super simple. So here, I haven't imported it up here, so you can't see that. But basically, you call action. So you define a property on your model, call action, pass it the action that you want to run, and you pass it the property that you want to toggle or change when the action has returned true.
27:42
Same in the inverse, unlike, unlike, and we're going to change liked back to false. Then in your adapter, you define a set of actions. And here, I'm just defining the like action. And I'm going to say, when this action is fired, hit up user slash like. And you're going to take the model keys, ID and reblog key. These are Tumblr-specific things. And those will automatically go in the post body.
28:02
You can configure whether it's a post request, a put request, delete request, whatever you like. And those things automatically get added into the body. Then in your component, the API is super, super simple. Grab the post, call like. Seems simple, right? This is really, really difficult with Ember data out of the box. So we built an add-on for it. And we did it as an in-repo add-on.
28:22
In-repo add-ons are super cool. You should give them a try. This is what the syntax looked like to generate one. You call ember g in-repo add-on. And you give it a name. And then when you want to generate something within that component, you want to say create a component in that add-on.
28:41
You just add the dash dash in-repo add-on and give the name of the add-on that you're generating the component into. And Ember will automatically generate you a structure that looks something like this. This is our Ember data add-ons. Very, very simple. We've got our mix-in for our adapter. And we've got a utility that we use in the model that action callback that I showed you.
29:02
Really simple way of prototyping out something that you think, hmm, maybe I might want to open source this in the future. Last thing is living style guides. Now, living style guides has been really, really useful for us. And we're using an add-on called ember-freestyle. And as you can see here, this kind of looks like what you saw earlier.
29:21
We've got all our different add-ons. It shows you the invocation below it, you see right there. And this is actually rendering what is in here. So you basically wrap this in a special semantics for this add-on. And it will render that add-on in that block. And it will show you the invocation at the bottom here. This is really useful for both developers and for designers,
29:40
because it allows them to separate those concerns. Designers can decide, well, actually, you know what? I don't want to see all the code. I don't really care about that. They can toggle that on and off. Developers can look at this. And it basically provides you a certain level of API documentation for your components. You can see right here, it lists out all the different permutations of a component that you might have.
30:00
And bam, you can happily manage change management, make sure things don't break. And as you can see, it looks pretty snazzy. So we still have plenty more to do. And one thing that I really want to get across here is the use of add-ons allows you to do one great thing.
30:21
It allows you to stop reinventing the wheel. Unless, of course, you're in the business of wheel making, then don't go ahead and reinvent the wheel. Build an add-on. Use an add-on. At the very least, if you have a concern in your application, it probably applies to someone else as well. So consider making an add-on. Start off as an in-repo add-on and move on from there.
30:42
So things are not perfect right now in the Ember ecosystem. Ember data is awesome if your API is a perfect RESTful JSON API. Rocket.js, it's super powerful. The documentation isn't great. Ember works out of the box.
31:03
But sometimes you don't want the whole box. And mobile performance for us in this application is absolutely paramount for 2017. And I know it's something that is at the forefront of Tom's mind right now, making sure that Ember really is a first class citizen when it comes to performance. So the question is, how do we get from here to here?
31:28
Well, I was just trolling around on Twitter. And I found this guy. And he said this. As a tech community, we must treat documentation, marketing, logistics, infrastructure, art, et cetera, work with as much respect as engineering.
31:44
And this couldn't be any more true. We have a responsibility as consumers of this application to give back. Now, that doesn't mean you have to develop an add-on. It could be that it took you weeks to understand what serializers are and what adapters are in Ember data. And then finally, you read a blog post somewhere,
32:02
and you're like, oh my god, I get it. Submit a pull request to the guides repo, because it's not that clear. Another thing, when you're looking at, this is really interesting. And I probably should have done this really prior to this, because I eat my own dog food.
32:22
Returning something from a model hook, when you look at how that stuff works in Ember, it's just assumed that you're using Ember data. Maybe you're not. It doesn't actually say on the first model, the guides for the model hook, that you can just return a promise. Or if it is there, it's very, very buried. And these are the kind of things that stop other developers from being
32:41
able to get involved in the Ember ecosystem, because some people want to persist and really dig into the internals and find out how stuff works, and some people don't. For those that don't, that's totally OK. No one's expecting you to do so. But if you know the answer, just submit a pull request, make things better. Another big thing we need to be doing is we need to break up the monolith.
33:01
And I was really unsure about this slide, because it's kind of weird, and it creeps me out. But for those of you that haven't read it, there's an RFC. It's up here. It's number 176. And you can get to it, github.com slash emma.js slash rfcs, about breaking up the Ember monolith application. Glimmer is going a huge way to accomplishing this.
33:21
There's a whole bunch of other things within Ember itself that, if you don't need all of the box, don't ship all of the box. And that's imperative, not just from shipping the bytes down the wire, but from the bigger the payload, the longer it takes. The larger the payload, the more JavaScript there is to parse and evaluate, and the slower your boot up time is going to be. It also means that we can really
33:41
start competing in the framework wars as not shipping a monolith. I think people nowadays in the JavaScript community are used to being able to receive small packages. So that's what we want to be able to do. So what did we learn? Well, it turns out making web apps is hard, but making native comparable web apps
34:03
is even harder. There are so many things that you have to take account of these days. We don't have the luxury of native applications where they come with these lovely APIs and SDKs like iOS that comes with UI kits and all the animation libraries. And we don't have that. We have the DOM.
34:22
If we're lucky, maybe somebody has abstracted it into a library that we can use. This is where add-ons come in. We are providing abstractions on top of this to make these APIs accessible and consumable by other developers like yourself. You can't simply just get by with jQuery anymore. These are some of the concerns that you have to deal with if you're building a mobile web
34:42
application that you want to be as good as native. There's a lot of things here, and I've covered some of them. But there's a whole bunch of other things, even outside of this slide as well, that you have to be aware of. Security is a huge thing. So things like sub-resource integrity, go check that out. It's supported in Ember out of the box. Isn't that cool? Things like cross-site scripting.
35:00
You want to have 60 frames a second animations. You want to make sure that you have code splitting, which we hopefully will do sometime in the future. You want to have a deployment strategy. You need a build environment. You want to potentially have offline data and use it like IndexedDB. You want to have async bundles so you can split your application down into smaller pieces and only ship the user what they need. So many things that you have to deal with.
35:23
Don't try and reinvent the wheel. So I'm going to leave you with a few things here. Number one, stand on the shoulders of giants. You can do it by using a framework like Ember. You don't need to reinvent the wheel. You can use the collective knowledge of the community, and we can all benefit together.
35:43
We can do great things. If we work together, build add-ons, as the core team said earlier, as Tom and Yehuda said, they're going to be focusing on lower level primitives, which will really allow add-on developers to bootstrap and build out functionality on top of Ember
36:01
for the entire community going forwards. So let's say check out emberaddons.com. Great resource for the latest and greatest add-ons that are on the market. And I want to take this opportunity to give a shout out to Tom and Yehuda and the entire Ember team and the core teams for building an incredible framework
36:20
that we've been able to build our applications on top of. So I think at this point, I'm just going to give everybody a round of applause for the Ember core teams. So thank you. This is me. If you want to hit me up, please do so. If anybody wants to have a look at the application
36:41
that we've built, I'm more than happy to demo it. Thanks very much. Enjoy your break.