Recursive component JSON configuration builder
Good things

This code uses const for variables that don't get re-assigned.

The functions are concise, though some of the lines are a bit long due to ternary operators.

Suggestions

Bear in mind that functional programming is typically slower than imperative because each iteration leads to a function being added to the call stack. This would be noticeable with large data sets. Having the function addResult() seems like an excess step since it is only called in one spot. The lines to ensure the object at the given key is an array and push an element to that array could simply exist in the callback to the _.reduce() call. 

Also, instead of either creating a new array with the data item or pushing it into an existing array, it could create an empty array when appropriate and then always push the data. This may be slightly less performant but requires fewer lines of code than storing the data in a temporary variable.

function createConfiguration(configuration) {
  return _.reduce(configuration.components, (result, data) =&gt; {
    const component = data.$ref ? getComponentByReference(data) : data;
    if(!result[component.key]) {
      result[component.key] = [];
    }
    result[component.key].push(component.components ? { ...component, components: createConfiguration(component) } : component)
    return result;
  }, {});
}


Unless you fully understand the ways Automatic semicolon insertion can be broken by certain statements, add semi-colons to terminate the lines.