 OK, so I'll start. Can we make the lights dimmer? OK, so I'm going to talk about today, ember2.0 and the road ahead. I actually agonized a lot over this title, because really what I want to talk about is just like, where are we at? ember2.x, where are we at? But that seemed like a bad thing to put on meetup.com. And really what I want to talk about is sort of like a post-mortem for ember2.0, although that also seems like a bad thing to put on meetup.com since we're not dead yet. And I want to talk about sort of, we're in a weird place right now, because a lot of the things that we want to do for ember2.0 are still in progress in early 2.x, and a lot of the things that we want to do in 2.x have not happened yet. So I'm going to try to talk about all that. So first of all, ember2.0. So we first announced that we were going to do 2.0 a long time ago. The date on that is November 2014, and we merged it December 2014. So we made this RFC a long time ago. It may be hard to recall, but when we announced ember2.0, it happened. It was like a few weeks or a month after the Angular 2.0 thing. And we had been working on the ember2.0 plan for a while. So I think we talked about it at every face to face from probably summer of 2014 until when we announced it. So we effectively knew the plan. I'm personally a big believer in stability and compatibility for years, years, years, multiple projects. So I kind of knew what I wanted to do already. But we announced this around the same time as there was a lot of Sturman Drung about Angular 2.0. But a big thing that happened was that we originally announced this, and we got a lot of feedback, which is great. A big thing that I care a lot about is that when I work on ember, I'm not working on ember as myself, and then there's a separate community that is working on ember stuff with me. I basically work in the same space as everybody else. And I happen to work at Tilda, and some other members of the core team happen to work at Yahoo or Yap or LinkedIn. But we all work in the same public space. And that actually comes out of having a large number of people at different companies trying to coordinate an open source. We really have no choice but to work in the same public space, which is GitHub. And that's great. I think I love it. I love that. So we announced this. We got a lot of feedback. Probably the biggest points of feedback came from the fact that at the time, we knew we wanted to get rid of views and controllers, but we only had a path-baked idea of how to do it. And we also knew we wanted to drop IE8, which I'll talk about more later. And that, of course, brought out a lot of people who, literally all the people who still relied on IE8 probably replied on the thread, which is fair. I think that was a fair discussion. Because the IE8 thing became so controversial, we actually separated out into another RFC just to talk about IE8. So this was actually great RFC. Usually when we say we're going to get rid of views or controllers, we kind of know because the core team has a lot of different types of people on it, what kinds of things are being used. But of course, if you say we're going to drop a feature, you learn about ways people are using things that you had not thought of. So this was a great starting point. There were a number of things that we did over the course of the Ember 2.0 process. So after we merged, I wrote a blog post that transitioned to Ember 2.0 in detail where I was actually saying today I looked back at the high level and we didn't actually do that, the second one, Ember 2.0.13 will ship with support for angle bracket components. But we did actually do all the other things on this list. So yeah, we didn't get all the things, but we basically kind of do what we were doing. And this thing here talks about all the things that had to do with Ember 2.0 and transitioning to Ember 2.0 as a 1.13 app that we knew on May 10, 2015, which by the way is also my birthday. So I was busy that day, I guess. I also posted another post, Ember 2.0 X status update on May 24. And at this point, we kind of noticed, we knew already that we were probably going to miss a few things that we thought we might hit. That sort of talked about it. We also at this point realized that there was a high probability that we were going to have to maintain 1.13 for a while after 2.0 because of the likelihood of breakage and people being on 1.13 for longer than we hoped. So we started talking about that. And this blog post talks about the fact that we were planning on removing a lot of stuff and the removals were really the high order bit of Ember 2.0, not any new features. And then finally, I wrote this blog post on June 16, which basically said, I talked about something in my keynote, EmberConf. Actually, the EmberConf keynote happened in between the RSC and this, which is basically me repeating what we already knew about Ember 2.0 at that point and also introducing Glimmer. So at this point, I repeated what we had said before because it was clear to me that it was not getting absorbed fully, which is basically that there are five things that Ember in 2.x will be. Ember CLI is effectively the primary entry point into Ember. This transition has not actually finished yet. So if you're an Ember user now, Ember CLI being Ember has not finished. But for example, if you gem install rails in the Rails ecosystem or MPM install sales or whatever you would do, dash G, what that does is it brings along a lot of stuff. And Ember historically has been split between Ember.js, Ember data.js, maybe some other stuff. And Ember CLI was a separate project. So one of the goals for the Ember 2.x, which I'll get to more later, is that the main entry point probably starting in a release or two or still working out the kinks will be Ember CLI. So you'll install, if you want Ember 2.4, you'll say MPM install Ember CLI at 2.4 dash G. And you'll also be allowed to use Ember 2.4 in your package.json. And you'll get the right version of Ember. So in other words, just like in Rails, you don't necessarily know what version of iRubus happens to be used. You might not know exactly what version of what has since become Ember collection is being used or what version of liquid fire, but you'll think about it as a package that comes with a bunch of stuff. And this actually is maybe one of the highest priorities for me personally. So stuff we actually did. It's also, if you've been around for a long time, easy to forget the path here. But Ember 1.0 shipped with a string-based templating engine. String-based templating engine involved a lot of hacks, most notably metamorph script tags for the entire time from 1.0 to 1.7 to do at a high level what we always want to do, which is have a templating engine with some embedded expressions and you run it. And then when anything changes, you update it, which is at a high level what literally every framework is trying to do. But we use a string-based templating engine at 1.0 because when we shipped in the first place, templating engines weren't necessarily. We know a lot more now. So in 1.8, we eliminated metamorph script tags and we shipped a thing called Metal Views. And really the main benefit of Metal Views was SVG support, actually. So we were able to write SVG because of course, you're using inner HTML, you can get SVG, but you couldn't have like an SVG component. We shipped HTML bars in 1.10 and basically that was probably the biggest change since 1.0. Interestingly, if you were a person who used 1.10, you probably didn't notice a large amount of breakage even though we completely swapped out the templating engine under the hood. So even though in 1.9, we were using a string-based templating engine and in 1.10, we switched to a DOM-based templating engine, there was no compatibility breakage at that point or extremely little. We also shipped block brands, which hopefully as an Ember user in September 2015 is a feature you have used or like to use. We also shipped a feature that maybe you don't use but you should, which is if you have a bunch of if-else statements, you can use like the JavaScript else-if syntax. So you can say if something and then you can say else-if something else-else something else slash if. Shipped services, 1.11, because we had shipped HTML bars in 1.10, we allowed you to say something like ahref equals curlies to put in ahref, which, frustrating, that was not possible until then effectively eliminated by that bind adder as a requirement. Also, 1.11 shipped the component helper, which let you say I would like a component but the name of it is not known-is not known until runtime. 1.12, we started working on fastboot and 1.13, we landed glimmer. So there was a pretty big path in the 1.X series in which we added a lot of features and didn't break a lot of things. And interestingly, also during this entire period, we deprecated a lot of things. And I'll talk about deprecations in a bit. But until here, after 1.13, those deprecations did not come to fruition, none of the deprecated features broke. We missed a couple things that we wanted, angle-wracking components and ratable components. Both of those features are features that got a lot of hype and will matter a lot, but we missed. Why did we miss it? I'll come back to this later, but the short answer to why we missed it is POTS. I'll come back to why that is much later. OK, so what was the highest 2.0 priority for everyone on the core team? The highest priority was migration. A big reason for that is that all of us on the core team have apps. So Tilda has Skylight. It's an Ember 1.x app. We do not want Skylight to be stuck on 1.13. Steph works at Yahoo. They have a whole bunch of Ember 1.x apps. They do not want to be stuck on Ember 1.x. A bunch of people working in consulting companies, all of them do not want to be stuck on 1.x. So for us, the highest priority over all other priorities was migration. You may or may not be familiar with these. If you happen to have an app that is still on 1.x, I would recommend becoming familiar with these things. And we talked about them in the blog post. So first of all, Ember CLI deprecation workflow. The idea behind this is that deprecations are a thing that can manifest in many different ways. And if they manifest as a thousand messages to your console, you will probably be very angry at them. And also, you will not have any good way of dealing with them. And so Ember CLI deprecation workflow allows you to effectively work through deprecations and say in your project which deprecations you think you have already worked through and which ones you would like to ignore. That allows you to schedule in whatever sprint you feel like. I would like to eliminate these deprecations. This deprecation, or these five deprecations, work through them. And then once they're done, you can seal them and move on to the next one. It's a nice thing. So that's a way to silence them. This for me was actually even more important, which was if we're going to have a lot of deprecations, it would be nice if they didn't go into your console because you're probably using your console for other stuff. This actually landed a long time ago, but you have to actually have the inspector open to see it. There's just deprecations pain that tells you what's up. We started, every deprecation in Ember has a unique identifier. So the string that gets printed out may be contextual. It may say something about what you're trying to do. But there's always a unique identifier. There's a URL that is attached to it that says what deprecation is and transition plan. So you can see there that it says you can click on transition plan. It will tell you the transition plan for that particular deprecation. You can see the trace in the console. And actually using the deprecation workflow and the inspector together is pretty nice. You basically get a quick checklist of the deprecations you felt like working on. It doesn't clog up your console and everything is grouped together with traces. So I think deprecations were a source of some frustration, but I think a large part of that was that pace at which we rolled out these things did not exactly match the pace at which we rolled out deprecations. I want to say another thing, which is that deprecations are not the enemy. In the 1.13 period, because of the fact that we had so many deprecations that resulted in removals, people got the end because of the console spew. People got very email at deprecations. And in fact, towards the end of the 1.13 series, we got a number of people submitting RFCs or other requests that we should slow down the pace of deprecations into .x. So please do not deprecate things so fast. And what I would say to that is that deprecations themselves are not the enemy. In fact, if we're not about to remove something, you still would like to know as soon as possible whether that we're planning at some point in the far future on removing it. And to the extent that you don't have to see it in your console because you're using every deprecation workflow slash the inspector, and we're not planning on removing it any time soon, you'd rather know sooner rather than later. It doesn't help you for us to defer the point at which we start emitting the deprecation warning. But because of the fact that deprecations were noisy and annoying and coupled with a bunch of removals very soon, I think people got the idea that deprecations are the enemy. And I would say deprecations are good. You should like deprecations. You should be sad about removal, but you should like deprecations. OK, so what? So ember1.x had a release process that I still think is pretty great. Rust has the same release process, and it was derived from Chrome. And the idea is that there's a six-week release cycle. The six-week release cycle is additive only, so we don't delete things in every six-week release. It's not like six-week major releases. They're six-week sembr releases. And people can upgrade at their leisure, et cetera. However, if you read this, I wrote this RFC May 21st. It's a busy month, I guess. I wrote this RFC in May 21st. And the goal of this RFC was basically to say there are some issues with the six-week release cycle that require some refinement. So it starts off roughly by saying the six-week release cycle is great. In fact, I think a lot of people who are used to much longer release cycles, like enterprise people, get the idea that six-week release cycles are dangerous. They increase risk. But there's actually a reason that Chrome and Firefox do six-week release cycles, even though they're shipping a production browser. And that's because six-week release cycles actually reduce risk. It's like continuous deployment. And intuitively, it feels like continuous deployment increases risk because you're shipping all the time. But in fact, what continuous deployment does is it exposes your product to your customers as fast as possible so you can get feedback as fast as possible. And because you're shipping a lot, it gives you the ability to fix things fast. So you ship something. If there's a regression, you can fix it tomorrow if you're doing continuous deployment. If you're doing releases every six months and you ship something, it might be a large process. Because maybe there was like a, I don't know how many people here have worked at companies with long-release processes. But maybe there's like a release manager, an Excel spreadsheet, and a freezing period, and QA that comes along with that. So even though it seems like the long release cycles reduce risk, they actually increase it dramatically. And they increase it dramatically, especially as you start heading towards the end of a release cycle. Because then people become very obsessed with cramming things into the end of a release process. Again, I've worked at places like this. And the consequences that the features that get crammed in at the end are extremely risky and hard to fix. So the nice thing about six-week releases, especially when they're accompanied with feature flags. In other words, everybody works on master. And there's just some feature flags that you can use to strip them out from the production builds, which is basically how continuous deployment works. It decreases risk dramatically. And it has done that for Ember. I've worked on many open source projects. And the six-week release cycle, both in Ember and Rust, really, really reduced the sense of urgency around releases and also the risk, people's risk tolerance. People's risk tolerance is actually much lower when there's a lot of releases. People, a common refrain is there will be another train, wait for the next train. But there's a problem, which is that not everybody can upgrade every six weeks. We try to make it pretty seamless, but it still requires scheduling and upgrading and things like that. And especially if there is, for some reason, even though we follow Sember, I'll get to this in a second, there are some releases that can still break your app for some reason, which I'll get to in a second. So not everyone can upgrade every six weeks. Now, when I first heard of this issue, like I know about it, I said, well, that's not really a problem because you can just upgrade whenever. So if you don't want to upgrade from 1.10 to 1.11, fine. You can just upgrade every even release or you can upgrade every four releases. That's fine. It's Sember, so it should work. But there's a bit of an issue, which is that the ecosystem has to sync up. So if you're an add-on author, you have to know what releases to support. You probably do not want to support if you're up to 1.10, literally every release since 1.0. That would be very annoying. So in practice, add-on authors tend to support a relatively small number of leading edge releases. And because people who are conservative are on a variety of different releases, it's very hard for add-on authors to know what to target. It's hard for the ecosystems to know what to target. It's hard to know when we can upgrade the inspector. So one of the goals behind LTS releases, which is an open RSE that will probably merge soon, is just to give conservative people who don't want to upgrade every six weeks some release that they can stay on that is synchronized. So everyone, let's say 2.4 is a LTS release. What that means is that if we're up to 2.7, add-on authors and people building tools for Ember and whatever know that 2.4 is still a popular release. And when 2.8 happens, probably 2.4 is still a popular release and maybe like once 2.10 happens, 2.4 is no longer a popular release. But that gives everybody a sense of a particular cadence of not just six-week release cycles, but also release cycles for more conservative folks. Now, there is an issue that is related. I said maybe upgrading from 2.9 to 2.10 may break your app. How can that happen? Well, what happens is that JavaScript is a very dynamic language with very hard ability to control private APIs. And so we have a term that we use in Ember Core called intimate APIs. And the idea is these are APIs that are private, but the community is very intimate with them. And this may happen because maybe a very popular add-on like LiquidFire uses them. Or it may happen just because there's a particular problem that is hard to solve with Ember and people use the private APIs to get around it. And there's a popular Stack Overflow answer that tells you to do it. And a thing I learned, DHH convinced me of this like five years ago or something. This is not a bad thing, actually. If you're in a language where everything is final and you can't escape, then if you get stuck, you're stuck. Game over. But in a language with more ability to be porous, you can fight your way out of problems. But it has the cost of maybe your stuff will break. So we've always had the policy that if we happen to know that a particular private API that we are breaking is heavily used for some reason, like a lot of the container APIs is private, but we tend to try to avoid breaking it because it's intimate. If we need to break it for some reason, we've had the policy in the entire 1x series that there's always has to be at least two releases in between the time that we deprecate and the time we remove it. So this is not, again, this is not a semver violation because these APIs were not part of the publicly documented API, but we try to be helpful anyway. So the way that this entangles with LTS releases is that one of the issues that causes people to not be able to just upgrade every four releases is that because the policy is that we can remove things two releases later, if you jump four releases ahead, you might miss a deprecation. So this is really the only interesting policy change about the LTS release plan. And the other thing is ecosystem syncing, but that's not really a policy change, is let's imagine that 2.4 is an LTS release. May or may not be. 2.5 may come out and then 2.6 may come out and maybe in 2.6 we discover that there is a intimate API that we would like to deprecate. In the presence of LTS releases, we cannot actually remove it in 2.8, which is when we would have removed it in previous, in the 1.x series. Instead what happens is we have to wait until the next LTS release and the idea is that there is an API that was heavily used privately in 2.4, so 2.8 people need to receive a deprecation warning because they basically skipped over the entire thing in the middle. So now they're landing on 2.8, now they're gonna get that deprecation warning that we added in 2.6, which means we can remove it in 2.9. But the point of the LTS releases is to give us a framework for thinking about this kind of problem. So the idea is now you know that you can jump all the way over four releases and not fear that maybe we deprecated a heavily used private API. Also means that add-ons have the same story. Add-ons that are heavily using private APIs know exactly the lifetime that they can continue supporting and it matches people who are more conservative. In practice, EmberData and LiquidFire, because they made too much use of private APIs, are two that are upgrade blockers. Both EmberData and LiquidFire have spent a lot of time recently trying to contain the amount of private APIs that they're using to bring it down to a very small amount. But one of the major goals of 2.x is actually to reduce reliance on private APIs period. And what that effectively means is that we want to have add-on APIs for all the things that we know add-ons are doing. This is sort of a similar story to Stack Overflow tells you to do a weird thing. In the 1.x series, it's pretty hard to prioritize getting good plug-in APIs when there's still pretty bad issues with the public APIs. But now that we've gotten to 2.0 and a lot of the public API issues have been ironed out, we want to make sure that LiquidFire and EmberData and other popular add-ons that are doing stuff that rely on private APIs have an ability to not rely on private APIs and be more stable and effectively opt back into December, which seems good. And that's something Edward has been doing a lot of and it's something that Igor and I and Tom have been doing a lot of in EmberData just basically getting things stable. A sort of related thing, and I talked about this earlier, is a major goal of Ember2.x is Ember as a suite of things and the idea basically is that NPM install Ember, which by the way we have access, we have but we haven't used for anything, is that's the thing that has the important version on it. So when you're installing Ember2.3, NPM install Ember is how you get it and it has a bunch of stuff inside of it that have versions that you don't have to care that much about like I said, like Rails has E-rubus and Sprockets and whatever and you don't really care about the exact versions of those things, but you know that you're using Rails for. One of the great things about this is that when the vast majority of people are in the same version of everything, it's a lot easier if someone goes to Stack Overflow and says I'm trying to use LiquidFire with Ember, LiquidFire and Ember2.4 and it's broken in this way, you don't have to play 20 questions to figure out what combination of versions of everything they happen to be using. So for things that we know that are basically ubiquitous around among the Ember community, we've decided effectively to integration test the combination so that people can generally assume that if somebody's asking a question about a particular version of Ember, they are using a particular version of all the dependencies as well. And this is definitely something that causes pretty severe issues in all ecosystems where people just you mix and match libraries with the bend. I should also point out that the goal of this is not to make it impossible for LiquidFire 2.5 to work with Ember 2.4 or something like that. The goal is just to say that that will work for some combination of versions. The goal is more just to make sure that there's a general cluster of them that people are using and that there's a version number attached to it. Okay, cruft versus compatibility is another big issue. What I mean here is that Semver requires that you maintain compatibility across minor releases. But maintaining compatibility requires maintaining cruft. And generally speaking, people don't like cruft so there's a pressure to increment the major version. This was definitely a big thing for us in 2.0. We want to get rid of cruft, so we had to increment the version. And we treated 2.0 as a GC pass, basically kill a bunch of cruft. And for 1.x that was actually pretty good because we had a lot of a holdover cruft from pre 1.0 that was good to remove. But generally speaking, it's possible to isolate the cruft for things that are increasingly obsolete inside of your code base. The thing that's annoying for Ember about this and the thing that produces attention is that it is annoying for people who are not using those features to have to pay for them. And one of the goals of 2.x is to reduce the tension there via a thing called spelt releases. And the basic idea here is that deprecations will become effectively reverse feature flags. So every deprecation will isolate the area of code that it's talking about in the same way feature flags do. And you will be able to ask Ember CLI to build you a version of Ember without some set of deprecations. Probably you'll refer to it as the set of deprecations as of some release. So you'll say, okay, I actually started this project in 2.4. You don't need to give me any features that were deprecated before 2.4. Obviously we can't remove them from the public build or any of the defaults for semantic versioning reasons, but it's good for you to be allowed to ask for that to remove the cruft. And that allows people to basically GC their own cruft and hopefully will allow us to take a longer time before we feel the need to do it globally. Of course it's important to note that if you are removing features, they will probably, some add-ons will probably not break if they rely on them, but hopefully the existence of spelt builds will cause add-ons to try to support non-deprecated features. Also important to note, if you have a particular deprecated feature removed, we will probably leave the deprecated feature around in debug mode with an exception. So if you encounter a deprecated feature will not just like randomly fail, in debug mode you'll see an exception that says, hey, you said you didn't want this feature and yet you are using it. Seems bad. And sort of related to this is that ES6 modules provide a pretty good host for dead code elimination. If you didn't import a module, we don't need it. And this is a little bit further away, but we're planning on trying to leverage the fact that you have to explicitly import things that you want to allow us to purge a lot of stuff from Ember that you didn't happen to ask for. It's a little trickier than it looks because things like the application pull in a lot of stuff. So there may be places where we have to use the spelt build conditional trick instead of ES6 module trick. Maybe you're not importing something explicitly and the framework is doing it for you, but I think there's a good path for ES6 modules being a way to discover what things you need to include in your build. Okay, so that was the high priority. The high priority was getting us to a point where everybody's transitioned. Everyone's on 2.0. Everything is good. The second priority for 2.0 was to make a better foundation for 2.x and beyond. And there were actually only a few things here, but they ended up having a pretty big impact. The first thing is ES5. So ES3, so the story of JavaScript is that Brendan wrote JavaScript in a week or 10 days or whatever the origin story is there. And then they shipped it and it was in Netscape and Microsoft did Jscript and blah, blah, blah. And it got standardized. And ES3 was effectively the end, at the end of the browser wars when Microsoft won, they standardized what would become the version of JavaScript that was everywhere. That was ES3. And that happened in like probably 1998 or 1999, something like that. I should know that. And that version of JavaScript had very little features. It was effectively just like all objects are dictionaries and maybe we added exception, so that's great, but that's about it. It's amazing. Dave Herman said to me last week, I was with him at T-Stereo and he runs Mozilla Research. He said ES3 was a thought experiment of what if we gave the world the lambda calculus and said go. And that's really what it is. There's very little features, but you have anonymous functions and that gets you a long way. Well, let's see you write async stuff too. But ES5 cleaned up a lot of stuff and importantly added some critical reflection capabilities with things like objects that define property and that whole suite of tools, strict mode also. And that stuff matters. And it's very difficult to move forward without it. We end up with things like mandatory.gen and .set because we can't use getters and setters, even though they've existed in the language since 2009, so we really wanted to move forward. But there's actually even a better reason, which is that ES6, there's a few features like proxies in ES6 that you literally cannot polyfill or transpile, it's impossible because proxies let you intercept any get operation or set operation in the entire language. But almost the entire ES6, almost all of it, is just sugar on top of stuff you could already have done in ES5. However, it is not sugar on top of stuff you could have already done in ES3. Which means that if you want to use Babel and you want it to give you a good experience, you really do need to be building on top of ES5. So had we decided to maintain support for IE8, which support only has ES3, what that would have meant is that we could not have used a lot of Babel. And we talked about that in the RC, but of course people who really, really need to support IE8 are willing to accept a lot of pain and trade-offs. So ES6 plus for us, ES6 and beyond is a very important thing for us. For me, I'm on T39. And dropping IE8 as a result was of critical importance. Also importantly is that views, which were the core primitive that we copied from Sproutcore. So Sproutcore had a thing called views. So Ember0.x had a thing called views. Ember1.0 also had a thing called views. But we, I was trying, already at 1.0, if you look at the public API, I had started to try to push components. And the reason for that is that components are effectively views, if you are a 1.0 user, with better scoping, like just, that's the only difference, better scoping. However, for all manner of reasons, people got addicted to views with mostly without any strong, compelling reason why it was needed, but a lot of people used them. And unfortunately that worldview, the specifically the bad scoping part of it, infected a lot of internals of Ember. So basically anything that had to do with components had to say, what if I happen to be a view? Maybe there's weird scoping rules here. Maybe the user, an example of this is, any view is allowed to set a context property, which says instead of using this thing as the context, instead use this completely other object. And we already had width in Ember1.0. So this is a completely unnecessary, but it was used, which meant that every single part of the Ember internals that might be talking about a view at all has to worry about this context thing. And the magic controller keyword, which could be like if you say width controller equals, or there were many, many constructs that allow you to interject controllers. And controllers did things like capture actions. So basically all this crazy scoping stuff that was inherited from SproutCore was really painful in the internals. And it was really painful for the programming model too, because it meant we could never say with complete confidence to a user, if you are inside of this context, here's what is in scope, which is a nice thing to be able to, so handlebars is basically a programming language, a little one, and it's a nice thing to be able to say, I'm looking at your template and here's what is in scope. But basically handlebars was like ES3, where people using the width keyword a lot, you could basically never know what was in scope. And that was bad. So 2.0x eliminated views for all those reasons, but we made sure that basically all the existing semantics work in an add-on. So if you happen to be using the view keyword anywhere, or the view helper, or a controller equals, there are add-ons that you can use that will bring the semantics back. And we promised to maintain support for them until 2.6 at the earliest. But we will see how much people need it. I'm hoping to not need to support it much after that. But it depends. Generally speaking, when I say all this, what I mean is, if it turns out that people heavily use it, we will keep supporting it. But please don't. By the way, one thing that happens with add-ons is that people use an add-on, like LiquidFire or something, and they try to upgrade and the upgrade fails, and they get angry at either LiquidFire or Ember or the ecosystem or something like that. But add-ons are actually a pretty awesome buffer between you and private APIs. What I mean by that is, LiquidFire actually does not expose any private APIs to you. It exposes its own public API, and it uses private APIs under the hood. What that means is that when you upgrade to Ember 2.2 and LiquidFire breaks, you do not need to update your app. All you need to do is wait for Edward to upgrade LiquidFire for Ember 2.2, and then your app keeps running with the exact same code. Now, obviously it would be better if people did not use private APIs. But that strategy is much better than you copying and pasting a private API from Stack Overflow and putting it in your app. Because that means that when we upgrade to Ember 2.2, you have to figure out what the answer is, and that's probably harder for you to do than for Edward. So add-ons are actually a great buffer. Again, I think it's good for us to reduce reliance on private APIs, but to the extent that they are in use, it is better if they are encapsulated in an add-on with a public API than if people are just using them directly. And so you should be happy if you're using an add-on that gives you powerful capabilities that you want. You should be happier that they give you that public API and the breakage is contained by them releasing a new version than if you just did it yourself. OK, I'm closing in here. I hear a lot that the web is changing a lot. Look at the web. Like in the last 10 years, it has wildly changed. It's a completely different thing. So obviously that means that we need to rewrite our frameworks every year to take advantage of that. This is not an excuse, but actually the reason it's not an excuse is a ridiculous thing. Not a ridiculous thing, but it's ridiculous that people say this, because I'm on a bunch of standards bodies and don't break the web is the only constraint that we have. The only rule that we have to follow for sure is that we can't break last year's code, which means that you have no excuse whatsoever. If somebody ever tells you, I have to rewrite my framework or I have to use a new framework because the old web is no longer here. It has changed. Everything has wildly changed. That is just not true. Famously, the Space Jam website, which was produced in 1995, still runs on Chrome right now. I suspect it's like in integration test suites, in browsers. That's amazing. Yes, it is. And it is amazing and also a true thing that exists. So we are not forced to rewrite our frameworks and break compatibility because the web is broken. In fact, the opposite is true. The web has done us a great favor, a much greater favor than, for example, Coco, which is that the web has promised to basically never break anything. It's not 0% very, very rarely. There's a great thread on the bugzilla where they remove the Moz prefix. There's a very prefix, Moz opacity. And someone is like 100 comments where he said, you are basically destroying my livelihood. I have to manually go modify hundreds of websites. And it's very crazy. But there are, with rare exception, things that worked five years ago work now. Except if you're using explicitly marked experimental features. And so there's no real reason why people need to rewrite their frameworks or their apps because the web has added new features. The web is additive. You can take advantage of the new features without breaking everything. OK, 2.x. So now that I've said how 2.0 went, what's coming to the next? Actually, there's a bunch of stuff. Pods, I'll go into more detail in a second. Engines are coming. But I would like to issue a warning, which is that I think engines has become a word that is symbolic. It's like a monolith. Everybody has poured their heart and soul into what they want it to mean. It probably will not mean exactly the thing that you want it to mean. But it will mean that you are able to make isolated applications that you can mount inside of other applications. And that set of things that you can do with them will get better over time. So engines are coming. Radable components are coming. In a second, I'll talk about why they really required pods. Angle bracket components are coming. This one is really exciting to me. So I've been working on modules for years and also decorators for years. And I'm excited. Decorators are moving along. And they'll probably be in not in ES 2016 because ES 2016's deadline is like a month away or something. But they'll probably be in ES 2017. They're already in Babel. And they allow you to do a lot of cool stuff. And I think Ember will probably take advantage of them starting pretty soon along with a process in the 2.x series of allowing you to slowly migrate towards ES6 classes with decorators and fields and things like that. So that's cool. A teary goodbye to controllers. What I mean by that is that controllers are hanging on by a thread. They're on life support. They are still needed for query parameters and communicating with your routes. That is literally the only reason they still exist. The only reason we could not deprecate them and remove them in 2.0 and tell you to point out a plug-in. Because there are two things that you still need them for in 2.0 world. And what routable components and other things will eliminate the need for them to exist as a mandatory part of the programming model. So we will not remove them because we will not be able to do that until 3.0. And that may not come extremely soon. But there will come a day where controllers are not a part of the mandatory programming model. And that is exciting to me. Pods. Hey, what happened here? No. Ah, fuck it. I give up. OK. So pods. The basic idea behind pods is that the directory structure, instead of being a flat top-level global directory structure with types that nest things inside of them, will basically be structured in terms of your application structure. And what that effectively means is that every point in the hierarchy will look like every other point in the hierarchy just nested. And so another important thing, which is that every template will be allowed to have helper components and helper helpers. And effectively, if you nest something inside of a components directory and nested under yourself, you are allowed to refer to that directly. So instead of everything always being global all the time and having to use slashers like that to organize your code, if something is just local to you, you can just put it local to you and it will win. And this is like if you're writing a JavaScript file, you can write local functions. And you don't have to make modules for those. You can just write local functions as helpers. And this process is recursive just like in JavaScript. If you wrote a local function, it can also have local functions. So this is basically the same thing but just using the file system. At the top level, there's components. So you can have global components. And the same story applies. Hilarious. Anybody can refer to top level components. And components themselves can refer to things that are nested inside of them locally. I was at Intercom in Dublin a couple of weeks ago. And I did an exercise with them where they have hundreds of components. We went through all of their hundreds of components, looked at every single component that had a slash in it, and tried to figure out I had a hypothesis that literally every component that had a slash in it or almost all of them would be always the thing that, like if you said food slash bar slash bad as a component name, that would always be called from food slash bar. And that was actually true. We went through all their components, and that was true about all their components. You're either referring to a global thing, or if you're using slash, you're always referring to something nested inside of yourself. So this basically allows, makes that the convention. You can always put some components directly inside of you, and that works. Also makes testing much nicer. So pods, the key thing is that they're a repeating pattern. So at any point in the structure, you can jump five levels deep, and the thing you're looking at is the same as any other part of the structure. There is effectively an existing environmental model, which is like, here are some routes. They're nested inside of other routes. I have some components. They're nested inside of other components. They're nested inside this route. That's the thing that exists in the environmental model, but it doesn't really match today's directory structure. And pods fix that. It makes it really easy to relocate entire areas. You can just drag a subdirectory somewhere else, because it's all nested locally, it will all continue to work perfectly. Gives you a simple file system scoping for helper components. You can just put a component here and not have to worry about how it breaks everything else. And the same rules apply for all types. So there's always global names that you can talk about, but there's always a local, you can always override the global name with a local name, like again, JavaScript scoping. Part of this is add-on namespacing. So add-on namespacing is basically ability to use add-on stuff without it polluting the global namespace. So today, every time you use an add-on, it has to smash things to the global names. So if you have five add-ons or 10 add-ons or 20 add-ons, maybe some of them conflict. Maybe they conflict with your local names. They may conflict with local variable names that are on your component, right? And that's pretty bad. So this is basically a way of getting namespacing. Here's a slightly more advanced example that uses a bunch of features that are in the pipeline. But if you use Rails, you basically know what this means, if not, whatever. Like, basically it's cool and you'll learn it then. But the basic idea here is that you're able to build like significantly more rich packages of components with behavior and without breaking the global name. The basic idea here is that, so unfortunately, global namespace coordination is a hard problem, very hard problem. And decentralized namespace coordination is incredibly hard, maybe impossible. Good news is we have already agreed to do some kind of global namespace coordination, which is our MPM package names. So we can just say that our namespaces are the same as your MPM package name and then you automatically get the namespace coordination that is very hard to engineer. And so, yeah, this basically means that you can reliably say like some name, colon, colon, something else and you know that it's referring to a specific thing. This applies to anything in add-on. So I don't know if people have written here, have written add-ons, but when you write an add-on, you have two directors, you have app and add-on. And add-on today is kind of anemic because it's hard to get access to stuff inside it without going through a bunch of imports and JavaScript stuff. The idea here is that if you put stuff inside of add-on, it works exactly like app except this namespace. So you have to use the add-ons namespace, but now it's very easy to get access to it and it leaves the app directory inside of your add-on for global. So just like, I could say to you, like everyone chooses modules in JavaScript, but occasionally you need a global variable for some reason and it's good that you are still allowed to do that. Basically app slash star star. So Ember itself, for example, comes with a bunch of components like select and input and that's when Ember itself becomes organized as an add-on, which is happening soon, Ember will put its own stuff inside of app and like add-ons are allowed to do that, but probably should do it with great care. Pods stage the engine feature. So the engine feature is basically, it doesn't really make sense to have an engine feature that lets you mount a whole section of things without pods because then people will end up using engines which have a lot more isolation than you really need just to model pods and you'll probably end up with a lot of people using engines for things that are unnecessary. So engines are being actively worked on but it's good to have the features together so people don't end up using a very, very isolated model unnecessarily. And I promised I'd come back to this. Pods stage routable components and the reason for this is that if you try to figure out how to describe routable components in today's world, there are a lot of file system conflict problems. So you might already have a component called article or imagine your route is named article, like my article, you may already have a component named that. So it's hard for us to figure out do you mean a component here or do you mean a route? There's a lot of other related issues like that. Now these issues are solvable, we could in theory solve them but the much better solution is to just do what I showed before, which is that your routable component is just a couple of files in your route directory. We could actually also do a hybrid model today where just the routable components went inside your route directory. But and we'll probably do some variant of all this once we have pods for transitioning purposes. But we really did want to figure out the full story in a world where that is where the directory structure will end up for real. So I think there was a hesitancy, hesitance to land routable components in a world with suboptimal. Yep, wrapping up. Almost there, I have like four more slides. There's a hesitance to land it when we knew that there would be a lot of compromises that would be easier to understand with pods. So it's coming. Glimmer two, coming soon. I actually haven't talked about this at all before public except on the Intercom video that you should watch if you're interested. It's like pretty long and detailed and boring but might be a- You're selling it. Totally selling it. Okay, so Glimmer one, the goal of Glimmer one was fast re-render. And we did that. Unfortunately, one of the consequences was that we got slower render. So, and this is especially unfortunate because what fast re-render effectively means is that if you have an array of 50 items in it and you have the arrays already in the DOM and you want to sort it and put the new array in the DOM, that will be fast. And that's a great thing to be allowed to do because arrays are common and it's very hard to use replace or whatever APIs that you have to use to teach Ember what you're doing to do things like a sort. It's very complicated. So, it's good to be able to do that. Unfortunately, the consequence of Glimmer one was that initial render got slower. In 2013, much slower. We're getting closer to the original performance profile but it's still slower. Basically, the goal of Glimmer two is fast initial render and fast re-render and we're working on it. Godfrey's working on it with me and hopefully it will be done soon. And it's a pretty big change. You should check out the video like I said if you want to understand why. The TLDR is append mode. The TLDR is that when you're appending into the DOM it's a totally different thing than when you're updating the DOM but Glimmer one forces appends to act like updates which means we have to put a bunch of stuff in the DOM just to get updated. It's because of some vagaries of how the implementation worked and Glimmer two has a separated faster append mode. That should be much faster. So, that's coming soon. Check it out and I'm done. Thank you.