Tech @ Runtastic • 19.07.2017 • Runtastic Tech Team

How to Create Easily Shareable Ember Components

by Thomas Eilmsteiner, Software Engineer Web

When we started building our Ember apps, we soon figured out that we wanted to have one place to share stylesheets, L10N and components as well as config files across all the different apps we create and maintain. Why did we want to do this? To keep everything maintainable and DRY (Don’t Repeat Yourself). Initially, we created a small, lightweight Ember addon we could easily include in all apps without encountering problems.

The longer we worked with this approach, the more we realized that we didn’t need all the shared content everywhere, but some of it still needed to be shared with a few apps. How could we avoid moving everything back into the apps directly or maintain different shared addons without increasing the payload size of each single app?

Every single piece of code from the shared addon got added in the compiled code, which caused the app size to grow without using all the pieces in the stack.
The first noticeable problem was that the page performance slowed and the page load time grew. Not nice. For us as developers, it quickly started to get annoying as the server startup and building of the apps took longer and longer. And nobody likes to wait – not for page load and even less when developing cool new things.

Correct puzzle piece

Only include what is needed

We introduced a way to include only the parts of our shared addon that we actually need (or exclude those we don’t). Depending on your use case, you can decide if you use a whitelist or a blacklist approach.

module.exports = function(defaults) {
  const app = EmberApp(defaults, {
    ...
    'shared-addon': {
      only: [                        
        'controllers/*',
        'initializers/*',
        'mixins/*',
        'utils/**',
        'navigation/-footer.*',
      ]
    }
  });
  ...
};
Drastically decrease the payload size of your Ember.js app with black- & whitelisting! Click To Tweet

In the “only” array, you can add parts of the shared addon you want to use in your app. Everything else will be excluded. This is the whitelist approach. You just add what you need.

It is also possible to follow the blacklist approach, which means you add an “except” array and define everything you don’t want to use.

module.exports = function(defaults) {
  const app = EmberApp(defaults, {
    ...
    'shared-addon': {
      except: [
        'initializers/*',
        'mixins/*',
        'utils/**'
      ]
    }
  });
  ...
};

Whitelist vs. Blacklist

Depending on the size and complexity of your shared addon, the whitelist approach will be the easier one to use and maintain in an ongoing project. Why? The shared addon will continue to grow the more features you build. With a whitelist, you are sure that only the parts you really need are included in your existing apps. With the blacklist, you always need to exclude every single unused part from every single app.

Both methods can be very helpful, but what really matters is finding the right approach for your needs.

Dependency Blacklisting

As an additional step, we added dependency blacklisting. This is another useful list to keep your app small when using a shared addon. Usually, every dependency from your package.json file is included in your build. However, by excluding some parts of the addon, you probably don’t need all the packages. Luckily, it’s also possible to blacklist package dependencies.

module.exports = function(defaults) {
  const app = RuntasticApp(defaults, {
    ...
    'shared-addon': {
      only: [                        
       ...
      ],
      excludedDependencies: [
        'ember-other-func'
      ]
    }
  });
  ...
};

You can find the necessary code snippets in this repo. This approach is inspired by DockYard’s ember-composable-helper. To use it, include the code in your index.js file and try it out in your own projects.

Conclusion

Using a shared addon as the library for parts of your code you want to re-use at various places is a good thing.
Adding the possibility to control what will be included or excluded makes it awesome and easy to maintain. When working in a team or across several teams on different projects, this helps to create shareable snippets for all projects.

What do you think about this solution? Be sure to drop us some feedback or suggest a correction if you spot a mistake. We’d love to hear from you!

P.S.: We’re looking for you!

***

Runtastic Tech Team

We are made up of all the technical departments at Runtastic like iOS, Android, Web, Infrastructure, Data Engineering, etc. We're eager to tell you about how we work here at Runtastic, what our processes look like, the cool stuff we create and what we have learned along the way. And BTW we are always looking for talented people who want to join us!
View all posts by Runtastic Tech Team »