diff --git a/core/core.services.yml b/core/core.services.yml
index 8bce755..cdc7818 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -1653,4 +1653,6 @@ services:
   response_filter.rss.relative_url:
     class: Drupal\Core\EventSubscriber\RssResponseRelativeUrlFilter
     tags:
-      - { name: event_subscriber }
+  plugin.manager.entity.display_component_handler:
+    class: Drupal\Core\Entity\DisplayComponentHandlerPluginManager
+    parent: default_plugin_manager
diff --git a/core/lib/Drupal/Core/Entity/Entity/EntityFormDisplay.php b/core/lib/Drupal/Core/Entity/Entity/EntityFormDisplay.php
index cd90ecc..744deb7 100644
--- a/core/lib/Drupal/Core/Entity/Entity/EntityFormDisplay.php
+++ b/core/lib/Drupal/Core/Entity/Entity/EntityFormDisplay.php
@@ -129,33 +129,6 @@ public function __construct(array $values, $entity_type) {
   /**
    * {@inheritdoc}
    */
-  public function getRenderer($field_name) {
-    if (isset($this->plugins[$field_name])) {
-      return $this->plugins[$field_name];
-    }
-
-    // Instantiate the widget object from the stored display properties.
-    if (($configuration = $this->getComponent($field_name)) && isset($configuration['type']) && ($definition = $this->getFieldDefinition($field_name))) {
-      $widget = $this->pluginManager->getInstance(array(
-        'field_definition' => $definition,
-        'form_mode' => $this->originalMode,
-        // No need to prepare, defaults have been merged in setComponent().
-        'prepare' => FALSE,
-        'configuration' => $configuration
-      ));
-    }
-    else {
-      $widget = NULL;
-    }
-
-    // Persist the widget object.
-    $this->plugins[$field_name] = $widget;
-    return $widget;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function buildForm(FieldableEntityInterface $entity, array &$form, FormStateInterface $form_state) {
     // Set #parents to 'top-level' by default.
     $form += array('#parents' => array());
diff --git a/core/lib/Drupal/Core/Entity/EntityDisplayBase.php b/core/lib/Drupal/Core/Entity/EntityDisplayBase.php
index b6c73e5..053f661 100644
--- a/core/lib/Drupal/Core/Entity/EntityDisplayBase.php
+++ b/core/lib/Drupal/Core/Entity/EntityDisplayBase.php
@@ -79,6 +79,11 @@
   protected $hidden = array();
 
   /**
+   * The renderer objects used for this display, keyed by component name.
+   */
+  protected $renderers = array();
+
+  /**
    * The original view or form mode that was requested (case of view/form modes
    * being configured to fall back to the 'default' display).
    *
@@ -115,6 +120,18 @@
   protected $renderer;
 
   /**
+   * A mapping of display elements and its corresponding handler.
+   */
+  protected $handlers;
+
+  /**
+   * The display component handler plugin manager.
+   *
+   * @var \Drupal\Core\Entity\DisplayComponentHandlerPluginManager
+   */
+  protected $handlerManager;
+
+  /**
    * {@inheritdoc}
    */
   public function __construct(array $values, $entity_type) {
@@ -138,6 +155,8 @@ public function __construct(array $values, $entity_type) {
 
     parent::__construct($values, $entity_type);
 
+    $this->handlerManager = \Drupal::service('plugin.manager.entity.display_component_handler');
+
     $this->originalMode = $this->mode;
 
     $this->init();
@@ -321,13 +340,14 @@ public function calculateDependencies() {
    */
   public function toArray() {
     $properties = parent::toArray();
-    // Do not store options for fields whose display is not set to be
-    // configurable.
-    foreach ($this->getFieldDefinitions() as $field_name => $definition) {
-      if (!$definition->isDisplayConfigurable($this->displayContext)) {
-        unset($properties['content'][$field_name]);
-        unset($properties['hidden'][$field_name]);
-      }
+
+    // Let the component handlers add missing components.
+    if (!$this->handlerManager) {
+      $this->handlerManager = \Drupal::service('plugin.manager.entity.display_component_handler');
+    }
+    $handlers = $this->handlerManager->getDefinitions();
+    foreach (array_keys($handlers) as $type) {
+      $properties = $this->getComponentHandler($type)->massageOut($properties);
     }
 
     return $properties;
@@ -366,16 +386,20 @@ public function setComponent($name, array $options = array()) {
       $options['weight'] = isset($max) ? $max + 1 : 0;
     }
 
-    // For a field, fill in default options.
-    if ($field_definition = $this->getFieldDefinition($name)) {
-      $options = $this->pluginManager->prepareConfiguration($field_definition->getType(), $options);
+    // Massage in some values.
+    $handler = $this->getComponentHandlerByElementName($name);
+    if ($handler) {
+      $options = $handler->massageIn($name, $options);
     }
 
     // Ensure we always have an empty settings and array.
     $options += ['settings' => [], 'third_party_settings' => []];
 
     $this->content[$name] = $options;
+
+    // Unset these to ensure new settings are picked up.
     unset($this->hidden[$name]);
+    unset($this->renderers[$name]);
     unset($this->plugins[$name]);
 
     return $this;
@@ -595,4 +619,69 @@ protected function getLogger() {
     return \Drupal::logger('system');
   }
 
+  /**
+   * Finds component handler by element name.
+   *
+   * @param string $name
+   *   The element name.
+   *
+   * @return \Drupal\Core\Entity\DisplayComponentHandlerInterface
+   */
+  public function getComponentHandlerByElementName($name) {
+    if (!isset($this->handlers[$name])) {
+      $handlers = $this->handlerManager->getDefinitions();
+      foreach (array_keys($handlers) as $type) {
+        $handler = $this->getComponentHandler($type);
+        if ($handler && $handler->hasElement($name)) {
+          break;
+        }
+        $handler = NULL;
+      }
+      $this->handlers[$name] = $handler;
+    }
+
+    return $this->handlers[$name];
+  }
+
+  /**
+   * Instantiates component handler.
+   *
+   * @param string $type
+   *   The type of component handler (field, extra_field).
+   *
+   * @return \Drupal\Core\Entity\DisplayComponentHandlerInterface
+   */
+  public function getComponentHandler($type) {
+    $handler = $this->handlerManager->getInstance(array('type' => $type));
+    if ($handler) {
+      $handler->setContext(array(
+        'entity_type' => $this->targetEntityType,
+        'bundle' => $this->bundle,
+        'mode' => $this->originalMode,
+        'display_context' => $this->displayContext,
+      ));
+    }
+    return $handler;
+  }
+
+  /**+
+   * {@inheritdoc}
+   */
+  public function getRenderer($name) {
+    if (!isset($this->content[$name])) {
+      return NULL;
+    }
+
+    if (!array_key_exists($name, $this->renderers)) {
+      if ($handler = $this->getComponentHandlerByElementName($name)) {
+        $options = $this->getComponent($name);
+        $this->renderers[$name] = $handler->getRenderer($name, $options);
+      }
+      else {
+        $this->renderers[$name] = NULL;
+      }
+    }
+    return $this->renderers[$name];
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityViewBuilder.php b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php
index 1b3e6c0..4c7f7e4 100644
--- a/core/lib/Drupal/Core/Entity/EntityViewBuilder.php
+++ b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php
@@ -465,6 +465,12 @@ protected function getSingleFieldDisplay($entity, $field_name, $display_options)
       $bundle = $entity->bundle();
       $key = $entity_type_id . ':' . $bundle . ':' . $field_name . ':' . Crypt::hashBase64(serialize($display_options));
       if (!isset($this->singleFieldDisplays[$key])) {
+
+        $definitions = $this->entityManager->getBaseFieldDefinitions($entity_type_id);
+        if (isset($definitions[$field_name])) {
+          $display_options = \Drupal::service('plugin.manager.field.formatter')->prepareConfiguration($definitions[$field_name]->getType(), $display_options);
+        }
+
         $this->singleFieldDisplays[$key] = EntityViewDisplay::create(array(
           'targetEntityType' => $entity_type_id,
           'bundle' => $bundle,
diff --git a/core/lib/Drupal/Core/Entity/entity.api.php b/core/lib/Drupal/Core/Entity/entity.api.php
index 9f6ef8b..bda7740 100644
--- a/core/lib/Drupal/Core/Entity/entity.api.php
+++ b/core/lib/Drupal/Core/Entity/entity.api.php
@@ -2017,5 +2017,20 @@ function hook_entity_extra_field_info_alter(&$info) {
 }
 
 /**
+ * Modify the list of available component handler plugins.
+ *
+ * This hook may be used to modify plugin properties after they have been
+ * specified by other modules.
+ *
+ * @param $plugins
+ *   An array of all the existing plugin definitions, passed by reference.
+ *
+ * @see DisplayComponentHandlerPluginManager
+ */
+function hook_display_component_handler_info_alter(array &$plugins) {
+  $plugins['someplugin']['label'] = t('Better name');
+}
+
+/**
  * @} End of "addtogroup hooks".
  */
diff --git a/core/lib/Drupal/Core/Field/FormatterPluginManager.php b/core/lib/Drupal/Core/Field/FormatterPluginManager.php
index ca9bd06..65e1d3a 100644
--- a/core/lib/Drupal/Core/Field/FormatterPluginManager.php
+++ b/core/lib/Drupal/Core/Field/FormatterPluginManager.php
@@ -56,6 +56,12 @@ public function createInstance($plugin_id, array $configuration = array()) {
     $plugin_definition = $this->getDefinition($plugin_id);
     $plugin_class = DefaultFactory::getPluginClass($plugin_id, $plugin_definition);
 
+    // @TODO, is this missing somewhere else?
+    if (!isset($configuration['label'])) {
+      $configuration['label'] = '';
+      assert(FALSE, sprintf('The %s does not have a label', $plugin_id));
+    }
+
     // @todo This is copied from \Drupal\Core\Plugin\Factory\ContainerFactory.
     //   Find a way to restore sanity to
     //   \Drupal\Core\Field\FormatterBase::__construct().
