Pros & Cons Of Ember Engines

When I started working on our team’s massive Ember app with more directories than the eye can see, it became my goal to simplify the work process and find a way to separate logical parts of the app. I implemented Ember Engines and here are my thoughts on it.

Shahar Avigezer
Frontend Weekly
5 min readJan 31, 2022

--

Photo by Xavi Cabrera on Unsplash

One of the concerns for growing teams like us is being code-pendent (get it?) and the big challenge is making sure many teams are in sync.

That is where Ember Engines comes to the rescue

What is an Ember Engines?

According to Ember Engines documentation, an Engine represents a set of functionality and user experiences that could logically be considered an application. It’s a specific type of Ember addon that relies on its hosts to fulfill these responsibilities. From the user’s perspective, the host application and its Engines appear to be a single application.

It’s already being used by a number of organizations, including LinkedIn, CLARK, and Square to optimize sites with millions of users.

You can use Ember Engines in a variety of formats, depending on your needs. Here are some examples:

Standalone

Standard addon (normally just referred to as addons) is full-fledged NPM packages that can be distributed and installed in other Ember applications.

In-repo

This type of addon lives within the repository of an Ember application and is only used by that specific application. Using an in-repo Engine is a good alternative to consider instead of maintaining two separate repositories.

Route-less

They don’t live at a specific route but are instead mounted within a template or your application. Examples of good candidates for route-less Engines are chat boxes or complex forms.

Routable

They live at a designated route in your application and can have their own internal routes which you can navigate to.

After some deliberations, I’ve decided to use a routable in-repo Engine. Since our feature will be composed of multiple routes and its own business logic, I’ll isolate it from the parent app as a routable Engine. Additionally, I’d like to keep using the full CI/CD process because our frontend repo is rapidly changing in most areas; so the Engine will have to be in-repo since in this case, a standalone Engine might slow down the development process.

Working with Ember Engines was overall a good experience. The only roadblock I experienced during development was the need for pre-planning for how we would share components from the parent app. I ended up adding a shared add-on for all required components, data, and so on. It did require a bit more work but it’s a great investment for the future since to this day, our team adds any needed components or data when it’s in broader use.

Strengths Of Ember Engines

Performance

The coolest concept of the Engine’s source code is that it can be asynchronously loaded when the Engine is mounted. When set as true, only the Engine’s routing map is initially loaded. The rest of the Engine can be loaded when a route in an Engine is visited. This ability to optimize performance is crucial and eventually saves money.

Maintenance

Using Ember Engines reduces the complexity of a huge dependency tree that keeps growing as we go along. The fact that small chunks of the app are loosely coupled can eventually help us to avoid unwanted side effects and iterate quicker. A more forward-looking approach like this can also help newcomers feel less overwhelmed and get them integrated faster.

Weak spots Of Ember Engines

Testing

In-repo engine testing can be challenging since it is not fully decoupled. Meaning, you’ll have to keep all your tests in the parent app. Specifically, the issue with unit and integration tests is more complex because your parent app will not find the component you’re testing. We worked our way around it and Happily the testing resolver to support multiple engines using the module prefix. Full details can be found in our suggestion in #653 PR. Happily, Ember Engines Roadmap does include fixing this issue for 2022.

Dependencies

Since the Engine functions as a mini-app, it has its own dependencies. It makes sense for a standalone Engine but when dealing with in-repo, it’s up to you to manage and maintain different versions of packages across your Engines and parent app. The real issue begins when you have different versions of packages across your Engines and parent app. For example, imagine the parent app depends on ember-truth-helpers~1.0.0, Engine#1 depends on ember-truth-helpers~1.7.0 and Engine#2 depends on ember-truth-helpers~2.1.0.
Now, three different versions of ember-truth-helpers would be included in your vendor bundles. But which version would actually be used in your app/Engine would depend on the order in which the bundles are loaded.

*Using yarn workspaces can be a good solution to manage duplications of dependencies since it unifies all required packages in one process.

Sharing code

When you start to work on an in-repo Engine, in an existing app, you might find yourself needing existing components, helpers, and utilities. For the existing repo, you might be investing most of your time in pre-planning. To avoid incidental coupling with a specific host design and architecture, Ember encourages moving the shared constructs into an addon. It is easy to understand the reasoning behind this, since it supports the concept of having an independent Engine but eventually, it creates a longer pre-planning process and makes you choose between duplications (no one wants that) and extracting existing components into a shared addon. A mid-way solution would be to inject a component dependency as we do with services, for example.

Final thoughts

The concept of Ember Engines makes it possible to separate individual pieces of your application and it enables our different teams to iterate quickly and independently.

I recommend trying out using this great tool in your Ember app, but I strongly believe that for an existing large app, you should invest some time in planning ahead.

Tom Dale, Senior Staff Software Engineer at LinkedIn, explained it best in his tweet thread:

I hope you enjoyed this post! Clap 👏 and share away!

If you’re looking to start using Ember Engines, here’s a quick guide to get you started: https://ember-engines.com/docs/quickstart

--

--

Shahar Avigezer
Frontend Weekly

UX/UI designer turned Full Stack Developer, currently @ Riskified. Solving challenges both in tech and parenting.