How to keep your Ember.js project clean and well-structured

André Joaquim
4 min readJun 24, 2018
Say “Hello!” to our beloved Tomster!

One year ago at Uniplaces, we had only one ember.js project. Nowadays, we have almost our front-end platforms build on top of ember and we’ve come up with this simple five-step recipe to keep an ember.js project clean and well-structured.

Step 1 — Using pods structure

The first step is making use of ember’s pods structure.

Disclaimer: This is not the default ember project structure. By default, an ember’s project blueprint aggregates files by their type (Fig. 1).

Fig.1 — Every resource type has its own folder — components, controllers, templates, etc.

First of all, what is the meaning behind the word pod? A pod means everything is grouped up in its own directory. Whether it’s all the files of a component, all files related to a route (controller, route, template) or all the files related to a model.

Using pods in your project can be done in several ways. Setting the usePods variable in .ember-cli is the way to go. You can now generate resources using ember-cli just like you did before, only using pods. You also need to specify you pods directory in the config/environment.js.

Step 2 — Routable components as a pattern

ROUTABLE COMPONENTS \o/

Yes, routable components. You heard it here first.

No, not those routable components. I’ll care to explain.

[…] we wanted to introduce the idea of “routable components” components that are managed by the router.

Tom Dale wrote the above on the EmberConf: State of Union article in Apr. 2017.

If you’re an ember.js enthusiast, you must know what a routable component is. (If you don’t know what it is, you can read the article above cited and/or the routable components RFC that was been recently closed due to reasons)

At Uniplaces, we like the idea behind routable components. Just because they’ll not be available, it doesn’t mean that we can’t apply some of their principles to our projects… and so we did.

The «one route renders one component» rule

The idea behind routable components is having a component that acts like a route in the sense that it has the route’s logic in it. Essentially, this means that each route is associated with one, and only one, (routable) component.

We mimicked this philosophy to our projects and we came up with the «one route renders one component» rule.

Fig. 2 — «One route renders one component» rule applied to an example route

Using this rule, we know a priori that each route will render only one component — which name must be the route’s name affixed with -page. Every developer knows, given a route’s name, which component it renders. This makes our project a lot more structured and organized.

Step 3 — Data down, actions up

Data down, actions up, also known as DDAU, is considered an Ember best practice for a long time (see the DockYard article from October 14th, 2015).

You pass the data down to the component, but where should you actually mutate the data? Components shouldn’t mutate data, as they are responsible for the templating. Unfortunately, this is something we actually do quite often.

It’s easy to fall in love with two-way bindings, but that can lead into serious problems. That’s why shifting to one-way bindings (DDAU) makes your app easier to reason about and debug, and is generally the idiomatic way of building Ember apps going forward. There should only be one single point of failure — most likely in your route.

And now you ask yourself: what about the input helper? It has explicit two-way binding!

You’re pretty damn right about that! But feat not, as some great contributors to the Ember community came up with ember-one-way-controls.

One-way controls do not mutate the data when it changes. Instead, they trigger an update action with the new value. This is DDAU done right!

Step 4 — Component-bound stylesheets

Front-end developers know the pain of maintaining global styles. One ends up sharing styles between unrelated contexts to avoid duplicated code. This can lead to unwanted styles applied to new components due to name clashing.

Erik Bryn’s ember-component-css helps keeping your styles contained using pods structure.

ember-component-css’s readme section about usage with pods structure

The styles specified in this style file are only applied to the template of that pod. This way we have separate styles sheets for each pod that are isolated from the rest of you application.

Step 5— Use enumerables

Fig.3 — Example of an enumerable

Although not playing a major role in this five-step guide, enumerables save you from having hard-coded strings everywhere in your code. The convention is that every enumerable file is always affixed with -type, except some really special cases. Concluding, hard-coded strings and/or magic numbers are bad for your project’s health.

Summary

This is the part where I present a TL;DR a.k.a. summary. This five step recipe played a major part in keeping our projects healthy at Uniplaces:

  1. Use pods structure
  2. Match each route to one routable component
  3. Avoid mutating data on your components
  4. Use ember-component-css
  5. Never hardcode stuff

Thank you for reading and I hope you enjoyed it. Every feedback is welcome!

--

--

André Joaquim

Product Engineer at Trouva and an Ember.js enthusiast