Upcoming and OnDemand Webinars View full list

Is Your Ember App Too Big? Split It Up with Ember Engines

Todd Gandee

The Ember team has does an excellent job giving proper names to most their components, tools and libraries. For example, the rendering engine is called Glimmer, while it uses HTMLBars as the template language. Singletons in Ember applications are called Services. The build tool is called Ember-CLI, and a external application module is called an Addon, generally stored in NPM with the prefix ember-cli-[addon-name]. Having recognizable names makes talking about them a lot easier.

This is very intentional for the community. There are specific terms for developers to discuss and an easy way to market changes to the framework. The latest is Engines, or Ember Engines.

The Ember Engines RFC started in October 2014 and was merged in April 2016. The goal was to allow large Ember applications to be split into consumable Addons allowing development teams to build logically-grouped pieces of an application in separate repositories and mount each micro application as a route or container in a parent application. In the table below are links to resources for EmberEngines for more history and details:

Resources URLS
Ember Engines Guide http://ember-engines.com/guide
Github Repo https://github.com/ember-engines/ember-engines
Engines – RFC https://github.com/emberjs/rfcs/pull/10

Engines and the flow to setup Engines were added to Ember fairly early in the Engines-RFC process. The most recent feature to be added, and what I think to be a crucial piece, is lazy-loading. This allows the core application to load with the initial page request while mounted engine sections of the application will be requested as needed in separate .js files.

Engine Structure

For applications that have sections with different business concerns, engines provide a structure for scaling without the threat of exponential file size growth. From the image above, the admin section of the site will only be used by a select group of individuals maintaining the site content. Allowing these user to load a separate file will shed weight from the readers using the blog app. The benefit lies in the main app maintaining the session, styles and global components.

To achieve the separation of concerns with engines, there are two ways to create the sandbox needed for mounting engines: in-repo-engine and external repo Addon. In this post, we’ll walk through building a basic application that uses an in-repo-engine and lazy-loading. In a the next post in the series, you’ll learn about making an Ember Addon an engine in an external git repository. In the final post of the series, we’ll bring it all together with shared services and links.

Create a New Ember App


  ember new large-company-site
  cd large-company-site
  ember install ember-engines

This assumes you have ember-cli install (npm install -g ember-cli). Also, it assumes you are running Ember@2.10

These commands will setup your umbrella application with the appropriate addon to mount engines. The next step is creating an engine to mount. We will start with the in-app engine. While in the large-company-site directory add an engine with ember generate:

  ember g in-repo-engine in-app-blog

This has added a directory named “lib” and an app addon directory structure named for “in-app-blog”.

In-Repo Engine Directory Structure

Using the blueprint in-repo-engine, ember-cli has added all the appropriate files to create a new app structure with its own routes. Open lib/in-app-blog/addon/routes.js to add new routes:

  import buildRoutes from 'ember-engines/routes';

  export default buildRoutes(function() {
-     // Define your engine's route map here
+     this.route('new');
+     this.route('posts');
    });
  });

Once the routes are added in the engine’s addon/routes.js file, it is time to create route and template files for each. For this simple example, add the route and template files for new and posts in the addon/routes and addon/templates directories.

Engine Routes and Templates

The next step is to add some content to see the routes working between the parent app and engine. In the following code examples you’ll add simple headlines to each .hbs file. The file name will be in italics above the code block.

lib/in-app-blog/addon/templates/application.hbs

  <h1>Blog Engine App</h1>
  {{outlet}}

lib/in-app-blog/addon/templates/new.hbs

  <h1>New Form</h1>
  <form>
    {{input type="text" value=title}}
    {{textarea value=post}}
  <form>

lib/in-app-blog/addon/templates/posts.hbs

  <h1>All Posts</h1>
  <ul>
    <!-- will insert items here -->
  </ul>

Now, add an application template to the umbrella application:

app/templates/application.hbs

  <h1>Large Company Umbrella</h1>
  {{outlet}}

Finally, add a path to the mount route for the engine in app/route.js:

  import Ember from 'ember';
  import config from './config/environment';

  const Router = Ember.Router.extend({
  location: config.locationType,
  rootURL: config.rootURL
  });

  Router.map(function() {
-    this.mount('in-app-blog');
+    this.mount('in-app-blog', {path: "blog"});
  });

  export default Router;

At this point, the structure is in place to create new routes, templates, controllers, and components for the blog engine application. The last change you need to make is in the lib/in-app-blog/index.js file. You will change the application to lazy-load the blog engine. Add the following to the index.js file in the lib/in-app-blog:

  /\*jshint node:true\*/
  var EngineAddon = require('ember-engines/lib/engine-addon');
  module.exports = EngineAddon.extend({
    name: 'in-app-blog',
+   lazyLoading: true,
    isDevelopingAddon: function() {
      return true;
    }
  });

In the terminal, run ember s, and open your browser to the location localhost:4200/blog/posts.

Using the Chrome browser and the Developer Tools, you can open the Network tab to see the network traffic. What you’ll see is multiple .js files being loaded.

Highlighted in the developer console is engine.js which is a separate file from large-company-site.js. This is it, this is what we’ve been waiting for. You can now built the largest Ember site ever and separate concerns with engines and know your users will get script and style resources efficiently. The benefit to you and your team is huge—you don’t have to spend all of your time configuring the build process. That’s Ember’s gift to you.

This example will be on Github at https://github.com/bignerdranch/ember-engine-example. As the series continues, the GitHub repo will include tags/commits for each blog post.

In the next post of the series, you will create an external addon as an engine and link it to your project. The final post will add shared services and links to tie the application together.

Not Happy with Your Current App, or Digital Product?

Submit your event

Let's Discuss Your Project

Let's Discuss Your Project