What “bloat” means

When people complain about “bloat” in software, they often mean that every new feature makes it slower to load, takes more memory, and taxes their CPU.

We know that our users are sensitive to performance: they are likely playing a visually intense game while talking on Discord with their friends and the last thing we want to do is cause performance issues. We always keep this in mind when adding new features like video chat, screen sharing, or the overlay.

For our desktop app, we achieve great performance while adding features with something called code splitting which loads code on demand.

How Discord Stays Lean

Every time you load an app, it has to load up code and layout styles in order to run. Each piece of this takes time to load and parse while increasing the app’s memory usage. Segmenting the code required to get the app going makes it load faster and use less memory than if we bundled it all together. This also means that not all of the code is available instantly, but if the bundles are kept small and are well-planned, the user will not experience the loading anyway.

When you boot up Discord, the core set of JavaScript, fonts, images, and stylesheets is about 700KB: about the size of Google’s minimal homepage in a browser. Everything else is loaded on-demand, allowing users to get the parts that matter most to them quickly (and so new users responding to invites don’t need to load the whole web app).

The Real Deal: Code Splitting

As you switch around different views in Discord, you are switching routes through the codebase. We wrap the components for each route in a function which gets called when you arrive at the route. The tool we use to bundle and optimize our code, called webpack, bundles these routes into separate chunks and automates most of the loading.

A problem with this loader is that it can potentially fail to load a chunk. When this happens, the component does not not appear and an error is thrown. To remedy this, we built a custom loader called makeLazy which continues trying at increasing intervals until it succeeds:

The makeLazy asynchronous component loader, with backoff retry. If the function signatures look strange to you, it’s because we use Flow typing here at Discord.

The routes also contain stylesheets to layout the screens. Like our code, our stylesheets are split into loadable chunks and only arrive when needed. Even our animations throughout the app are lazy loaded which allows us to continue adding art and polish while keeping performance high.

Additionally, we support a lot of translations in the app. Code splitting allows us to load only the one you use. You might notice this when switching locales because it takes a moment to load the new one. This is our code splitting dynamically loading the required chunk to display the language.

With this technique, we’re able to support as many unique languages as we want without impacting performance. We currently have 27 translations, so at 30KB each this saves the user nearly 1MB.

Code splitting lets us add languages, features, and polish without bloating the app. Performance is a core feature of Discord. As we continue to improve the app, we will be sure to keep it lean and fast.

We’re always looking for the next great addition to our engineering teams at Discord. Check out our available positions here.