Few seats left for our Advanced Backstage Plugin Development workshop on December 7th. Secure your seat today!
CHARLES: Hello, everybody and welcome to The Frontside Podcast, Episode 75. My name is Charles Lowell, a developer here at The Frontside and your podcast host-in-training. This is a little bit of a diamond anniversary episode, I guess -- #75 -- so it's going to be good. With me today is Jeffrey Cherewaty. Hello, Jeffrey.
CHARLES: To celebrate our 75th diamond jubilee, we have with us a very special guest who I like to refer to as the Eye of Sauron when it comes to bugs in the Ember community. Mr Robert Jackson, who is a person over at LinkedIn, who does what he think is best. Hello, Robert.
ROBERT: Nice. Howdy, howdy. It's great to be here. Thanks for having me back.
ROBERT: I think, for sure that we, at this point, have a whole tower of Babel going on, with all the things that we're doing. We have a ton of tools at our disposal today that I wish that I had years ago. I think that, unfortunately the law of nice things is that as you get better things, you realize the things that you don't have still. It's like an ever-increasing distance to the Promised Land, if you will. But I think that where we are today is massively night and day better than where we've ever been before. We can do so many things like code mods and transpilation and prod debug style, all sorts of things. For the most part, in the Ember community at least, we try to make that as much like a default out of the box experience as possible.
CHARLES: Just to talk about that land before time, now Ember was one of the first frameworks to really embrace transpilation but also using Babel as the primary tool. What was that experience like? What changes that we have to make in order to hit that?
ROBERT: I think, the Ember itself, the framework itself which is still shrouded in the final global's output which folks used, was one of the first major things to use ES6 modules and at that point, it was before Babel was even like a concept, as far as I know, we started using Traceur. Then we also used the Squarehead written in model transpiler as well and we use [inaudible] for a while and it was great.
As we continue to press on this path, we realized that we wanted nice things in our apps too. We wanted modules. At the time, we're using Ember app kits. This is pre-dates Ember CLI using Ember app kit and the way we got modules was either via [inaudible] pipeline which was a Ruby thing in Ember side or just like some Grunt pre-compilation which roughly just ensured that the modules were evaluated in the right order and people generally actually wrote global style code and just assumed the concatenation order worked. That is super not great. It made for some really gnarly interdependencies that was hard to untangle, I suppose.
CHARLES: When did Babel come in that conversation?
ROBERT: Shortly after we started doing Ember app kit. This was like a project that Stef Penner started. We started doing ES6 modules specifically. At that time we were using Grunt for that and we did modules. I think we used squares ES6 modules transpiler. Then shortly after we started working on Ember CLI itself, like the tool named Ember CLI that you know today, we migrated to a tool called Esperanto from Square's transpiler. Then that was deprecated and we started using Babel.
We have made many hops along the way. I think when we originally introduced Babel into the Ember CLI app pipeline, it was an optional dependency because it was actually quite slow to run Babel across a decent-sized app. It was many orders of magnitude slower with Babel than without. Some folks wanted to optionally opt in to using Babel. That was probably sometime in 2015 so over the years, we slowly started migrating the codebase so that at this point, a Babel is totally required part of Ember CLI built pipeline and we will warn you or something if you don't have.
ROBERT: I don't know that we've always done a great job of this but hopefully, the idea is that we should insulate most Ember users from having to make all these sources themselves. Ideally, we are doing internal things. We expose specific public APIs and in most Ember apps, it could upgrade from amongst these, from Squares transpiler to Esperanto then to Babel, mostly seamlessly. You just drop this thing in or do that thing, just basically add a package to your package JSON and it should work. That's the idea. Hopefully, no one else had to deal with quite the level of shenanigans that I was talking about. Hopefully, there's only a handful of people that remember all the names that I already listed.
CHARLES: I remember them happening but you're right, we were relatively insulated from all of that. I think the hardest part was making the mental leap from global-oriented code over to modular code where every symbol has to be important before you can use it and bridging that chasm, I think was the work that the majority of developers had to do. It was no small task but clearly, it was worth.
I guess the question is obviously, there's a lot of benefits to using ES6 modules but there's other things, because it's a full transpiler, you've got a lot of features like the modules that you can either take or you can leave. How do you decide which ones to turn on by default versus leave off?
ROBERT: The way that Babel itself internally did this in version five of Babel is quite different than what Babel 6 does. In Babel 5, they roughly took the mindset of, "We'll just transpile everything that is past stage two," which is the way they rate things are, like stage two is ready for browser implementing. Stage three is roughly finished and you can consider it stable. By default, Babel in the Babel 5 version era was just trying to transpile everything and you could opt in to special experimental things. Maybe like spread operator or decorators or something like that. That's how Babel 5 works.
Now, on Babel 6, which is the migration we just underwent in Ember community, going from Babel 5 to Babel 6 was a huge leap for us because it turns the whole thing on its head and basically, makes it that each and every transformation you want to use, you have to opt in to manually by adding a plugin. They also add a presets and things like that.
CHARLES: So literally, every transpilation you want to --?
ROBERT: Yeah, exactly. It was a quite huge shift and that's also why it took us so long to upgrade from five to six.
CHARLES: Was the upgrade again pretty transparent for the end user?
ROBERT: If you weren't using experimental features like decorators for example, the upgrade was roughly like yarn, upgrade Ember CLI Babel, done. That was basically the upgrade. Now, there are people that got bit by specific bugs or specific things where maybe they had a custom plugin that they were using. For Babel 5, they would have to upgrade that also.
But by and large, the default out of the box Ember app generated by Ember CLI 2.4, we tested all the way back to 2.4 and make sure that version number CLI Babel worked and for all the versions and hops between 2.4 and 2.13, which is when we finally released it.
CHARLES: About turning this on the head, why was that decision made to make every single transpilation opt in?
ROBERT: I didn't have to see the table at that time with the Babel folks. I'm not quite sure exactly why it was done. All I can say is that the main reason, as I understand it, had to do with plugin ordering and making that you had the ability to much easier opt in and out. For example, the way we migrated to Babel 6 in Ember Land was by using Babel preset in, which is a preset maintained by the Babel folks that essentially takes a list of targets, similar conceptually to auto-prefixer or something and says --
CHARLES: What is auto-prefixer?
ROBERT: Oh, sorry. Auto-prefixer is a thing that will post-process your CSS and add the random browser prefixes based on the list of browsers that you support. In Babel world, this basically means we give Babel preset in and the list of browsers. You might say, IE11+. You might say latest two Chromes, latest two Safari, latest two Edge or something. Firefox too.
You give us this array of what you support and double preset uses an internal database that's also the same thing that powers like, CanIUse.com and it just decides, "What do I need to transpile to target these specific browsers." For example, if you only support browsers that natively support like Promise or something, you might not need to polyfill, for example. That's just a crude example but another one, like arrow functions or classes.
CHARLES: I actually noticed this yesterday because I was on the BabelJS site and I remember, it used to be when you would type something in that left pane, your ES6, it would always generate this really nasty thing that boiled down to prototype code where you're manually adding methods and stuff to prototypes, sometimes using to find property and what have you. But I noticed yesterday, I would enter in a class and it would just be a class over on the right. It didn't touch the code at all. It just passed it through. Is that because the preset environment is now the one that they're using to do the transpilation on the demo site, basically is set to the level of browsers that understand class constructs?
ROBERT: Yes. If you can forgive IE11 for a moment, which some of us can, some of us can't, all of the evergreen browsers plus Safari, which I don't think is evergreen, all support class and error functions, they all support a huge swath of ES6, out of the box, by default. If you're only have to support like Edge, Chrome, Firefox and Safari -- maybe Opera, I don't know -- then you can like transpile way less stuff. You can use native classes and the Bebel JS repl, lets you choose what to transpile back to. I don't remember if they're specifically using Babel preset in or not but that's basically the idea, which where you're getting at.
CHARLES: Does that make it faster, because it has to do less work?
The class for example is much smaller by bytes than the prototypal version. It also provide some additional guarantees like you have to call super, for example and things like that. Then in addition, it's just better optimized or has the potential to be better optimized in the browsers than the ES5 version because they can make specific assumptions about the patterns you can follow.
JEFFREY: These are all big architectural decisions that changed how Babel works. How do these changes the workflow for somebody working with Ember CLI, that doesn't have anything particularly custom going on?
ROBERT: Again, the workflow should basically not have changed in any way. A default out of the box Ember CLI app from version, I think Ember CLI 2.12 used a Babel 5 and then, 2.13 started using Babel 6 for the blueprint. Anybody could upgrade add-ons, for example. It can upgrade to Babel 6.
As soon as they were ready and the reason for this was because each layer in the Ember CLI app pipeline is responsible for transpiling its own code that it owns. This is how, for example we were able to upgrade to Babel 6 in a minor version bump because it was essentially opt in only. Again, each add-on, for example got to say, "I will use Babel 6," and then their add-on works and do their tests and all that stuff. But by and large, a normal app should only have to upgrade the one Ember CLI Babel package and then any Babel plugins you might be using and that's it. There shouldn't be any other special shenanigans or hoop jumping that you have to do.
CHARLES: Do you have any, even anecdata, surrounding how much savings you get in terms of payload size?
ROBERT: The problem is that Ember itself still supports IE9, which doesn't have any features of the good things. Also, Uglify has significant problems with ES6 code. We're still struggling through the woods of getting a good set of targets built up. The default set of targets that we include for new Ember app still includes IE9 because that's what Ember supports so in your new Ember app, you would have to edit the config/targets file and just configure how you'd like it. Basically like last two Chrome, last two Firefox, last two Edge --
CHARLES: Let me stop you there because I think you just mentioned something that is of key interest. When you said 'config targets,' does that mean that every Ember application comes with a stock set of targets that's changeable?
ROBERT: Yep, exactly. I wrote a blog post about this, actually at RWJBlue.com. It talks about the targets and how this was introduced and how it works. The default stock set of targets is also listed in there and I have a bunch of tips and tricks about how you can have local development, say on latest Chrome. You can have native generators. You can accept through your Ember-concurrency things and that have to see the wacky regenerator like switch statement. I talked a lot about that in this blog post.
Basically, the config/targets file that is generated by default Ember app today has some list. I think it has four things in it but it includes IE9, that is the oldest thing. It's like the tent-pole, if you will. But if you drop that out, then it's roughly evergreen browsers only and you can target classes and arrow functions and all sorts of stuff, have that actually emitted.
CHARLES: Wow. That's incredible to be able to do that. I know that certainly when it comes to debugging, it is so frustrating to see the mangled concatenated code.
ROBERT: Yes, exactly. The thing that just blew my mind when I first got this working was just being able to step into an async function and just step over, step in as appropriate without having to jump to weird [inaudible] land or weird backburner code, like run loop code. It just works and no regenerator, no extra polyfills. The Promised Land is gorgeous. I don't know however you get there but it is beautiful over there.
CHARLES: Yeah, although I have a question. This has been something that I know has been a challenge when it comes to working, especially people who are beginners. Having the code at runtime, not be in the same form as it is when you're developing it can be a wide cognitive gap that you have to straddle as a developer. Supposedly, source maps are there to help us with that. But I've noticed source maps don't always work and they feel a little bit fragile like if something's not configured quite right, then the whole source map chain breaks down in your back to looking at mangled code and you're like, "I'm not totally free from ES5 because I have to understand how it's compiled down."
A similar situation would be like back in Ruby code or some other language, having to still understand how it'd map down or be able to read out as assembly, even though I don't think it's quite that bad but you still have to hold that mental model and you have to understand what a prototype is. Is there any way to address that? What’s the deal there, I guess? I know that's a really open-ended question but --
Unless you're running minified code locally, you're already out of that zone. Even if you have no Babel, you have no other transpilation, you're almost certainly going to minify. That's already a problem, a chink-in-the-armor of doing both things. Minifying locally during dev is theoretically fine. It's just going to make your life very miserable but it should work technically. There's ways in Ember CLI to do that out of the box like you just set a flag but generally, that's already a thing.
I think, source maps are massively brittle, as you mentioned. It's just slightly wrong thing and when you have a file of like a thousand lines, just having something be a few characters off is quite bad by the time you get to the end. You can easily have a debugger in a place and you think you're stopped at one section but you hover over the symbols or something and they don't show what you expect. Or you're just not in the function you thought you were or something like that.
A great example of this is if you've ever put a debugger in Ember-Twiddle.com and put a debugger in app code in a Twiddle, you'll get a breakpoint and the role that's highlighted is not a debugger line and it's like really [inaudible] so you know that you stop the debugger but because Twiddle does all of the compilation client side in the browser with Babel, then it like evals it essentially, the source maps are totally wacky and you have this exact situation that you're talking about, where it's like I don't know how to reason about what is happening.
CHARLES: You just have to use the console.
ROBERT: In that case, you have to use a console. I think the most common thing for me to see or to tell people is to disable source maps. If you have a thing where you believe source maps might be right or might be wrong, easiest thing to do is disable source maps, refresh and then you're looking at what's actually being evaluated but that's a super sucky answer. That's roughly like, "I have this caching problem. I will just don't cache things." That's not a great answer. You should just fix the bugs.
The issue is that the bugs lie at the feet of, literally every tool in the space. It's really hard. For example, if you Babel before Uglify, are you supposed to give Uglify the input source maps? The answer is yes but Uglify oftentimes doesn't handle input source maps properly so it won't do the right thing. Then there's tools like Sorcery that is essentially a thing that have each step, only do their own source maps from raw code to Babel and then from the Babel-transpired code to minified code and then you give all those source maps to Sorcery and it try to stitch them back together and make them work. That's a really neat tool.
CHARLES: That sounds amazing. It really sounds like the only real solution.
ROBERT: That's the only solution to solve the threading through of all the source maps thing and it actually works quite well. Unfortunately, the problem with that is now you have to track the order of all the things and that's all actually non-trivial. Especially in Ember CLI app or any app of any significant size where you have thousands of files and you're transpiling them, you have to basically keep track of the source and then you concat stages independently. We don't have a good mechanism like back channel, if you will to keep track during the pipeline of what the order of operations are and how to stitch all the source maps back together properly.
But I totally agree that this is not a wonderful place to be and we just need to spend more time to focus. We basically need to do two things. We need to say, "We all agree this is unacceptable and we actually have to be willing to invest time to fix it. It's just too easy to uncheck little check boxes in source maps and move on about my day and it would be better if we just dug in and dealt with it like we would any other bug.
CHARLES: Yeah, I think it's hardest because this one in particular, it hits beginners way harder than everybody else because they don't necessarily have the transpiler mental model.
ROBERT: Well, the other thing is like with lots of things, if it only sporadically works or only sporadically breaks, you just completely destroys any trust you might have had with the thing. Basically, if you test suite mostly passed, how well are you going to feel about deploying? It's like, "It passes eight out of 10 times, it's probably okay." That's not the kind of confidence that you want with these tests. It's the same sort of thing.
If your default answer is, "Well, maybe the bugs [inaudible]. Let me uncheck the thing and refresh." You either should just never use source maps or you should just like fix the damn problem. Figure it out and fix it. The issue is that almost never is the thing I'm trying to work on relate to source maps. The thing I'm trying to work on is some other bug in some other system and I'm like, "Oh, damn," and I just want to beat this out. You end up getting like three yak shaves deep and at some point, you have to declare yak shaving bankruptcy and give up. [inaudible], ah yes. Good. Well, I'm absorbing that one. That's great.
CHARLES: That's called yak overflow.
ROBERT: The thing is if we can only harness the yaks and convince them to build things for us. That could be amazing.
CHARLES: Yeah, each layer is a yak frame. There are could be some burden. If in terms of allocating your developer resources, if you could track the number of the yaks that were required to accomplish each task, you could say this is a really high value yak to kill or to shave, I guess.
ROBERT: We don't kill them, come on. They got to carry our stuff.
CHARLES: Yeah, the land of the future, the Promised Land is wrapped and it's built with [inaudible]. Anyway, moving on. We have a question from Twitter, from one Rob DeLuca. He wants to know about what's going on with Ember decorators and ES6 classes. When are those going to make an appearance in Ember?
ROBERT: Ember decorators is an add-on that I authored roughly forever ago, it seems like but not quite. There's been a lot of work on it lately to update it, to work nicer with Babel 6. We also added support for classes. There's a whole bunch of work going on in the Babel space to update things to the latest spec of decorators. Back when I originally wrote the add-on, this was in the stage one version of decorators spec and a massive amount of things change in the spec around what was allowed, what wasn't allowed. It doesn't change a ton on the user facing side so the way you invoke a decorator was like [inaudible] or something. It's roughly the same. But the internals of how that transpiled, what syntax is allowed and not allowed, that all went through a lot of changes.
CHARLES: Didn't they used to decorate things more than just classes and methods?
ROBERT: Confirmed. Yeah, exactly.
CHARLES: I actually was kind of disappointed that they walked back from that.
ROBERT: I agree, actually. It is slightly unfortunate that you can't decorate like a POJO, for example today or with the current spec. The thing to remember is that it's really important that TC39 take the most conservative approach and iterate forward, especially with this massively shifting technology. Decorators are a big change in the way you think about things. Same as class properties and private fields and all of these things that are coming out of TC39 these days. If we started too broad, I fear we do painted in like a giant corner. Also, as a side, the syntax of decorators is nice but if you just wanted decorate a function, you could just wrap the function and a calling function. It's not that complicated.
CHARLES: Right but that's the same thing. That's just what a decorator is, right?
ROBERT: Except in classes. In classes, it's actually not possible to do that. In classes, the class body, you cannot say, "foo: Ember computed and pass a function." You actually have to have the concise methods syntax. For plain functions, you can easily just wrap it. For classes, you don't have a choice.
CHARLES: Or you have to do what Ember object does, which is just take a hash and then construct the methods by hand.
ROBERT: Yes. Unfortunately, if you do that, then you can't use getters and setters. If you do that, because when you define like 'get space' first name or something, you actually define a getter on that hash, that POJO and Ember object will just eagerly evaluate it when it goes to instantiate your instance. That is definitely not what you wanted. There's all sorts of landmines in there and there definitely are dragons, I promise.
The good news is, I think we're going to a really good place, the Ember decorators add-on was recently renamed for Ember computed decorators and now offers decorators for action. We've had computed and observer and on for quite a while. I think service inject, like control inject but don't do that and things like that. Those all exist as decorators.
CHARLES: Even though the thrust is towards using ES6 classes, under the hood is it still going to be instantiating in Ember object?
ROBERT: The nice thing is that Ember object itself actually just embraces ES5 and you can already imagine like a regular class foo extends bar, already can extend from anything that is a prototype type class as well. Internally, Ember itself like Ember object or Ember component or Ember service or all those things, are basically just prototypal classes so extending from them works exactly the same like normal function foo set prototypes and stuff like that. It's exactly the same as the prototypal version in ES5.
There's an open issue on Ember decorators repo that someone opened just yesterday or two days ago about adding a mixin decorator. Personally, I would prefer to hold off landing that because I want to see how far we can take normal class syntax, like normal class stuff. I think that the next thing that we'll probably need is an RFC in Ember Land to officially embrace using regular classes for these things and explore all the edge cases and stuff that were sort of ferreting out in the add-on.
ROBERT: You should totally be able to do that but I just don't think that we should support Ember.mixin, basically is what I'm saying.
CHARLES: Yeah. I don't think I've ever written a mixin that I didn't come to regret later.
ROBERT: I tend to agree. I would like to ban creation of all new mixins.
CHARLES: Yeah. Anyway. That's a whole another can of worms.
ROBERT: That's another topic. Yes, exactly.
CHARLES: Behind the scenes, we're getting in Ember object essentially, a new Ember object that extends this class, if I understand it correctly that is generated and decorated but it's an ES6 class and then behind the scenes, you get an Ember object that extends it. One of the things that I think is another big challenge is because Ember objects are not regular POJOs, they're really hard to inspect in the debugger. Computer properties are kind of no-go when you use log into the console. Are they going to clean up a little bit of that?
ROBERT: There's a few things. First of all, being able to use plain class syntax means that we can use real getters trivially for the things that we don't need. Some of the magic that Ember computed is doing for us, it's not magic but still it can waive internals. There's use cases that people use computed for, which is roughly that, "I want to lazily do a thing," which isn't really the point of computed but sometimes people don't want to eagerly do. They only want to create some array or something if instantiated, for example. Then they rely on the fact that the computed is cache or [inaudible].
When you do that, you're talking about moving to real getters and if we move to real getters, then all of your normal debug tooling will just work out of the box. I think that's the path but I think there's many stepping stones, if you will. We're going to try to rule it out in small chunks over time so that it's not too hard to digest and we can slowly iterate the way we teach folks the guides and things like that. We have a lot of things to move forward at the same time.
CHARLES: Yeah, I know another thing too is being able to see the actual name of the class in the dev tooling when you're trying to track down memory leaks, when you're logging into the console. Being able to see that if you're using ES6 class say, I've got a class named 'person,' today when you log out of the console, it just says class. Or if you see it in, if you're looking at a heap snapshot, it just says class. But hopefully, we can get to a point where it'll say, 'person,' or it'll say, 'car,' or it will say, 'dog.'
ROBERT: I think that specifically will require some of the target stuff that I was mentioning because it's only going to work when you're actually using classes. I think we're close to the point where many apps already don't have support IE11. As it continues to age out, more and more users drop away and we can start embracing evergreen-only style browsers. Then when we're there, then like it basically everybody supports class. Basically all of them support arrows and async away and all sorts of nice things.
CHARLES: Actually, I think in that particular case, if it's a function, even though it transpiles the class down to a constructor function, the browser will still recognize it because that's something I noticed today when I'm using POJOs and when I'm using Ember objects. The reason it's called class because literally, you say var class when Ember creates the constructor.
ROBERT: But the reason for that is in Ember, in the raw source, it is using the class keyword. It's actually using class but we transpile it down because Ember targets IE9, which transpiles down to wacky-land basically. Once we can use targets, then we can basically remove the extra layer so you're actually using classes, even at the depths of the internals. We would basically not set a variable. It has to be a named class, basically.
CHARLES: You're right. You have to give a name to the class because right now, it's basically because the variable name, it literally is var capital class. That's the name of the class gets in the runtime. There's a lot to look forward to. It's always a dangerous thing to ask people, when can we expect this? I don't want to put any pressure but when do you see these things rolling out? Don’t you love how you always preface a question with, "No, I don't want to put pressure on you, but I'm going to put pressure on you?"
ROBERT: I'll give the stock answer that I always give which is, "You will get it when it is ready and you will be happy about it." But that last bit was more for my kids actually but anyway, I realized that I'm on record here. I think that a good window for this is something like the six-month horizon. Maybe slightly longer. It's hard to say exactly. Like I said, we have to do an RFC. There's a small amount of work has to happen in the Ember internals to unlock a few of the things that the RFC needs to say but the Ember core team has talked about this pretty extensively. We're all generally, obviously want to do the thing. The question is exactly, "How far we go?" And my personal perspective is that we should do small steps like unlocking small parts at a time.
For example, we can go to class syntax and say that it's public API to implement a constructor function, instead of init for example, and say exactly what the semantics are on that and we can do that roughly independently of actually officially embracing specific set of decorators. The decorators are fine to live in add-on space for a period of time. As we mature and figure out which ones are good, which ones do we want, what do we not want, that kind of stuff. I'm a strong advocate of doing the smallest amount of things possible to unlock the feature, unlock the things and then we can iterate forward as we go along.
We're working on updating the guides and making things more idiomatic in API docs. There is a massive amount of literature that exists between the API docs and the guides that will have to be rethought, not always rewritten but we have to make sure that what it's saying is the actual idiomatic 'right thing,' like embraces the language. From my perspective, I think it's very, very important. It's a huge priority because I think, right now one of the things that I hear from folks is the custom object model makes Ember feel like a dinosaur.
Partially because we had to create all of these things before any of these exist in the language. Our dedication to supporting backwards compatibility is really important. We haven't just dropped support for all things. We need to chart a nice path that lets everyone sort of meander forward and upgrade their apps and no one gets stuck on a cliff. I think that's really important to do and do slowly over time in a consistent way.
CHARLES: I think that thoughtfulness is the key to the castle. You aren't just throwing away backwards compatibility and thinking about what is the migration path for everybody. People lose that as being way more valuable than having the hottest thing in your hands and unfortunately, only being burned by that, can make you perceive it.
I think we just need to do a better job of telegraphing our emotions like where we're going, like talking about the direction in a more overall road map-y way in Ember. It's clear, why can't I use classes today or one of the edge cases or things like that. Hopefully, in the next little while, we'll get that RFC up and we can start talking about these things in earnest.
Right now, with the Ember decorators add-on, you can look at the API docs of that. But basically with that add-on, you can totally use regular class syntax today for the vast majority of things that you'd want to do an app. You could do class extend service or something and it works just fine in vast majority of things work.
I link to them along but I wrote two blog posts about things that were doing in Ember CLI Babel. The first one is targets. The second was about debug code stripping. If you feel like basically, have a certain deprecations in an add-on or app code, it automatically stripped the same way the Ember does. But those are the kinds of things that are unlocked by having shared Babel tooling and stuff.
ROBERT: Yep, that's next week on the 11th. That is coming up quick.
CHARLES: All right. Everybody, look for that. We'll link to that in the show notes. Also, there's a lot of extra stuff that we didn't have time to talk about, specifically around this topic that Robert's written about on his blog so be sure to check out those links below. See you around.