Having a great packaging system is critical to Ember's success. This wish list is not long, but very important to land and 'get right'.

tldr; We really need to adopt Embroider!

Ember 2019 Roadmap Process 🛣

The #EmberJS2019 call for blog posts went out a few days ago. Seeing these posts pop up made me start to think about what I would like to see happen in the next year. The pressure of "getting the perfect list" is just too much pressure for me 🙀, so I've decided to try to do a few smaller posts where each is focused on a specific area that I think we can improve on in the coming year. We'll see if I end up getting more than one out there 😉.

Packaging 🎁

The ongoing effort to migrate from using the existing build pipeline in ember-cli to using Embroider should allow us to check each one of these items off. I'm primarily calling these out as fundamental requirements of the system, and as an example of what our future could look like if we push ourselves to get Embroider landed into the default stack for ember new.

Shims ☠

We should be able to completely remove the need for "shim" addons and instead import directly from npm packages. Don't get me wrong, loads of addons exist that add Ember specific functionality in addition to "shimming" other libraries; I think this is one of the biggest features of our addon ecosystem. However, being forced to author an addon just to import a given library into my build is a very frustrating barrier to entry. Addons like my own ember-cli-pretender only exist because without a good baked in packaging system bringing in Pretender was too annoying.

In order to do this, we should support importing from npm packages directly. The good news is that we can get this functionality today by using ember-auto-import, but we have been somewhat hesitant to make this part of the default stack. An application could also use Embroider instead of the built-in build/package system which would make the use of ember-auto-import not needed.

Targeted Builds 🎯

Today's Ember apps are generally transpiled directly for the most common development environments: latest Chrome, latest Safari, and latest FireFox. But then when we deploy, we transpile all the way down to IE11 😱. This does make the development ergonomics much better (ZOMG debugging native async / await code is wonderful 😍). Unfortunately, it doesn't really do us many favors in production where we end up shipping a much more bloated version of our application because transpiling template strings, class features, async/await, etc end up being quite a bit larger. In addition, there are a number of optimizations that can only be done when actually leveraging the new ES features which means: not only is it more overall bytes on the wire, but the browser isn't able to take advantage of the same optimizations!

There are at least a couple different ways to do this:

  • Emit separate builds grouped by target (e.g. "last 2 evergreen") into dist/ (e.g. dist/ie11/*, dist/latest-2-chrome/*, etc.)
  • Emit a single build asset but use <script src="/ie11-compat-file.js" nomodule> and <script module="/evergreen-file.js"> ([see this pre-RFC by @tomdale](https://github.com/emberjs/rfcs/issues/383))

In order to accomplish this, we need a better way to build (e.g. we shouldn't have to run ember build twice) so that we can share work between the various targeted builds. A good packager solution could do this by keeping ES latest "loose" modules throughout the system, and only transpile down at the latest stage. At this point, Embroider doesn't have this capability, but it absolutely could be added once it is a bit further along in the adoption process.

Whatever we decide, the rough idea that I'd like to get across is that we should make it trivial to compile and deploy my production app with separate assets by browser.

Lazy Engines ☠️

ember-engines provides an awesome mechanism to share isolated chunks of code between apps and other engines. Along the way, we added a feature enabling "lazy engines", because we simply had no other way to add this functionality. Well, it's time to pay the piper – it should be possible to make any addon lazy and as such "lazy engines" as a concept should completely go away! Instead, the packaging system should support making engines and addons alike lazy as needed.

Within Embroider it is already possible to have an arbitrary addon be bundled into its own lazy bundle and only loaded when needed (by way of dynamic import() statements). From there it should be possible to leverage the same rough ideas and to allow Embroider to make "lazy engines" completely obsolete.

Conclusion 🤔

We really need to adopt Embroider! There is already so much progress on this front, and many apps can already use Embroider out of the box 🎉 (its README has more details on adopting and slowly ramping up more and more of its features). In 2019, we need to continue smoothing out rough edges so that we make Embroider part of a default ember new foo application.

Let's do this!