 Hello, I'm Godfrey from the Framework Core Team. Welcome to the second half of the keynote where I walk you through everything that happened this year and how it might affect you as an Ember developer. I'd like to begin with announcing some personnel changes to the core team. This is not the whole core team, by the way. Many years ago we used to be able to fit everyone on one slide, but we're way past that point now. You can find a full list of Ember core team members on the website, but for now this is what changed this year. I second Jared joined the learning team and Scott joined the Ember data team. Kniepolo as well as Matthew from the framework core team joined the steering committee and Meanwhile, Melanie is alumnizing from the learning team and steering committee to focus her duties on the framework team. Likewise, Tom is now a steering committee alumni, but is staying on the framework core team and Jen alumnates from the framework team to focus on the learning team responsibilities. Finally, Kratty and Alex from the CLI team as well as Shiva Kuma from the learning team have alumnus as well. On behalf of the community and the entire core team I would like to extend a warm welcome to all the new team members and a big thank you to the new to well a big thank you to the alumni for the continued contributions over the years. Okay, so this is all for the core team changes and We have a lot of ground to cover today, so I'm just gonna jump right in and talk about the changes in the framework Now as always a lot of the Work went into behind the scenes things like maintaining the framework and this year is no exception These bug fixes and small improvements don't usually got talked about as much as the big features But they are no less important in maintaining a healthy framework and a productive workflow for us developers So I would like to take a few moments to talk about some of them briefly The first the first set of changes are post release improvements to octane With the wide release of octane and more dosages in the wild there were some occasional bug reports for the new auto tracking system, especially in edge cases involving other legacy features and these in a amount of work went into debugging and fixing these issues and Putting in place a better infrastructure so we can provide More helpful information when errors do occur Also as of the current beta all built-in components like linked to an input have been completely rewritten using the new octane paradigms internally We also made a lot of improvements to the linter to the template linter in particular There's now a new to-do system that makes it easier to adopt new lint rules and migrate your code base gradually A lot of the new lint rules also have auto fixers that could apply suggestions automatically Outside the framework itself We also made a lot of quality of life improvements to the tools and workflows you use on a day-to-day basis Notably we integrated prettier into the default stack so we can stop worrying about formatting your code and Focus more on writing it and avoiding the subsequent bike shed with your team during code review There are also some improvements to accessibility this year the default blueprint now include the ember page title add-on which encourages you to provide meaningful and descriptive title for your pages and There's also a link flag to the ember new command which explicitly sets the human language for your apps content These changes together will help provide a better experience to users of screen readers and other assistive assistive technologies Finally we also made some internal changes to ember source package in the past when you install the ember source package from npm What you get is essentially a pre-built file that you can run directly in the browser as a script tag all the way down to 11 With this change the ember source package is now just lose ES modules without Being transpiled first for a particular browser and your app is responsible for building it according to your own browser target That you have configured There are a number of advantages to this For one thing even though the ember 3.x series officially supports down to i11 most of you probably don't care for it So by deferring the building of ember source to your apps own build pipeline You can skip transpiling those features like native classes if your browser targets otherwise support them natively This can result in some wins and bite size and even some performance improvements in some cases Another benefit is that we are now able to compile your templates differently depending on whether you're building for development or production This allows us to leave a lot more debug information in your template without worrying about inflating your final bundle size in production So all of these are just a few examples of what we worked on behind the scenes this year And I would like to thank everyone who were involved in making these awesome improvements to the framework Okay, so as much as it was a year for improvements. It was also a year of cleaning things up Here are some of the deprecations we landed into their framework this year And hopefully you won't actually run into that many of them in practice because a lot of them are Targeting very old legacy features that are rarely used these days Nevertheless, I won't go into too much details about them and you can read about the deprecations on the deprecation guide However, I would like to point out two things real quick number one We have deprecated the pre-octane configurations also known as the classic edition This means that after 4.0 all ember apps Using 4.0 and BELF will automatically be octane apps and the difference doesn't matter anymore and second the latest the the last batch of deprecations targeting 4.0 have landed into 3.27 which is currently in beta if everything goes according to plan then next release after that would be free 28 and that release will have no more additional deprecations for 4.0 and Six weeks after the release of free 28. We will release version 4.0 dropping support for IE 11 and among other things And You'll soon hear about more of the 4.0 plans on ember blog soon, but that's the gist of it Okay, so that's all for improvements and deprecations up next I would like to highlight three major areas that we worked on over the last year But before that let's go back to this slide from Embercon 2019 Here Tom was describing how when individual features are developed and released incrementally Things might actually start to feel incoherent for a while Over time the more of the as more of the companion features were are released and As the documentation tooling and ecosystem start to catch up Then things will start to really come together The idea of an addition is to get to declare that we have reached those peak moments of stability and big picture coherence and That the features are ready for community-wide adoption Now with Octane release last year. We are starting to work towards the next edition called Polaris And so naturally we find ourselves iterating toward that pit of incoherence again, which is Again perfectly normal As I walk through these new features just keep in mind that Just keep that in mind. It's not that the features themselves are particularly buggy But you might find that for example the guides and the ember inspector are lagging behind and covering these features And it might be a little bit hard to get answers on this court just because of how new these features are So with that in mind if you and your team are not prepared to be an early adopter That's totally okay. Just treat this part as a sneak peek in the future and when we're ready to wrap up the next edition I'm sure you'll hear about it from us again But on the other hand if you're eager to help shape the future of ember this is your time to shine as The features are still being designed and experimented on your early feedback are going to be really important in terms of influencing the direction that we are headed and If you're looking for opportunities to contribute, then there are no shortages of things of things that you can help with right now So with that out of the way, let's get to these highlights. It shouldn't be a Surprise, but the first thing on my lease the first thing on my list is embroider By now you've probably heard about it many times, but in case you skip the first part of the keynote Here is a quick summary Now historically the ember build pipeline looks something like this We take your app plus the add-ons you use plus ember itself Run it through your disc custom black box and end result is something that you can run in browser Basically a script tag that you can drop in Because the build pipeline in the middle is completely custom and because the apps and Your app and the add-ons you use can customize this build line This build pipeline in numerous ways over time ember apps became quite a couple to this particular build pipeline And it's almost impossible to swap it out with something else In the meantime the wider ecosystem have converged on some de facto standards around how Morton Javascript codes should be structured and published and A lot of Morton tools have been written That play nicely with each other as long as these ecosystem conventions are followed Now we could duplicate these efforts and Reimplement these tools and features inside our own build pot pipeline But a lot of these problems are pretty low-level and not particularly specific to ember apps And we would honestly much rather focus our energy on some somewhere else That's like more core to a mission as a framework This is where in broader comes into play it isn't really a single tool or as an end-to-end Replacement for our build pipeline, but rather it started as a holistic We think on how we can reorient ourselves into aligning better with the wider Javascript ecosystem Conventions so that we can let these existing tools do most of the heavy lifting for us And we can benefit from these shared efforts for free With that in mind and broader is a bridge that tries to take the collection of things that make up an ember app But instead of building it directly for the browser It just transformed them into the de facto standard that is understood by most of the morning tools and from there you can send up From there you can use any off-the-shelf tools such as webpack to finish the job Now in this example, I've shown using webpack to build for the browser Which is going to be the default when embroider is enabled for? For new ember apps however and broader itself is not dependent or coupled to webpack per se its job is just to build things into the standard format and in fact in the future as Browser start to implement native support for these standards like native support for loading ES modules You might not even need that final step and you might be able to just take that Standard output and run it in the browser directly without further processing On the other hand you are not limited to building for the browser either because the output of ember because the output of embroider is The de facto standard JavaScript code you can also take that and feed it into other tools that understand those conventions Such as a dependency analyzer or maybe a documentation generator As long as they follow the same ecosystem wide non ember specific conventions, it will work Now if you want to read more about how it actually works beyond this very high level of review I recommend checking out the read me on the embroider repository on github and Finally, I would like to give you a rough sense of where we are at With this initiative over the past year We have merged the RFC that underpins the whole project called the add-on v2 format We have also tested embroider compatibility layer against the number of open source and closed source ember apps And along the way we fix many issues that popped up in many popular community add-ons Starting in ember ceo i3 27 which again currently in beta There will be a command line flag for generating a new apps using the embroider blueprint at this point We are also nearly ready to release 1.0 of the ember of the embroider page itself If it all goes well, we might be able to make embroider the default for new apps starting as soon as ember ceo 328 which would be the release after this one Therefore if you're an add-on author, this would be a really good time to add embroider to your CI config and make sure And on can actually build On it without issues You can find instructions linked from the read me that I mentioned before and if you're eager to test building your app With embroider you can also find instructions in the read me as well at this stage The top priority is Compatibility and a seamless transition. So we're likely going to stick with the more conservative more compatible configurations however, as more of the add-on ecosystem have adjusted to comply with the stricter settings on embroider you will start to see more and more benefits and better results from optimizations such as tree shaking which remove the unused part of the dependencies from your final bundle So in summary, I think we're pretty much ready for prime time And it's a long time coming and I'm really excited about the future the future and locks for us Okay, that's all for embroider and up next on my list. I have a feature called name blocks for this Let let us look in examples in arrow Let's see your task with implementing this fancy drop-down component at work It's pretty similar to your standard HTML select element except it support richer HTML for the Options like you can have images and and stuff inside the drop-down menu So after staring at it for a while, this is what you came up with So let's walk through this together First you have a button on top that toggles opening and closing drop-down menu and then That's the markup for the drop-down menu itself The component takes an add items argument and there's a each loop to go through every item in the array It then renders each of them inside the drop-down menu and so that's how you get the results on the right This is all great the component works, but there's one problem Currently this drop-down component hardcodes the markup for the menu items Which means that it will only work for this exact Scenario like these exact objects and you cannot reuse this in another place where you want the menu items It looks slightly different. Perhaps you want the image on the right. Perhaps you want no images at all It will be great if this drop-down component does not have any opinion on that and Would be able to just render the items however you want at at that particular location Fortunately, you know exactly what to do here Now after this refactor the component now takes a block the block is called once in each iteration of the loop and The item in question is yielded to the component Uder to the block via Like be a block param Instead of hard coding how the item should be displayed inside a component the markup now lives on the caller side and inside the block now the component doesn't care what the items are anymore and You are free to display them however you want all it does is takes cares of the basic functionality of a drop-down menu and Deferred rest to the caller to customize using a block. This is pretty awesome So just when you are ready to celebrate and take an early lunch a challenger has appeared turns out it was your p.m It turned out that he spotted a problem Sometimes the list of items could be empty in which case he wanted you to render nice message with an explanation Instead of just rendering an empty drop-down seems pretty reasonable and in and of itself It's not that hard to implement in fact You can probably just implement it right away. You just need to add an else block to the each loop, right? That's pretty straightforward Now the problem is though this basically wrote back to work You did earlier to make the component reusable You see the component once again is hard-coded to this exact scenario Thanks to the markup in that else block if it were just a simple message Perhaps you can get away with taking it as an argument But since this requires some non-trivial HTML that doesn't really work. Oh, well, maybe you have a better idea after lunch Just be just when you're ready to take your lunch your p.m Pink you again and turns out he just had a meeting with another p.m And he showed off your work on the drop-down the other p.m Loved it and in fact, they loved it so much that they wanted to use the space above your drop-down to show an ad That's unfortunate, but oh well eat first think later lunch time So yeah You took your lunch break and you had a generous portion of mashed potatoes if that doesn't solve your problem Then probably nothing will Okay, back from lunch get stash start over just before the food coma kicked in you remember hearing about name blocks at the Ember conf keynote and The presenter told a story that was oddly similar to your situation right now. So you decide to check that out After looking at the documentation realized name blocks is the perfect solution to your problem It's like they were made for this exact purpose This is what you came up with Let's break it down first you define a name block for the ad called and call it the banner block and On the caller side you can pass the name block with the colon banner syntax It looks like a regulation element except it starts with a colon That's how you know it's a name block Inside the drop-down component you can use to this name block using the same yield syntax from earlier But with the additional to argument set to banner, which is the name of the block Down below you have the item block which is exactly the same content as before Just like before the block is still being called once per item and has access to the item in question as a block Param which is provided by the component by passing it to a yield keyword Finally you have a third block for the empty state so the component doesn't have to hard-code anything there as well Just like that you have learned to use the name blocks feature and in summary It's just like normal blocks you can yield and take block rams as with normal blocks and the only difference is that they can now there can be multiple blocks and Each identified with a unique name. So when yielding you would also have to specify the name of the block that you're yielding to If you're already used to how blocks work in Ember hopefully this would feel pretty Straightforward and feels like a natural extension to that paradigm Now that we're covered the basic use cases for the feature. Let me walk you through a cheat sheet for the feature First of all this feature is only available for anger bracket implications There is currently no name block syntax for curly invocations So if you want to use name blocks you have to use anger bracket Invocation for now at least Next while you can pass multiple blocks in the same Invocation as we saw in the early example each of them must have a unique name So you cannot pass the same block multiple times Also name blocks can only appear immediately inside an angle bracket component Invocation, so you cannot have a name block just chilling out at the top level And on the other hand if you're going to pass name blocks, you cannot also have other content inside the invocation tag Likewise because you can only have name blocks immediately inside a component tag you cannot pass name blocks conditionally however, you can make the content inside of name blocks conditional as shown on the left here on The flip side inside a component you can detect whether a particular block is passed to you using the has block keyword This allows you to make a name block optional for your consumers and provide some useful default content if the block is not passed We already saw this story earlier But just as a regular block your component can yield as many or as little block programs to a name block as you would like On the passing side you can name them whatever you want And they'll become local variables that are accessible within and only within the block Not that you should ever write the thing on the right But the anonymous block syntax that you're used to is actually a shorthand for the default name block So again, there's generally no reason to do it that way But knowing this might be useful in some tricky interrupt and backwards compatibility situation that you might run into Likewise the two blocks that you can pass with curly invocations is actually Correspond to the default and the else name blocks This might come into handy when there is a component that takes an else block But you otherwise want to use the angle bracket notation to invoke it so this allows you to do just that and Along the same lines on the yielding side the default use syntax is the same as explicitly yielding to the default block Again, there's no good reason to write it out like that But knowing this might help you design a backwards compatible component that can be used with or without the name blocks feature so that's all I have for the name blocks feature and We have already used started using this in a few places in our app at work And I would certainly have designed some of our components differently if this feature were available earlier Even though the feature is pretty simple to use it unlocks some pretty powerful patterns for components And I can't wait to see what the compete the add-on community comes up with Okay, so moving on the third and final feature. I want to highlight doesn't really have a name So let's just call it template value semantics for now It is definitely a more advanced set of features. So please bear with me So here I have a hypothetical form component library and a form implemented using that library on the screen The form component takes a block and use block param, which we named f Inside the block you have access to the form controls provided by the component using the f block param You can invoke them like f dot input f dot tax area tax area and so on You have probably seen something like this in an add-on before but maybe not everyone knows exactly how that is Implemented under hood. So let's take a look at that Now if you open up the source code of this components template, it will probably look something like this the block param it yielded is actually a hash and each item in the hash corresponds to One of the form controls that you have access to inside a form component It uses the component helper which allows you to refer to and look up a component in your app or your add-on by name In this case, it's the actual definition of the f dot tax area component We saw earlier actually lived in a file called my my form slash tax area In addition to letting you refer to a component by name the component helper also Serve a second purpose which is to allow you to pre configure the component by Pre-applying some arguments in this case. We specified an argument called form and assigned the value to you this That means whenever someone invokes the f dot tax area component It will automatically pass this extra argument to the component as if the caller had Specified it in the invocation tag even though they didn't This pattern that we're seeing here is called contextual components where you can use the component Keyword to gather a bunch of your components Pre-configure them and yield them up to the caller Usually these components you're yielding aren't meant to be used standalone and they only really make sense in a specific context In this case the form controls are only meant to be used inside the context of a form Component and that's why the pattern is called contextual components And by the way, even though the pattern is usually done by grouping all the related contextual components into a hash There's nothing intrinsically special or requires the hash keyword You could have done the same thing by yielding the contextual components as positional block params And as you can see this still works Without the hash keyword. However by yielding the component one by one The caller would have to remember to find all the block params in that exact order that you yielded them That's why usually it's better to yield a single object that has everything in their keyed by their appropriate names Still the hash keyword here is not special or Required you could have made a pojo in JavaScript and yielded that out instead and it would work all the same Okay, so since we just talked about name blocks You might notice that there are some superficial similarities between name blocks and contextual components in fact because we didn't have name blocks in the past until very recently at least Some of the roles that would have otherwise been more naturally filled by name blocks were sometimes historically implemented using Contextual components because we don't have anything else However now that we have both they actually serve pretty different purposes, and it's not like one is replacing the other On the one hand when using a name block design the component author has total control You can decide exactly when to call which of the blocks and you can call block Zero times 20 times completely up to you You can choose to pass additional data to the block in a form of block params And on the other hand when using a contextual component pattern You are giving the control to the caller of the component instead You can yield as many contextual components as you like, but there's no guarantee that the caller will call them at all or in any particular order so and also instead Instead of you passing data to a caller The caller will be passing data to your components instead by passing arguments In other words the component the difference is I called you versus you call me and In the drop-down example There can only be one banner for instance and it has to appear exactly at the top of the drop-down menu So it wouldn't really make sense for that to be a contextual components because otherwise you can Call it in any place and caught many times that wouldn't make any sense On the other hand in the form example You want the consumer to be able to design a form by mixing and matching your form controls arbitrarily in any Order or combination so the contextual component approach makes total sense there Okay, so even though it's pretty advanced Contextual components are actually a pretty old feature of ember dating back to ember 2.3 So why are we talking about this right now? Well until now you can only have contextual components But as of free 27 which again is currently in beta you can also have Contextual helpers and modifiers thanks to the new modifier and helper keywords This work exactly the same way as the component keyword by taking the name of the modifier or the helper as a string and Returning a value representing that modifier or helper As with components the most common thing you want to do of it is probably to yield them out in a contextual fashion But because it's just a regular value you can actually do whatever you want with that You can for example pass it to another Component as an argument if the component accepts a helper or modifier for one of its arguments and Just like the component keyword you can use the modifier and the helper keyword to Pre-configure things by pre applying certain arguments to them These arguments will then be baked into the value returned by the keyword so that when someone tries to invoke it later The modifier or the helper will automatically receive those extra arguments as if the caller had provided them Again, this works exactly the same way as the component keyword On the other hand, this is what it will look like to invoke one of these values Very similar to the example before This feature opens up the possibility for a completely new category of component composition patterns for example in the hypothetical form library, we can yield an Autoresize modifier that you can attach to any of the text input and have them automatically grow and shrink as the user types in them It can also yield a collection of helpers for declaring validation rules right inside the form template instead of having to do it in JavaScript and Yeah, contextual components are probably one of the most powerful template features in ember and when it became available it opened the floodgate of a lot of interesting component designs and I'm hoping that this will be the same and again. I'm really looking forward to seeing how you put this feature to use Okay, so that's pretty exciting, but that's not it in addition to the keywords to create a value referencing a component and modifier or helper we also Overhauled the rendering engine to accept them as values in a lot more places than it used to for example Here we imported a component a modifier and a helper from an add-on and we assigned them as class fields This allow us to access these imported values from within the template and if we try to invoke them This didn't use to work, but now it does everything just works as you would expect again all you did was importing a component or a helper or a modifier and If you have access to them in the template somehow then you can invoke them all the same as You can see in this case. You don't even need the Component keyword anymore or the helper keyword or a modifier keyword Of course, you can still choose to use those keywords to attach additional arguments to your imported values If that's what you want to do This works exactly as you would expect as well That opens up some pretty interesting possibilities for example You can define a helper function in the module scope of a component JavaScript file Attached to a class field and that allows you to create a truly private one-off helper Specific to this component without having to registering it and leaking it into the global namespace You can even dynamically create one-off modifiers that capture tracked instance it inside a getter and As always the getter will be automatically rerun and therefore returning a new modifier Replacing the old one whenever any of the tracks they changes These patterns are pretty powerful And I think they will open up a lot more use cases that are previously either very cumbersome or even impossible I know I've said this a bunch already, but I'm really looking forward to seeing what the next generation of ember add-ons will look like Before we close off on this topic. There's an elephant in the room that I need to address Going back to this example that we saw earlier It's pretty cool that you can do this I guess but having to import the values in your JavaScript and then make a class and then assign them to Fields just so you can have access to them inside a template that feels like a lot of boilerplate Especially when you otherwise wouldn't have needed a JavaScript class and like if you would have been able to get away with a template only component this seems like a Lot of work wouldn't it be great if you can just import those values and use them in the template directly Well good news Template imports allow you to do just that and it's exactly the depth the direction that we're iterating towards this example isn't work yet and This is probably not going to be the exact syntax that you would type in its final form anyway But it's a good enough stand-in to show the direction that we're headed towards The idea is that you would have to Import everything that you use in the template just like you would in JavaScript Instead of having everything magically become available in the global scope Well, this adds a little bit of a boilerplate. It makes it a lot easier And a lot clearer Where your components, water fires and helpers actually coming from not only will that help humans navigate? And unfamiliar ember code base. It will also make it easier for VS code and other ideas to provide Tools like autocomplete jump to definition that kind of stuff plus it will also help help embroider to see What you're actually using and not using in your app so we can remove any unneeded code from your final bundle in the tree shaking step The design for template import syntax haven't been finalized yet. So that's why the feature have not been implemented yet However, we're doing things a little bit differently this time instead of waiting to finalize the user level syntax We designed and implemented the underlying low-level primitive that is needed to provide the functionality That primitive have already landed in recent versions of ember. So thanks to that We are currently able to experiment with different syntax ideas in an add-on called ember template imports If your app is running on ember 325 or above You can install the add-on today and start getting a feel of what the future would look like or feel like One of the current design exploration is to see if we can find a good syntax for embedding the template into your JavaScript files directly And the template would have access to any Values that are available in the outer JavaScript scope This would make it much easier to do the one one off private helpers kind of thing that I showed earlier, but There are still a lot of open questions to answer. Would this be ergonomic? Is this going to feel awkward is it possible to get good syntax highlighting and edit the support and What should the file extension be for this kind of hybrid files? These questions would have been quite difficult to answer without being able to experiment with the feature hands-on and Thankfully the experimental add-on allows us to do just that As I said in the beginning we are approaching the pit of incoherence a lot of things are stone flux But that also means that right now you have a lot of influence on how these things shapes up in next edition So if you want to hear more about template imports There was a bonus contact on that topic yesterday, which should be available on YouTube soon follow Ember counter accounts or you'll miss it Okay, so that was it for the highlights and before we wrap up here are some of the new Primitives that we have landed in the past year Because these are primitives you're not expected to have to know about them and it's unlikely that you will Use them in your app directly. So I'm not gonna go through them However, if you're an add-on author or an experimenter These are the of C's to read for instance RC number for 96 Strict mode templates is the underlying primitive that was used by the template imports Experimental add-on that I showed earlier So with that said we also made some process changes this year Let's see RC 617 for instance revamped RC process itself with the goals of making the process more agile 649 aims to make the deprecation roll process more gradual and incremental 685 defined the browser support policy for Ember 4.0 onwards notably dropping at 11 The polyfills and the code mods are also now more of an official part of our process We have centralized github orgs for each and we strive to provide them like for any new features and deprecations have we released whenever possible The accessibility track team also graduated into the accessibility working group, which is a more like and they have a more permanent mandate You can thank them for spearheading the accessibility efforts such as the page title and length like Dimension in the beginning and they have more work in flight. So stay tuned for that Meanwhile, we have also formed a typescript strike team to shepherd the effort of official typescript support Right now you can already use typescript with Ember and it works pretty great. We use it at work. It's perfect It's great to community that are really good job supporting that effort, but by Making this more official. We hope to provide a more seamless and more stable experience for all the typescript users that Along the same lines that you would come to expect with the Ember project Finally with things like template imports on the horizon We would need to ramp up our tooling effort and to that end There's a new deaf Ember tooling channel on this court If you're excited about template imports for instance and want to help build a polished developer experience That would be a great place to start Finally that brings us to to my last point from testing out and broader From testing out and broader trying out Polaris features and providing early feedback for Off these helping build the tooling support for template imports to following by reports and answering questions on this court I hope I have inspired you to find some avenue to get involved in the community and Hopefully we'll be able to meet in person again soon enough, but until then enjoy your virtual Ember content experience and see you on this court Thank you