 Hello, I'm Vaudry, and welcome to my talk about adopting Envoider. But before that, who am I? I'm a front-end engineer at Conto, a company that provides all of your business finances and gather it in one app. That's me on the left, trying to speak like a fish. When I'm not on stage making up stories, you can find me on Discord and on GitHub, we see under Vendor. Why talk about Envoider? Well, Conto started in 2016 with Ember. Seven years later, the company has grown, and so does both its web assets, the number of features that we've shipped, the number of apps. So does the web team. And Ember did a great job helping us scale. At this stage, new kind of topics have arised. Our code base has gone bigger, and it has had impacts on the rebuild delay when we are developing. The implementation of our design system into a component library add-on is now being shipped through 50-ish components that get systematically bundled into our apps, even when they are not used. Also, when we want to make, also we want to make the initial load strategy smarter so that it gets smaller. But the good thing is none of those topics are new. And actually, the Ember community has been working on it for years now. It's called Embrider, and it has been around for four years. Embrider in itself is not a package bundler. It will transform your Ember app into a very large years version of it that can be understood by a package bundler. So now I have 30 minutes to convince you that it is ready and easy to get on with Embrider. It has been designed as an alternative way of building apps to improve build performance, better integration with the toolchain, the DS toolchain, sorry, and provide tree shaking. So how do we bring this to Ember? For this Ember, I'm not an Embrider expert. I won't dig into the deep details of its implementation. And if you add it, you should definitely go watch or re-watch head talk about it. But in short, and what you have to keep in mind for the rest of this talk is that the whole design revolves around embracing ES modules. It means that while apps and add-on use to be able to push whatever code they wanted into the final bundle app, now with ES modules, they will have to pull each other into the build when needed. That will make the rebuild faster, as it can now determine which things don't need actually to be rebuilt. We will replace the app import API of Ember with the ES import. The last idea is that we want to allow static analysis of our app to allow a big time optimization. To do that, we need to have an explicit list of dependencies, what is needed in terms of components, server, service helpers to display a certain route. So what Embrider Compact Build is doing is transforming all of this Ember convention into making a list of dependencies so that you don't have to write them down. In the end, you get a collection of ES modules that the package bundler can handle. So let's try it as it's pretty easy to set up. You just have to add two lines at the bottom of your Ember CLI build.js file. You can build an Embrider without everything figured out. It will transform your app with Embrider Compact and passing it down to the only package bundler for now available, Webpack, all configured for us. That's it. You're done. Two minutes, end of my talk, almost. Because switching to app bundling processes can be risky and tedious. At control, we were early adopters. So we needed a trial-based strategy. We couldn't afford to block the feature pipeline for weeks or even introduce regression in our apps. So our strategy was to build an Embrider trial version of our app every time we merge something on main. Then we would run all of our test code base against it, let them fail, and look errors and problems that we encountered. And once we had them fixed, we would be able to switch for Embrider as our main build strategy. So we started to run Embrider three years ago on our control apps with Embrider Compact C++. And we only switched to Embrider fully at the beginning of this very year. Of course, it shouldn't take that long now. Most problems have been solved and are well-documented. Embrider is at a version 3.14 now. So this slide is more a moment of appreciation for everyone who worked on this fix in the Embrider team for our control. So we thought we were good. And we pushed Embrider as our default production. But we had missed something. See, pre-Embrider, apps were able to push anything to the bundle. So any asset inside a public folder would be pushed in the disk asset folder. An Embrider, an Ember Broccoli asset have in a post-process tree hook would list them, fingerprint them, and generate a map to access each asset from the app. But this doesn't work now with Embrider. The public folder assets are still available in the disk and the assets are where inside. But they are not fingerprinted anymore. If you need your asset to be available in your app, you will have to make some change. This whole topic is discussed at length in a spec. Remember, we mentioned that we switched to a pool system. So this spec proposed that when your code needs to refer an asset, you should import it and you would get back a valid URL. So for instance, if it's from within the CSS, if you want to use an image as a background, then you should move the image from inside the app folder and actually make sure that you import the CSS files that we rely on. Same as with assets imported from template. This time you would import the asset from within the CSS or thanks to an helper provided by Embrider Macro. Import sync. Here we propose to fix the pass only in the helper to ease migration without having to update pass on all the templates. Last thing that I didn't mention, that you can use Embrider Macro without Embrider is when you can start fixing things before switching. And then it would be the package model responsibility to ship your assets. Since we only have follow webpack as a package model, it would be handled by asset module feature. As a side effect, you are now able to decide how you want those assets to be shipped, whether inline or static and also run some optimization plug-in to reduce asset side. Make sure that the fingerprint depends on the content and stay consistent when image is unchanged between release. Now that we have fixed this little misunderstanding, there is a good chance that you can switch to Embrider completely doing so without any asset. But remember, we have shipped our apps with all of the compatibility mechanisms and none of them optimization. That means very few benefits from Embrider. So Embrider itself allows gradual adoption of its optimizations and that's really, really helpful. At each step, Embrider will make more assumptions on static analysis of your app and try to tre-check on your things. As a side note, they are listed in the right order, so you can activate them first with add-on trees and helper and modifiers and components and only then you would be able to do root code splitting. We'll go through each of the steps together. First one consists on allowing the static add-on trees. So add-ons used to push every file into the final bundle. Now, when activated, the add-on files must be imported from somewhere that we can statically see during the bit. For us, it meant 300 kilobytes of saved payload even though two add-ons were not compatible with our feature. In that case, it shouldn't block you. You can discard them. For us, it was our component library that was using Ember CSS modules. So we discarded it until we moved to an Embrider way of doing CSS modules. To do that, you can use compact adapters and this solution is brought by Nick Shot who will give a workshop tomorrow. Be sure to check this article on the topic. The next step consists on transforming your app into something that is statically analysis-safe. So we will list all components and helpers and modifiers every time they are being used so that we can pre-check the other ones. So that's a given unless you have dynamic usage of components or helpers in the sense of picking one based on the variable or concatenating a few strings to find one. So it's actually extremely rare to dynamically register helpers and modifiers. But for components, there is an helper called component that allows you to pass a string and invoke it at runtime and this pattern is more common. But this prevent static analysis as Embrider at build time cannot know which component is required. But there's a way around to fix this. The ensure safe component helper provided by Embrider will turn a component class into a component definition that can be invoked in the template. You can also pass a full back component to handle undefined cases. It is a good opportunity to make your app more robust, especially the component APIs, like would your component work with an undefined or not the components that you forced in before? Again, it is documented at length in the Embrider build documentation. And so it made our 20-ish issues that we had easy to fix. Even the one that we're in the test where we registered dynamically components to test some modifiers. So at this point, you're already repeating the benefits of tree shaking. Only components that are needed get pulled. This means we also know which one are needed per root. So now we can safely activate root-based code splitting. So it's actually fairly easy to set up. You just have to replace EmberRouter with EmbriderRouter. It's a wrapper of the former one that is capable of also handling dynamic imports. Also, you will have to decide which root should be loaded as a dedicated chunk and the strategy of depending which one will change from one app to another, obviously. And now a practical case. I think it is fair to say that a good number of us right here have learned EmberRouter on the tutorial. It consists of building a bare Ember app with three roots, contact about the main one, EmberData to fetch data, and less than 15 components to play with the template API. The first thing that puzzled me when I migrated to Embrider was that EmbriderSafe was already bringing a huge improvement in terms of final payload. As you can see, adding progressively optimization brings also significant improvement, even though the app has only a few components and practically no add-ons. So if your app is a lot bigger, you can expect even bigger improvements. So what we discussed here, we know of an actionable way of improving significantly performances of our Ember apps. It takes literally five minutes to migrate. It took us longer than expected, but you can adopt Embrider features incrementally at your own pace without blocking the feature pipeline. The documentation is really getting better. And after four years, it covers extensively the migration process that may come around. Lastly, it was for us a great opportunity as we rediscovered how things are actually tied up behind the scene. And before I leave you, we didn't discuss about migrating all our add-ons to Embrider native V2 format that would improve even better build performance. Now that we talked about alternatives to Webpack, I don't want to spoil things, but you should definitely go watch a talk about what's coming in Embrider. Also, I don't know you, but I'm really, really hyped with a number of things that are coming with this Polaris edition. Thanks for your attention.