A cool CLI tool to break up your Ember monolith

The monolith problem is not specific to back-end services but also applies equally to the front-end realm. And with frameworks like Ember.js, it can easily become an aggravating problem over time.

Ember apps tend to get larger and larger with time (that is, into ‘monoliths’) and there is no way to split code or lazy-load code for your applications other than using an experimental build tool like Embroider or moving away from Ember conventions. 

To solve this, we at Freshworks decided to move some of our modules in the existing app to Ember Engines. Ember Engines is the de-facto standard to split up your Ember app into multiple Engines.

But to migrate an existing application into Engines is not a simple task when you have hundreds of modules to migrate. Even with a large number of people, this task is a daunting one. We need to automate this to some extent. That’s why at Freshworks we have built a CLI tool to automate the process of migration to Engines.

The tool: app-to-addon-migrator

app-to-addon-migrator is an opinionated CLI to migrate Ember components from app to addons within a Yarn workspace.

NOTE: This CLI works only with the following folder structure for your Ember app.

We chose to use Yarn workspaces because we wanted to keep all our Engines inside a single repository so that the developers don’t have to worry about the context-switching by checking out different repositories. We also adopted a different folder structure than the one recommended by Yarn workspaces or Ember Engines to have a mono-repo kind of hierarchy to reduce the large diffs from moving files around. This also helps us to incrementally migrate every module to Engines.

Assumptions made by this tool

  • Your Ember app lives in the root of your project folder.
  • Engines live under packages/engines folder.
  • Addons live under packages/addons folder.
  • You are using Yarn workspaces.
  • You are using a POD structure for your components.


You can install this CLI like any other npm package by running npm install in the terminal. It is recommended to install this package globally so that you can run the CLI any time.

<span style="font-weight: 400;">npm install --global app-to-addon-migrator</span>



The CLI tool offers two types of interfaces—ateam and atam.  

1. ateam (wizard UI)

A wizard-like interface where you can select the components you want to move to the addons folder by just typing a few characters in the name of the component.

<a href=”https://asciinema.org/a/pLiwcZx1E3CUEuPDd4ELNvwIF” target=”_blank”><img src=”https://asciinema.org/a/pLiwcZx1E3CUEuPDd4ELNvwIF.svg” /></a>

2. atam (classic CLI)

A classic CLI interface where you explicitly specify the commands through arguments and flags.

<span style="font-weight: 400;">atam [entity] [entity-name] [dest-folder]</span>

<span style="font-weight: 400;">atam route default packages/engines/dashboards-engine</span>

After running the above command, the route default from app/routes/default.js will be moved to packages/engines/dashboards-engine/addon/routes/default.js

Dry run

If you just want to see/verify the movement, use the –dry-run or -d option.

<span style="font-weight: 400;">atam route default packages/engines/dashboards-engine -d</span>

This will print something like (without actually copying the files):

<span style="font-weight: 400;">Moving route.js</span>

<span style="font-weight: 400;">---------------</span>

<span style="font-weight: 400;">app/routes/helpdesk/default.js</span>

<span style="font-weight: 400;">packages/engines/dashboards-engine/addon/routes/default.js</span>


<span style="font-weight: 400;">Moving route template.hbs</span>

<span style="font-weight: 400;">-------------------------</span>

<span style="font-weight: 400;">app/templates/helpdeskdefault.hbs</span>

<span style="font-weight: 400;">packages/engines/dashboards-engine/addon/templates/default.hbs</span>

Folder namespace

If your source entities are namespaced within a folder you can use the -f option to specify the same before copying. For example, if you want to move a component called widget from app/components/dashboards, use the following command:

<span style="font-weight: 400;">atam component widget packages/engines/dashboards-engine -f dashboards</span>

Or you can simply specify the source path directly to copy from there:

<span style="font-weight: 400;">atam component dashboards/widget packages/engines/dashboards-engine</span>

Moving dependencies

While copying a route from the host app to the engines, you may also want to move the dependencies like the components used in the route template to their respective place in the Engines. This can be a tedious process if you have to do it manually. The CLI comes with a special command routex which makes the job easy. Please note that this feature is experimental and still a work in progress.

<span style="font-weight: 400;">atam routex default packages/engines/dashboards-engine</span>


A huge shoutout to @Kanalveli and @Vinodkumar for their contributions to the enhancements of the tool.

Cover image: Vignesh Rajan