diff --git a/core/includes/entity.api.php b/core/includes/entity.api.php
index 88a8015..d64a01a 100644
--- a/core/includes/entity.api.php
+++ b/core/includes/entity.api.php
@@ -326,7 +326,7 @@ function hook_entity_view(\Drupal\Core\Entity\EntityInterface $entity, \Drupal\e
   // Only do the extra work if the component is configured to be displayed.
   // This assumes a 'mymodule_addition' extra field has been defined for the
   // entity bundle in hook_field_extra_fields().
-  if ($display->getComponent('mymodule_addition')) {
+  if ($display->getComponent('extra_field', 'mymodule_addition')) {
     $entity->content['mymodule_addition'] = array(
       '#markup' => mymodule_addition($entity),
       '#theme' => 'mymodule_my_additional_field',
@@ -396,7 +396,7 @@ function hook_entity_prepare_view($entity_type, array $entities, array $displays
     // defined for the entity bundle in hook_field_extra_fields().
     $ids = array();
     foreach ($entities as $id => $entity) {
-      if ($displays[$entity->bundle()]->getComponent('mymodule_addition')) {
+      if ($displays[$entity->bundle()]->getComponent('extra_field', 'mymodule_addition')) {
         $ids[] = $id;
       }
     }
@@ -442,11 +442,9 @@ function hook_entity_view_mode_alter(&$view_mode, Drupal\Core\Entity\EntityInter
 function hook_entity_display_alter(\Drupal\entity\Plugin\Core\Entity\EntityDisplay $display, array $context) {
   // Leave field labels out of the search index.
   if ($context['entity_type'] == 'node' && $context['view_mode'] == 'search_index') {
-    foreach ($display->getComponents() as $name => $options) {
-      if (isset($options['label'])) {
-        $options['label'] = 'hidden';
-        $display->setComponent($name, $options);
-      }
+    foreach ($display->getComponents('field') as $name => $options) {
+      $options['label'] = 'hidden';
+      $display->setComponent('field', $name, $options);
     }
   }
 }
diff --git a/core/includes/entity.inc b/core/includes/entity.inc
index 9994406..fd14945 100644
--- a/core/includes/entity.inc
+++ b/core/includes/entity.inc
@@ -670,12 +670,12 @@ function entity_view_multiple(array $entities, $view_mode, $langcode = NULL) {
  *   hidden on article nodes in the 'default' display.
  * @code
  * entity_get_display('node', 'article', 'default')
- *   ->setComponent('body', array(
- *     'type' => 'text_summary_or_trimmed',
+ *   ->setComponent('field', 'body', array(
+ *     'formatter' => 'text_summary_or_trimmed',
  *     'settings' => array('trim_length' => '200')
  *     'weight' => 1,
  *   ))
- *   ->removeComponent('field_image')
+ *   ->removeComponent('field', 'field_image')
  *   ->save();
  * @endcode
  *
diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php
index 2153250..3d39944 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormController.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormController.php
@@ -210,7 +210,7 @@ public function processForm($element, $form_state, $form) {
     // Hide extra fields.
     $extra_fields = field_info_extra_fields($this->entity->entityType(), $this->entity->bundle(), 'form');
     foreach ($extra_fields as $extra_field => $info) {
-      if (!$this->getFormDisplay($form_state)->getComponent($extra_field)) {
+      if (!$this->getFormDisplay($form_state)->getComponent('extra_field', $extra_field)) {
         $element[$extra_field]['#access'] = FALSE;
       }
     }
diff --git a/core/modules/block/custom_block/custom_block.module b/core/modules/block/custom_block/custom_block.module
index 0a3efde..7ee1cc1 100644
--- a/core/modules/block/custom_block/custom_block.module
+++ b/core/modules/block/custom_block/custom_block.module
@@ -205,7 +205,7 @@ function custom_block_add_body_field($block_type_id, $label = 'Block body') {
 
     // Assign display settings for 'default' view mode.
     entity_get_display('custom_block', $block_type_id, 'default')
-      ->setComponent('block_body', array(
+      ->setComponent('field', 'block_body', array(
         'label' => 'hidden',
         'type' => 'text_default',
       ))
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockFieldTest.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockFieldTest.php
index da5ac4f..2a42193 100644
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockFieldTest.php
+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Tests/CustomBlockFieldTest.php
@@ -85,7 +85,7 @@ public function testBlockFields() {
       ))
       ->save();
     entity_get_display('custom_block', 'link', 'default')
-      ->setComponent($this->field['field_name'], array(
+      ->setComponent('field', $this->field['field_name'], array(
         'type' => 'link',
         'label' => 'hidden',
       ))
diff --git a/core/modules/comment/comment.api.php b/core/modules/comment/comment.api.php
index ec1707f..262eaf2 100644
--- a/core/modules/comment/comment.api.php
+++ b/core/modules/comment/comment.api.php
@@ -95,7 +95,7 @@ function hook_comment_view(\Drupal\comment\Plugin\Core\Entity\Comment $comment,
   // Only do the extra work if the component is configured to be displayed.
   // This assumes a 'mymodule_addition' extra field has been defined for the
   // node type in hook_field_extra_fields().
-  if ($display->getComponent('mymodule_addition')) {
+  if ($display->getComponent('extra_field', 'mymodule_addition')) {
     $comment->content['mymodule_addition'] = array(
       '#markup' => mymodule_addition($comment),
       '#theme' => 'mymodule_my_additional_field',
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index e5750c6..54ee0ff 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -356,9 +356,9 @@ function _comment_body_field_create($info) {
 
     // Assign display settings for the 'default' view mode.
     entity_get_display('comment', 'comment_node_' . $info->type, 'default')
-      ->setComponent('comment_body', array(
+      ->setComponent('field', 'comment_body', array(
         'label' => 'hidden',
-        'type' => 'text_default',
+        'formatter' => 'text_default',
         'weight' => 0,
       ))
       ->save();
diff --git a/core/modules/contact/lib/Drupal/contact/MessageRenderController.php b/core/modules/contact/lib/Drupal/contact/MessageRenderController.php
index f8aca5d..c052607 100644
--- a/core/modules/contact/lib/Drupal/contact/MessageRenderController.php
+++ b/core/modules/contact/lib/Drupal/contact/MessageRenderController.php
@@ -24,7 +24,7 @@ public function buildContent(array $entities, array $displays, $view_mode, $lang
     foreach ($entities as $entity) {
       // Add the message extra field, if enabled.
       $display = $displays[$entity->bundle()];
-      if ($entity->getMessage() && $display->getComponent('message')) {
+      if ($entity->getMessage() && $display->getComponent('extra_field', 'message')) {
         $entity->content['message'] = array(
           '#type' => 'item',
           '#title' => t('Message'),
diff --git a/core/modules/datetime/lib/Drupal/datetime/Tests/DatetimeFieldTest.php b/core/modules/datetime/lib/Drupal/datetime/Tests/DatetimeFieldTest.php
index a0538d7..51af4c3 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Tests/DatetimeFieldTest.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Tests/DatetimeFieldTest.php
@@ -79,12 +79,12 @@ function setUp() {
       ->save();
 
     $this->display_options = array(
-      'type' => 'datetime_default',
+      'formatter' => 'datetime_default',
       'label' => 'hidden',
       'settings' => array('format_type' => 'medium'),
     );
     entity_get_display($this->instance->entity_type, $this->instance->bundle, 'full')
-      ->setComponent($this->field->id(), $this->display_options)
+      ->setComponent('field', $this->field->id(), $this->display_options)
       ->save();
   }
 
@@ -131,7 +131,7 @@ function testDateField() {
         // Update the entity display settings.
         $this->display_options['settings'] = array($setting => $new_value);
         entity_get_display($this->instance->entity_type, $this->instance->bundle, 'full')
-          ->setComponent($field_name, $this->display_options)
+          ->setComponent('field', $field_name, $this->display_options)
           ->save();
 
         $this->renderTestEntity($id);
@@ -149,7 +149,7 @@ function testDateField() {
     // Verify that the plain formatter works.
     $this->display_options['type'] = 'datetime_plain';
     entity_get_display($this->instance->entity_type, $this->instance->bundle, 'full')
-      ->setComponent($field_name, $this->display_options)
+      ->setComponent('field', $field_name, $this->display_options)
       ->save();
     $expected = $date->format(DATETIME_DATE_STORAGE_FORMAT);
     $this->renderTestEntity($id);
@@ -200,7 +200,7 @@ function testDatetimeField() {
         // Update the entity display settings.
         $this->display_options['settings'] = array($setting => $new_value);
         entity_get_display($this->instance->entity_type, $this->instance->bundle, 'full')
-          ->setComponent($field_name, $this->display_options)
+          ->setComponent('field', $field_name, $this->display_options)
           ->save();
 
         $this->renderTestEntity($id);
@@ -218,7 +218,7 @@ function testDatetimeField() {
     // Verify that the plain formatter works.
     $this->display_options['type'] = 'datetime_plain';
     entity_get_display($this->instance->entity_type, $this->instance->bundle, 'full')
-      ->setComponent($field_name, $this->display_options)
+      ->setComponent('type', $field_name, $this->display_options)
       ->save();
     $expected = $date->format(DATETIME_DATETIME_STORAGE_FORMAT);
     $this->renderTestEntity($id);
diff --git a/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php b/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php
index 8930ace..a90c6aa 100644
--- a/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php
+++ b/core/modules/edit/lib/Drupal/edit/MetadataGenerator.php
@@ -68,7 +68,7 @@ public function generate(EntityInterface $entity, FieldInstance $instance, $lang
     }
 
     // Early-return if no editor is available.
-    $formatter_id = entity_get_render_display($entity, $view_mode)->getRenderer($instance['field_name'])->getPluginId();
+    $formatter_id = entity_get_render_display($entity, $view_mode)->getRenderer('field', $instance['field_name'])->getPluginId();
     $items = $entity->getTranslation($langcode, FALSE)->get($field_name)->getValue();
     $editor_id = $this->editorSelector->getEditor($formatter_id, $instance, $items);
     if (!isset($editor_id)) {
diff --git a/core/modules/edit/lib/Drupal/edit/Tests/EditTestBase.php b/core/modules/edit/lib/Drupal/edit/Tests/EditTestBase.php
index 649f033..41972e8 100644
--- a/core/modules/edit/lib/Drupal/edit/Tests/EditTestBase.php
+++ b/core/modules/edit/lib/Drupal/edit/Tests/EditTestBase.php
@@ -81,10 +81,10 @@ function createFieldWithInstance($field_name, $type, $cardinality, $label, $inst
       ))
       ->save();
 
-    entity_get_display('entity_test', 'entity_test', 'default')
+    entity_get_display('field', 'entity_test', 'entity_test', 'default')
       ->setComponent($field_name, array(
         'label' => 'above',
-        'type' => $formatter_type,
+        'formatter' => $formatter_type,
         'settings' => $formatter_settings
       ))
       ->save();
diff --git a/core/modules/edit/lib/Drupal/edit/Tests/EditorSelectionTest.php b/core/modules/edit/lib/Drupal/edit/Tests/EditorSelectionTest.php
index c1982c5..f365efe 100644
--- a/core/modules/edit/lib/Drupal/edit/Tests/EditorSelectionTest.php
+++ b/core/modules/edit/lib/Drupal/edit/Tests/EditorSelectionTest.php
@@ -49,7 +49,7 @@ function setUp() {
    * editor that Edit selects.
    */
   protected function getSelectedEditor($items, $field_name, $view_mode = 'default') {
-    $options = entity_get_display('entity_test', 'entity_test', $view_mode)->getComponent($field_name);
+    $options = entity_get_display('entity_test', 'entity_test', $view_mode)->getComponent('field', $field_name);
     $field_instance = field_info_instance('entity_test', $field_name, 'entity_test');
     return $this->editorSelector->getEditor($options['type'], $field_instance, $items);
   }
diff --git a/core/modules/editor/lib/Drupal/editor/Tests/EditIntegrationTest.php b/core/modules/editor/lib/Drupal/editor/Tests/EditIntegrationTest.php
index e9e3418..3100995 100644
--- a/core/modules/editor/lib/Drupal/editor/Tests/EditIntegrationTest.php
+++ b/core/modules/editor/lib/Drupal/editor/Tests/EditIntegrationTest.php
@@ -110,7 +110,7 @@ function setUp() {
    * editor that Edit selects.
    */
   protected function getSelectedEditor($items, $field_name, $view_mode = 'default') {
-    $options = entity_get_display('entity_test', 'entity_test', $view_mode)->getComponent($field_name);
+    $options = entity_get_display('entity_test', 'entity_test', $view_mode)->getComponent('field', $field_name);
     $field_instance = field_info_instance('entity_test', $field_name, 'entity_test');
     return $this->editorSelector->getEditor($options['type'], $field_instance, $items);
   }
diff --git a/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php b/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php
index 2d76d76..2292fbe 100644
--- a/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php
+++ b/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php
@@ -84,8 +84,8 @@ function testEmailField() {
       ->save();
     // Create a display for the full view mode.
     entity_get_display('entity_test', 'entity_test', 'full')
-      ->setComponent($field_name, array(
-        'type' => 'email_mailto',
+      ->setComponent('field', $field_name, array(
+        'formatter' => 'email_mailto',
       ))
       ->save();
 
diff --git a/core/modules/entity/entity.services.yml b/core/modules/entity/entity.services.yml
new file mode 100644
index 0000000..44ab004
--- /dev/null
+++ b/core/modules/entity/entity.services.yml
@@ -0,0 +1,4 @@
+services:
+  plugin.manager.entity.display_component_handler:
+    class: Drupal\entity\Plugin\Type\DisplayComponentHandlerPluginManager
+    arguments: ['@container.namespaces']
diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php
index 99008e2..9360955 100644
--- a/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php
+++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayBase.php
@@ -160,12 +160,15 @@ public function createCopy($mode) {
   /**
    * {@inheritdoc}
    */
-  public function getComponents() {
+  public function getComponents($type = '') {
     $result = array();
     foreach ($this->content as $name => $options) {
       if (!isset($options['visible']) || $options['visible'] == TRUE) {
         unset($options['visible']);
         $result[$name] = $options;
+        if (empty($type) || $options['handler_type'] == $type) {
+          $result[$name] = $this->getComponent($options['handler_type'], $name);
+        }
       }
     }
     return $result;
@@ -174,66 +177,42 @@ public function getComponents() {
   /**
    * {@inheritdoc}
    */
-  public function getComponent($name) {
-    // We always store 'extra fields', whether they are visible or hidden.
-    $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, $this->displayContext);
-    if (isset($extra_fields[$name])) {
-      // If we have explicit settings, return an array or NULL depending on
-      // visibility.
-      if (isset($this->content[$name])) {
-        if ($this->content[$name]['visible']) {
-          return array(
-            'weight' => $this->content[$name]['weight'],
-          );
-        }
-        else {
-          return NULL;
-        }
-      }
-
-      // If no explicit settings for the extra field, look at the default
-      // visibility in its definition.
-      $definition = $extra_fields[$name];
-      if (!isset($definition['visible']) || $definition['visible'] == TRUE) {
-        return array(
-          'weight' => $definition['weight']
-        );
-      }
-      else {
-        return NULL;
-      }
+  public function getComponent($type, $name) {
+    if (!isset($this->content[$name]) || $this->content[$name]['handler_type'] !== $type) {
+      return NULL;
     }
 
-    if (isset($this->content[$name])) {
-      return $this->content[$name];
+    $options = $this->content[$name];
+
+    if ($handler = $this->getComponentHandler($type)) {
+      $options = $handler->massageOut($name, $options);
     }
+
+    // The 'handler_type' entry is strictly internal.
+    unset($options['handler_type']);
+
+    return $options;
+
   }
 
   /**
    * {@inheritdoc}
    */
-  public function setComponent($name, array $options = array()) {
+  public function setComponent($type, $name, array $options = array()) {
     // If no weight specified, make sure the field sinks at the bottom.
     if (!isset($options['weight'])) {
       $max = $this->getHighestWeight();
       $options['weight'] = isset($max) ? $max + 1 : 0;
     }
 
-    if ($instance = field_info_instance($this->targetEntityType, $name, $this->bundle)) {
-      $field = field_info_field($instance['field_name']);
-      $options = $this->pluginManager->prepareConfiguration($field['type'], $options);
-
-      // Clear the persisted plugin, if any.
-      unset($this->plugins[$name]);
+    if ($handler = $this->getComponentHandler($type)) {
+      $options = $handler->massageIn($name, $options);
     }
 
-    // We always store 'extra fields', whether they are visible or hidden.
-    $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, $this->displayContext);
-    if (isset($extra_fields[$name])) {
-      $options['visible'] = TRUE;
-    }
+    $this->content[$name] = array('handler_type' => $type) + $options;
 
-    $this->content[$name] = $options;
+    // Clear the associated renderer object.
+    unset($this->renderers[$name]);
 
     return $this;
   }
@@ -241,22 +220,20 @@ public function setComponent($name, array $options = array()) {
   /**
    * {@inheritdoc}
    */
-  public function removeComponent($name) {
-    $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, $this->displayContext);
-    if (isset($extra_fields[$name])) {
-      // 'Extra fields' are exposed in hooks and can appear at any given time.
-      // Therefore we store extra fields that are explicitly being hidden, so
-      // that we can differenciate with those that are simply not configured
-      // yet.
-      $this->content[$name] = array(
-        'visible' => FALSE,
-      );
+  public function removeComponent($type, $name) {
+    if ($handler = $this->getComponentHandler($type)) {
+      $options = $handler->massageIn($name);
+    }
+    if (isset($options)) {
+      $this->content[$name] = array('handler_type' => $type) + $options;
     }
     else {
       unset($this->content[$name]);
-      unset($this->plugins[$name]);
     }
 
+    // Clear the associated renderer object.
+    unset($this->renderers[$name]);
+
     return $this;
   }
 
diff --git a/core/modules/entity/lib/Drupal/entity/EntityDisplayBaseInterface.php b/core/modules/entity/lib/Drupal/entity/EntityDisplayBaseInterface.php
index 06647e7..b6b8a86 100644
--- a/core/modules/entity/lib/Drupal/entity/EntityDisplayBaseInterface.php
+++ b/core/modules/entity/lib/Drupal/entity/EntityDisplayBaseInterface.php
@@ -31,14 +31,21 @@ public function createCopy($view_mode);
   /**
    * Gets the display options for all components.
    *
+   * @param string $type
+   *   The type of the component (i.e. the plugin id of its
+   *   display_component_handler).
+   *
    * @return array
    *   The array of display options, keyed by component name.
    */
-  public function getComponents();
+  public function getComponents($type = '');
 
   /**
    * Gets the display options set for a component.
    *
+   * @param string $type
+   *   The type of the component (i.e. the plugin id of its
+   *   display_component_handler).
    * @param string $name
    *   The name of the component.
    *
@@ -46,11 +53,14 @@ public function getComponents();
    *   The display options for the component, or NULL if the component is not
    *   displayed.
    */
-  public function getComponent($name);
+  public function getComponent($type, $name);
 
   /**
    * Sets the display options for a component.
    *
+   * @param string $type
+   *   The type of the component (i.e. the plugin id of its
+   *   display_component_handler).
    * @param string $name
    *   The name of the component.
    * @param array $options
@@ -59,18 +69,21 @@ public function getComponent($name);
    * @return \Drupal\entity\Plugin\Core\Entity\EntityDisplay
    *   The EntityDisplay object.
    */
-  public function setComponent($name, array $options = array());
+  public function setComponent($type, $name, array $options = array());
 
   /**
    * Sets a component to be hidden.
    *
+   * @param string $type
+   *   The type of the component (i.e. the plugin id of its
+   *   display_component_handler).
    * @param string $name
    *   The name of the component.
    *
    * @return \Drupal\entity\Plugin\Core\Entity\EntityDisplay
    *   The EntityDisplay object.
    */
-  public function removeComponent($name);
+  public function removeComponent($type, $name);
 
   /**
    * Returns the highest weight of the components in the display.
@@ -82,14 +95,17 @@ public function removeComponent($name);
   public function getHighestWeight();
 
   /**
-   * Returns the renderer plugin for a field (e.g. widget, formatter).
+   * Returns the object responsible for rendering the component.
    *
-   * @param string $field_name
-   *   The field name.
+   * @param string $type
+   *   The type of the component (i.e. the plugin id of its
+   *   display_component_handler).
+   * @param string $name
+   *   The component name.
    *
-   * @return \Drupal\field\Plugin\PluginSettingsInterface|null
-   *   A widget or formatter plugin or NULL if the field does not exist.
+   * @return
+   *   If the component is not hidden, the object to use for rendering it.
    */
-  public function getRenderer($field_name);
+  public function getRenderer($type, $name);
 
 }
diff --git a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php
index 78963bc..a3c89e1 100644
--- a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php
+++ b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php
@@ -33,41 +33,72 @@
 class EntityDisplay extends EntityDisplayBase implements EntityDisplayInterface {
 
   /**
+   * The renderer objects used for this display, keyed by component name.
+   */
+  protected $renderers = array();
+
+  /**
+   * The component handler plugin manager.
+   *
+   * @var \Drupal\entity\Plugin\Type\DisplayComponentHandlerPluginManager
+   */
+  protected $handlersManager;
+
+  /**
    * {@inheritdoc}
    */
   public function __construct(array $values, $entity_type) {
     $this->pluginManager = \Drupal::service('plugin.manager.field.formatter');
     $this->displayContext = 'display';
 
+    // Get the 'component handler' plugin manager.
+    $this->handlersManager = drupal_container()->get('plugin.manager.entity.display_component_handler');
+
+    // Let the component handlers add missing components.
+    $handlers = $this->handlersManager->getDefinitions();
+    foreach (array_keys($handlers) as $type) {
+      $this->getComponentHandler($type)->prepareDisplayComponents($this->content);
+    }
+
     parent::__construct($values, $entity_type);
   }
 
   /**
-   * {@inheritdoc}
+   * Returns the component handler plugin for a given component type.
+   *
+   * @param string $type
+   *   The component type.
+   *
+   * @return \Drupal\entity\Plugin\Type\DisplayComponentHandlerBase
+   *   @todo interface instead
+   *   The component handler plugin if it exists, NULL otherwise.
    */
-  public function getRenderer($field_name) {
-    if (isset($this->plugins[$field_name])) {
-      return $this->plugins[$field_name];
-    }
-
-    // Instantiate the formatter object from the stored display properties.
-    if ($configuration = $this->getComponent($field_name)) {
-      $instance = field_info_instance($this->targetEntityType, $field_name, $this->bundle);
-      $formatter = $this->pluginManager->getInstance(array(
-        'field_definition' => $instance,
+  public function getComponentHandler($type) {
+    $handler = $this->handlersManager->getInstance(array('type' => $type));
+    if ($handler) {
+      $handler->setContext(array(
+        'entity_type' => $this->targetEntityType,
+        'bundle' => $this->bundle,
         'view_mode' => $this->originalMode,
-        // No need to prepare, defaults have been merged in setComponent().
-        'prepare' => FALSE,
-        'configuration' => $configuration
       ));
     }
-    else {
-      $formatter = NULL;
-    }
+    return $handler;
+  }
 
-    // Persist the formatter object.
-    $this->plugins[$field_name] = $formatter;
-    return $formatter;
+  /**
+   * {@inheritdoc}
+   */
+  public function getRenderer($type, $name) {
+    if (!isset($this->renderers[$name]) && !array_key_exists($name, $this->renderers)) {
+      $options = $this->getComponent($type, $name);
+      if ($handler = $this->getComponentHandler($type)) {
+        $this->renderers[$name] = $handler->getRenderer($name, $options);
+      }
+      else {
+        $this->renderers[$name] = NULL;
+      }
+    }
+    return $this->renderers[$name];
   }
 
 }
diff --git a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormDisplay.php b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormDisplay.php
index 9a3f0a6..4105613 100644
--- a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormDisplay.php
+++ b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormDisplay.php
@@ -45,13 +45,20 @@ public function __construct(array $values, $entity_type) {
   /**
    * {@inheritdoc}
    */
-  public function getRenderer($field_name) {
+  public function getComponentHandler($type) {
+    return array();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getRenderer($type, $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)) {
+    if ($configuration = $this->getComponent('field', $field_name)) {
       $instance = field_info_instance($this->targetEntityType, $field_name, $this->bundle);
       $widget = $this->pluginManager->getInstance(array(
         'field_definition' => $instance,
diff --git a/core/modules/entity/lib/Drupal/entity/Plugin/Type/DisplayComponentHandlerBase.php b/core/modules/entity/lib/Drupal/entity/Plugin/Type/DisplayComponentHandlerBase.php
new file mode 100644
index 0000000..7431086
--- /dev/null
+++ b/core/modules/entity/lib/Drupal/entity/Plugin/Type/DisplayComponentHandlerBase.php
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\entity\Plugin\Type\DisplayComponentHandlerBase.
+ */
+
+namespace Drupal\entity\Plugin\Type;
+
+use Drupal\Component\Plugin\PluginBase;
+use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
+
+
+// @todo interface
+abstract class DisplayComponentHandlerBase extends PluginBase {
+
+  /**
+   * The context in which the handler is being used.
+   *
+   * @var array
+   */
+  protected $context;
+
+  public function setContext(array $context) {
+    $this->context = $context;
+  }
+
+  public function prepareDisplayComponents(array &$components) { }
+
+  public function massageOut($name, array $options = NULL) {
+    return $options;
+  }
+
+  public function massageIn($name, array $options = NULL) {
+    return $options;
+  }
+
+  public function getRenderer($name, array $options = NULL) { }
+
+}
diff --git a/core/modules/entity/lib/Drupal/entity/Plugin/Type/DisplayComponentHandlerPluginManager.php b/core/modules/entity/lib/Drupal/entity/Plugin/Type/DisplayComponentHandlerPluginManager.php
new file mode 100644
index 0000000..29d1330
--- /dev/null
+++ b/core/modules/entity/lib/Drupal/entity/Plugin/Type/DisplayComponentHandlerPluginManager.php
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\entity\Plugin\Type\DisplayComponentHandlerPluginManager.
+ */
+
+namespace Drupal\entity\Plugin\Type;
+
+use Drupal\Component\Plugin\PluginManagerBase;
+use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
+use Drupal\Core\Plugin\Discovery\AlterDecorator;
+use Drupal\Core\Plugin\Discovery\CacheDecorator;
+use Drupal\Component\Plugin\Factory\DefaultFactory;
+
+/**
+ * Plugin type manager for entity display component handlers.
+ *
+ * The handlers are typically shared for the whole request. getInstance() holds
+ * the instanciated plugins and only instanciates one of each type.
+ */
+class DisplayComponentHandlerPluginManager extends PluginManagerBase {
+
+  /**
+   * The handlers that have already been instanciated by getInstance().
+   *
+   * @var array
+   */
+  protected $plugins = array();
+
+  /**
+   * Constructs a DisplayComponentHandlerPluginManager object.
+   *
+   * @param \Traversable $namespaces
+   *   An object that implements \Traversable which contains the root paths
+   *   keyed by the corresponding namespace to look for plugin implementations,
+   */
+  public function __construct(\Traversable $namespaces) {
+    // @todo document the aletr hook.
+    // @todo cache key / bin ?
+    $this->discovery = new AnnotatedClassDiscovery('entity/display_component_handler', $namespaces);
+    $this->discovery = new AlterDecorator($this->discovery, 'display_component_handler_info');
+    $this->discovery = new CacheDecorator($this->discovery, 'plugin_display_component_handler');
+
+    $this->factory = new DefaultFactory($this->discovery);
+  }
+
+  /**
+   * Overrides PluginManagerBase::getInstance().
+   *
+   * The display component handlers are shared for the whole request.
+   */
+  public function getInstance(array $options) {
+    $plugin_id = $options['type'];
+
+    if (!isset($this->plugins[$plugin_id]) && !array_key_exists($plugin_id, $this->plugins)) {
+      $this->plugins[$plugin_id] = $this->discovery->getDefinition($plugin_id) ? $this->createInstance($plugin_id) : NULL;
+    }
+
+    return $this->plugins[$plugin_id];
+  }
+
+}
diff --git a/core/modules/entity/lib/Drupal/entity/Plugin/entity/display_component_handler/ExtraFieldDisplayComponentHandler.php b/core/modules/entity/lib/Drupal/entity/Plugin/entity/display_component_handler/ExtraFieldDisplayComponentHandler.php
new file mode 100644
index 0000000..b4909b3
--- /dev/null
+++ b/core/modules/entity/lib/Drupal/entity/Plugin/entity/display_component_handler/ExtraFieldDisplayComponentHandler.php
@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\entity\Plugin\entity\display_component_handler\ExtraFieldDisplayComponentHandler.
+ */
+
+namespace Drupal\entity\Plugin\entity\display_component_handler;
+
+use Drupal\Component\Annotation\Plugin;
+use Drupal\entity\Plugin\Type\DisplayComponentHandlerBase;
+
+/**
+ * @todo
+ *
+ * @Plugin(
+ *   id = "extra_field",
+ *   module = "entity"
+ * )
+ */
+class ExtraFieldDisplayComponentHandler extends DisplayComponentHandlerBase {
+
+  public function prepareDisplayComponents(array &$components) {
+    // Add extra fields that are not explicitely configured in the display.
+    $extra_fields = field_info_extra_fields($this->context['entity_type'], $this->context['bundle'], 'display');
+    foreach ($extra_fields as $name => $definition) {
+      if (!isset($components[$name])) {
+        if (!isset($definition['visible']) || $definition['visible'] == TRUE) {
+          $components[$name] = array(
+            'visible' => TRUE,
+            'weight' => $definition['weight'],
+          );
+        }
+        else {
+          $components[$name] = array(
+            'visible' => FALSE,
+          );
+        }
+
+        $components[$name]['handler_type'] = $this->pluginId;
+      }
+    }
+    // @todo : we could add a custom $display->hiddenExtraFields property on the display, and merge them back on save.
+  }
+
+  public function massageOut($name, array $options = NULL) {
+    // We always store 'extra fields', whether they are visible or hidden. Only
+    // return an options array for visible components.
+    if (!empty($options['visible'])) {
+      unset($options['visible']);
+      return $options;
+    }
+  }
+
+  public function massageIn($name, array $options = NULL) {
+    // 'Extra fields' are exposed in hooks and can appear at any given time.
+    // Therefore we store extra fields that are explicitly being hidden, so
+    // that we can differenciate with those that are simply not configured
+    // yet.
+    if (is_null($options)) {
+      $options['visible'] = FALSE;
+    }
+    else {
+      $options['visible'] = TRUE;
+    }
+    return $options;
+  }
+
+}
diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php
index 4337abd..781a26e 100644
--- a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php
+++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php
@@ -45,34 +45,34 @@ public function testEntityDisplayCRUD() {
     // being assigned.
     $expected['component_1'] = array('weight' => 0);
     $expected['component_2'] = array('weight' => 1);
-    $display->setComponent('component_1');
-    $display->setComponent('component_2');
-    $this->assertEqual($display->getComponent('component_1'), $expected['component_1']);
-    $this->assertEqual($display->getComponent('component_2'), $expected['component_2']);
+    $display->setComponent('default', 'component_1');
+    $display->setComponent('default', 'component_2');
+    $this->assertEqual($display->getComponent('default', 'component_1'), $expected['component_1']);
+    $this->assertEqual($display->getComponent('default', 'component_2'), $expected['component_2']);
 
     // Check that arbitrary options are correctly stored.
     $expected['component_3'] = array('weight' => 10, 'foo' => 'bar');
-    $display->setComponent('component_3', $expected['component_3']);
-    $this->assertEqual($display->getComponent('component_3'), $expected['component_3']);
+    $display->setComponent('default', 'component_3', $expected['component_3']);
+    $this->assertEqual($display->getComponent('default', 'component_3'), $expected['component_3']);
 
     // Check that the display can be properly saved and read back.
     $display->save();
     $display = entity_load('entity_display', $display->id());
     foreach (array('component_1', 'component_2', 'component_3') as $name) {
-      $this->assertEqual($display->getComponent($name), $expected[$name]);
+      $this->assertEqual($display->getComponent('default', $name), $expected[$name]);
     }
 
     // Check that getComponents() returns options for all components.
-    $this->assertEqual($display->getComponents(), $expected);
+    $this->assertEqual($display->getComponents('default'), $expected);
 
     // Check that a component can be removed.
-    $display->removeComponent('component_3');
-    $this->assertNULL($display->getComponent('component_3'));
+    $display->removeComponent('default', 'component_3');
+    $this->assertNULL($display->getComponent('default', 'component_3'));
 
     // Check that the removal is correctly persisted.
     $display->save();
     $display = entity_load('entity_display', $display->id());
-    $this->assertNULL($display->getComponent('component_3'));
+    $this->assertNULL($display->getComponent('default', 'component_3'));
 
     // Check that CreateCopy() creates a new component that can be correclty
     // saved.
@@ -95,14 +95,14 @@ public function testEntityGetDisplay() {
     $this->assertTrue($display->isNew());
 
     // Add some components and save the display.
-    $display->setComponent('component_1', array('weight' => 10))
+    $display->setComponent('default', 'component_1', array('weight' => 10))
       ->save();
 
     // Check that entity_get_display() returns the correct object.
     $display = entity_get_display('entity_test', 'entity_test', 'default');
     $this->assertFalse($display->isNew());
     $this->assertEqual($display->id, 'entity_test.entity_test.default');
-    $this->assertEqual($display->getComponent('component_1'), array('weight' => 10));
+    $this->assertEqual($display->getComponent('default', 'component_1'), array('weight' => 10));
   }
 
   /**
@@ -111,20 +111,20 @@ public function testEntityGetDisplay() {
   public function testExtraFieldComponent() {
     $display = entity_create('entity_display', array(
       'targetEntityType' => 'entity_test',
-      'bundle' => 'entity_test',
+      'bundle' => 'bundle_with_extra_fields',
       'mode' => 'default',
     ));
 
     // Check that the default visibility taken into account for extra fields
     // unknown in the display.
-    $this->assertEqual($display->getComponent('display_extra_field'), array('weight' => 5));
-    $this->assertNull($display->getComponent('display_extra_field_hidden'));
+    $this->assertEqual($display->getComponent('extra_field', 'display_extra_field'), array('weight' => 5));
+    $this->assertNull($display->getComponent('extra_field', 'display_extra_field_hidden'));
 
     // Check that setting explicit options overrides the defaults.
-    $display->removeComponent('display_extra_field');
-    $display->setComponent('display_extra_field_hidden', array('weight' => 10));
-    $this->assertNull($display->getComponent('display_extra_field'));
-    $this->assertEqual($display->getComponent('display_extra_field_hidden'), array('weight' => 10));
+    $display->removeComponent('extra_field', 'display_extra_field');
+    $display->setComponent('extra_field', 'display_extra_field_hidden', array('weight' => 10));
+    $this->assertNull($display->getComponent('extra_field', 'display_extra_field'));
+    $this->assertEqual($display->getComponent('extra_field', 'display_extra_field_hidden'), array('weight' => 10));
   }
 
   /**
@@ -154,7 +154,7 @@ public function testFieldComponent() {
     $instance->save();
 
     // Check that providing no options results in default values being used.
-    $display->setComponent($field_name);
+    $display->setComponent('field', $field_name);
     $field_type_info = field_info_field_types($field->type);
     $default_formatter = $field_type_info['default_formatter'];
     $default_settings = field_info_formatter_settings($default_formatter);
@@ -164,10 +164,10 @@ public function testFieldComponent() {
       'type' => $default_formatter,
       'settings' => $default_settings,
     );
-    $this->assertEqual($display->getComponent($field_name), $expected);
+    $this->assertEqual($display->getComponent('field', $field_name), $expected);
 
-    // Check that the getFormatter() method returns the correct formatter plugin.
-    $formatter = $display->getRenderer($field_name);
+    // Check that the getRenderer() method returns the correct formatter plugin.
+    $formatter = $display->getRenderer('field', $field_name);
     $this->assertEqual($formatter->getPluginId(), $default_formatter);
     $this->assertEqual($formatter->getSettings(), $default_settings);
 
@@ -175,26 +175,26 @@ public function testFieldComponent() {
     // arbitrary property and reading it back.
     $random_value = $this->randomString();
     $formatter->randomValue = $random_value;
-    $formatter = $display->getRenderer($field_name);
+    $formatter = $display->getRenderer('field', $field_name);
     $this->assertEqual($formatter->randomValue, $random_value);
 
     // Check that changing the definition creates a new formatter.
-    $display->setComponent($field_name, array(
+    $display->setComponent('field', $field_name, array(
       'type' => 'field_test_multiple',
     ));
-    $formatter = $display->getRenderer($field_name);
+    $formatter = $display->getRenderer('field', $field_name);
     $this->assertEqual($formatter->getPluginId(), 'field_test_multiple');
     $this->assertFalse(isset($formatter->randomValue));
 
     // Check that specifying an unknown formatter (e.g. case of a disabled
     // module) gets stored as is in the display, but results in the default
     // formatter being used.
-    $display->setComponent($field_name, array(
+    $display->setComponent('field', $field_name, array(
       'type' => 'unknown_formatter',
     ));
-    $options = $display->getComponent($field_name);
+    $options = $display->getComponent('field', $field_name);
     $this->assertEqual($options['type'], 'unknown_formatter');
-    $formatter = $display->getRenderer($field_name);
+    $formatter = $display->getRenderer('field', $field_name);
     $this->assertEqual($formatter->getPluginId(), $default_formatter);
   }
 
@@ -252,14 +252,14 @@ public function testDeleteFieldInstance() {
       'targetEntityType' => 'entity_test',
       'bundle' => 'entity_test',
       'viewMode' => 'default',
-    ))->setComponent($field_name)->save();
+    ))->setComponent('field', $field_name)->save();
 
     // Delete the instance.
     $instance->delete();
 
     // Check that the component has been removed from the entity display.
     $display = entity_get_display('entity_test', 'entity_test', 'default');
-    $this->assertFalse($display->getComponent($field_name));
+    $this->assertFalse($display->getComponent('field', $field_name));
   }
 
 }
diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc
index ff28636..d0a2453 100644
--- a/core/modules/field/field.attach.inc
+++ b/core/modules/field/field.attach.inc
@@ -402,7 +402,7 @@ function _field_invoke_get_instances($entity_type, $bundle, $options) {
  */
 function _field_invoke_widget_target($form_display) {
   return function ($instance) use ($form_display) {
-    return $form_display->getRenderer($instance['field_name']);
+    return $form_display->getRenderer('widget', $instance['field_name']);
   };
 }
 
@@ -1048,7 +1048,7 @@ function field_attach_prepare_view($entity_type, array $entities, array $display
   // the entity display.
   $target_function = function ($instance) use ($displays) {
     if (isset($displays[$instance['bundle']])) {
-      return $displays[$instance['bundle']]->getRenderer($instance['field_name']);
+      return $displays[$instance['bundle']]->getRenderer('field', $instance['field_name']);
     }
   };
   $null = NULL;
@@ -1093,7 +1093,7 @@ function field_attach_view(EntityInterface $entity, EntityDisplay $display, $lan
   // For each instance, call the view() method on the formatter object handed
   // by the entity display.
   $target_function = function ($instance) use ($display) {
-    return $display->getRenderer($instance['field_name']);
+    return $display->getRenderer('field', $instance['field_name']);
   };
   $null = NULL;
   $output = field_invoke_method('view', $target_function, $entity, $null, $null, $options);
diff --git a/core/modules/field/field.info.inc b/core/modules/field/field.info.inc
index 932f6b2..6607283 100644
--- a/core/modules/field/field.info.inc
+++ b/core/modules/field/field.info.inc
@@ -129,7 +129,7 @@ function _field_info_collate_types_reset() {
  */
 function field_behaviors_widget($op, $instance) {
   $info = array();
-  if ($component = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')->getComponent($instance['field_name'])) {
+  if ($component = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')->getComponent('field', $instance['field_name'])) {
     $info = field_info_widget_types($component['type']);
   }
   return isset($info[$op]) ? $info[$op] : FIELD_BEHAVIOR_DEFAULT;
diff --git a/core/modules/field/field.install b/core/modules/field/field.install
index b425169..ead2319 100644
--- a/core/modules/field/field.install
+++ b/core/modules/field/field.install
@@ -135,6 +135,7 @@ function field_update_8002() {
 
       // We do not need the 'module' key anymore.
       unset($widget_options['module']);
+      $display_options['handler_type'] = 'field';
       $form_displays[$form_display_id]->set("content.$record->field_name", $widget_options);
     }
 
@@ -205,7 +206,10 @@ function field_update_8002() {
             }
 
             // Set options in the display.
-            $new_options = array('visible' => $display_options['visible']);
+            $new_options = array(
+              'handler_type' => 'extra_field',
+              'visible' => $display_options['visible']
+            );
             // The display object only stores the weight for 'visible' extra
             // fields.
             if ($display_options['visible']) {
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 19bf6ed..b460ae4 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -748,7 +748,7 @@ function field_view_value(EntityInterface $entity, $field_name, $item, $display
  *     - label: (string) Position of the label. The default 'field' theme
  *       implementation supports the values 'inline', 'above' and 'hidden'.
  *       Defaults to 'above'.
- *     - type: (string) The formatter to use. Defaults to the
+ *     - formatter: (string) The formatter to use. Defaults to the
  *       'default_formatter' for the field type. The default formatter will also
  *       be used if the requested formatter is not available.
  *     - settings: (array) Settings specific to the formatter. Defaults to the
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php
index 5f7e435..3160f0f 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php
@@ -464,7 +464,7 @@ public function delete($field_cleanup = TRUE) {
 
       // Remove the instance from the entity form displays.
       if ($form_display = entity_load('entity_form_display', $this->entity_type . '.' . $this->bundle . '.default')) {
-        $form_display->removeComponent($this->field->id())->save();
+        $form_display->removeComponent('field', $this->field->id())->save();
       }
 
       // Remove the instance from the entity displays.
@@ -474,7 +474,7 @@ public function delete($field_cleanup = TRUE) {
         $ids[] = $this->entity_type . '.' . $this->bundle . '.' . $view_mode;
       }
       foreach (entity_load_multiple('entity_display', $ids) as $display) {
-        $display->removeComponent($this->field->id())->save();
+        $display->removeComponent('field', $this->field->id())->save();
       }
 
       // Delete the field itself if we just deleted its last instance.
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php
index 39deee9..29385d4 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php
@@ -64,7 +64,7 @@ public function createInstance($plugin_id, array $configuration) {
    *     - label: (string) Position of the label. The default 'field' theme
    *       implementation supports the values 'inline', 'above' and 'hidden'.
    *       Defaults to 'above'.
-   *     - type: (string) The formatter to use. Defaults to the
+   *     - formatter: (string) The formatter to use. Defaults to the
    *       'default_formatter' for the field type, The default formatter will
    *       also be used if the requested formatter is not available.
    *     - settings: (array) Settings specific to the formatter. Each setting
@@ -88,7 +88,7 @@ public function getInstance(array $options) {
     // Switch back to default formatter if either:
     // - $type_info doesn't exist (the widget type is unknown),
     // - the field type is not allowed for the widget.
-    $definition = $this->getDefinition($configuration['type']);
+    $definition = $this->getDefinition($plugin_id);
     if (!isset($definition['class']) || !in_array($field_type, $definition['field_types'])) {
       // Grab the default widget for the field type.
       $field_type_definition = field_info_field_types($field_type);
diff --git a/core/modules/field/lib/Drupal/field/Plugin/entity/display_component_handler/FieldDisplayComponentHandler.php b/core/modules/field/lib/Drupal/field/Plugin/entity/display_component_handler/FieldDisplayComponentHandler.php
new file mode 100644
index 0000000..d47157a
--- /dev/null
+++ b/core/modules/field/lib/Drupal/field/Plugin/entity/display_component_handler/FieldDisplayComponentHandler.php
@@ -0,0 +1,44 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\field\Plugin\entity\display_component_handler\FieldDisplayComponentHandler.
+ */
+
+namespace Drupal\field\Plugin\entity\display_component_handler;;
+
+use Drupal\Component\Annotation\Plugin;
+use Drupal\entity\Plugin\Type\DisplayComponentHandlerBase;
+
+/**
+ * @todo
+ *
+ * @Plugin(
+ *   id = "field",
+ *   module = "field"
+ * )
+ */
+class FieldDisplayComponentHandler extends DisplayComponentHandlerBase {
+
+  public function massageIn($name, array $options = NULL) {
+    if (!is_null($options)) {
+      // @todo do we need to check the field exists on the bundle ?
+      // Do we need a more general check by the handler that the $name is a valid component ?
+      $field = field_info_field($name);
+      return drupal_container()->get('plugin.manager.field.formatter')->prepareConfiguration($field['type'], $options);
+    }
+  }
+
+  public function getRenderer($name, array $options = NULL) {
+    if ($options) {
+      return drupal_container()->get('plugin.manager.field.formatter')->getInstance(array(
+        'field_definition' => field_info_instance($this->context['entity_type'], $name, $this->context['bundle']),
+        'view_mode' => $this->context['view_mode'],
+        'configuration' => $options,
+        // No need to prepare, defaults have been merged when the options were written in the display.
+        'prepare' => FALSE,
+      ));
+    }
+  }
+
+}
diff --git a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
index 0ae63b7..229367c 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
@@ -430,7 +430,7 @@ public function buildOptionsForm(&$form, &$form_state) {
     $options = array(
       'field_definition' => $field,
       'configuration' => array(
-        'type' => $format,
+        'formatter' => $format,
         'settings' => $settings,
         'label' => '',
         'weight' => 0,
@@ -649,7 +649,7 @@ public function getItems($values) {
     }
 
     $display = array(
-      'type' => $this->options['type'],
+      'formatter' => $this->options['type'],
       'settings' => $this->options['settings'],
       'label' => 'hidden',
       // Pass the View object in the display so that fields can act on it.
diff --git a/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php b/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php
index 70195d3..0bf2c0e 100644
--- a/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php
@@ -83,13 +83,13 @@ function setUp() {
 
     $this->display_options = array(
       'default' => array(
-        'type' => 'field_test_default',
+        'formatter' => 'field_test_default',
         'settings' => array(
           'test_formatter_setting' => $this->randomName(),
         ),
       ),
       'teaser' => array(
-        'type' => 'field_test_default',
+        'formatter' => 'field_test_default',
         'settings' => array(
           'test_formatter_setting' => $this->randomName(),
         ),
@@ -100,11 +100,11 @@ function setUp() {
     entity_create('field_instance', $instance)->save();
     // Create a display for the default view mode.
     entity_get_display($instance['entity_type'], $instance['bundle'], 'default')
-      ->setComponent($this->field_name, $this->display_options['default'])
+      ->setComponent('field', $this->field_name, $this->display_options['default'])
       ->save();
     // Create a display for the teaser view mode.
     entity_get_display($instance['entity_type'], $instance['bundle'], 'teaser')
-      ->setComponent($this->field_name, $this->display_options['teaser'])
+      ->setComponent('field', $this->field_name, $this->display_options['teaser'])
       ->save();
 
     // Create an entity with values.
@@ -131,7 +131,7 @@ function testFieldViewField() {
     // Check that explicit display settings are used.
     $display = array(
       'label' => 'hidden',
-      'type' => 'field_test_multiple',
+      'formatter' => 'field_test_multiple',
       'settings' => array(
         'test_formatter_setting_multiple' => $this->randomName(),
         'alter' => TRUE,
@@ -152,7 +152,7 @@ function testFieldViewField() {
     // Check the prepare_view steps are invoked.
     $display = array(
       'label' => 'hidden',
-      'type' => 'field_test_with_prepare_view',
+      'formatter' => 'field_test_with_prepare_view',
       'settings' => array(
         'test_formatter_setting_additional' => $this->randomName(),
       ),
@@ -204,7 +204,7 @@ function testFieldViewValue() {
 
     // Check that explicit display settings are used.
     $display = array(
-      'type' => 'field_test_multiple',
+      'formatter' => 'field_test_multiple',
       'settings' => array(
         'test_formatter_setting_multiple' => $this->randomName(),
       ),
@@ -220,7 +220,7 @@ function testFieldViewValue() {
 
     // Check that prepare_view steps are invoked.
     $display = array(
-      'type' => 'field_test_with_prepare_view',
+      'formatter' => 'field_test_with_prepare_view',
       'settings' => array(
         'test_formatter_setting_additional' => $this->randomName(),
       ),
@@ -262,7 +262,7 @@ function testFieldEmpty() {
     // Uses \Drupal\field_test\Plugin\field\formatter\TestFieldEmptyFormatter.
     $display = array(
       'label' => 'hidden',
-      'type' => 'field_empty_test',
+      'formatter' => 'field_empty_test',
       'settings' => array(
         'test_empty_string' => '**EMPTY FIELD**' . $this->randomName(),
       ),
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php
index 58fb767..b4c487f 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php
@@ -66,7 +66,7 @@ function setUp() {
     // Assign display properties for the 'default' and 'teaser' view modes.
     foreach (array('default', 'teaser') as $view_mode) {
       entity_get_display('node', $content_type, $view_mode)
-        ->setComponent($field['field_name'])
+        ->setComponent('field', $field['field_name'])
         ->save();
     }
 
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php
index 4739d5f..23a3186 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php
@@ -66,22 +66,22 @@ function testFieldAttachView() {
     $formatter_setting = $this->randomName();
     $display_options = array(
       'label' => 'above',
-      'type' => 'field_test_default',
+      'formatter' => 'field_test_default',
       'settings' => array(
         'test_formatter_setting' => $formatter_setting,
       ),
     );
-    $display->setComponent($this->field['field_name'], $display_options);
+    $display->setComponent('field', $this->field['field_name'], $display_options);
 
     $formatter_setting_2 = $this->randomName();
     $display_options_2 = array(
       'label' => 'above',
-      'type' => 'field_test_default',
+      'formatter' => 'field_test_default',
       'settings' => array(
         'test_formatter_setting' => $formatter_setting_2,
       ),
     );
-    $display->setComponent($this->field_2['field_name'], $display_options_2);
+    $display->setComponent('field', $this->field_2['field_name'], $display_options_2);
 
     // View all fields.
     field_attach_prepare_view($entity_type, array($entity->id() => $entity), $displays);
@@ -102,7 +102,7 @@ function testFieldAttachView() {
     // Label hidden.
     $entity = clone($entity_init);
     $display_options['label'] = 'hidden';
-    $display->setComponent($this->field['field_name'], $display_options);
+    $display->setComponent('field', $this->field['field_name'], $display_options);
     field_attach_prepare_view($entity_type, array($entity->id() => $entity), $displays);
     $entity->content = field_attach_view($entity, $display);
     $output = drupal_render($entity->content);
@@ -124,9 +124,9 @@ function testFieldAttachView() {
     // Multiple formatter.
     $entity = clone($entity_init);
     $formatter_setting = $this->randomName();
-    $display->setComponent($this->field['field_name'], array(
+    $display->setComponent('field', $this->field['field_name'], array(
       'label' => 'above',
-      'type' => 'field_test_multiple',
+      'formatter' => 'field_test_multiple',
       'settings' => array(
         'test_formatter_setting_multiple' => $formatter_setting,
       ),
@@ -144,9 +144,9 @@ function testFieldAttachView() {
     // Test a formatter that uses hook_field_formatter_prepare_view().
     $entity = clone($entity_init);
     $formatter_setting = $this->randomName();
-    $display->setComponent($this->field['field_name'], array(
+    $display->setComponent('field', $this->field['field_name'], array(
       'label' => 'above',
-      'type' => 'field_test_with_prepare_view',
+      'formatter' => 'field_test_with_prepare_view',
       'settings' => array(
         'test_formatter_setting_additional' => $formatter_setting,
       ),
@@ -197,7 +197,7 @@ function testFieldAttachPrepareViewMultiple() {
 
     $display_2 = entity_get_display('entity_test', 'test_bundle_2', 'full')
       ->setComponent($this->field['field_name'], array(
-        'type' => 'field_test_with_prepare_view',
+        'formatter' => 'field_test_with_prepare_view',
         'settings' => array(
           'test_formatter_setting_additional' => $formatter_setting,
         ),
diff --git a/core/modules/field/lib/Drupal/field/Tests/Views/FieldUITest.php b/core/modules/field/lib/Drupal/field/Tests/Views/FieldUITest.php
index 5c9b253..0ede906 100644
--- a/core/modules/field/lib/Drupal/field/Tests/Views/FieldUITest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/Views/FieldUITest.php
@@ -50,7 +50,7 @@ public function testHandlerUI() {
     $this->drupalGet($url);
 
     // Tests the available formatter options.
-    $result = $this->xpath('//select[@id=:id]/option', array(':id' => 'edit-options-type'));
+    $result = $this->xpath('//select[@id=:id]/option', array(':id' => 'edit-options-formatter'));
     $options = array_map(function($item) {
       return (string) $item->attributes()->value[0];
     }, $result);
@@ -58,10 +58,10 @@ public function testHandlerUI() {
     sort($options, SORT_STRING);
     $this->assertEqual($options, array('text_default', 'text_plain', 'text_trimmed'), 'The text formatters for a simple text field appear as expected.');
 
-    $this->drupalPost(NULL, array('options[type]' => 'text_trimmed'), t('Apply'));
+    $this->drupalPost(NULL, array('options[formatter]' => 'text_trimmed'), t('Apply'));
 
     $this->drupalGet($url);
-    $this->assertOptionSelected('edit-options-type', 'text_trimmed');
+    $this->assertOptionSelected('edit-options-formatter', 'text_trimmed');
 
     $random_number = rand(100, 400);
     $this->drupalPost(NULL, array('options[settings][trim_length]' => $random_number), t('Apply'));
diff --git a/core/modules/field/tests/modules/field_test/field_test.module b/core/modules/field/tests/modules/field_test/field_test.module
index 800f4d4..06fdf55 100644
--- a/core/modules/field/tests/modules/field_test/field_test.module
+++ b/core/modules/field/tests/modules/field_test/field_test.module
@@ -218,7 +218,7 @@ function field_test_field_formatter_settings_form_alter(&$element, &$form_state,
   $element['field_test_formatter_settings_form_alter'] = array(
     '#type' => 'textfield',
     '#title' => t('Formatter settings form alter'),
-    '#default_value' => $context['formatter']->getSetting('field_test_formatter_settings_form_alter'),
+    '#default_value' => $context['type']->getSetting('field_test_formatter_settings_form_alter'),
   );
 }
 
diff --git a/core/modules/field_ui/field_ui.api.php b/core/modules/field_ui/field_ui.api.php
index 7bcfff0..e908fff 100644
--- a/core/modules/field_ui/field_ui.api.php
+++ b/core/modules/field_ui/field_ui.api.php
@@ -33,7 +33,7 @@ function hook_field_formatter_settings_form_alter(&$element, &$form_state, $cont
     $element['mysetting'] = array(
       '#type' => 'checkbox',
       '#title' => t('My setting'),
-      '#default_value' => $context['formatter']->getSetting('mysetting'),
+      '#default_value' => $context['type']->getSetting('mysetting'),
     );
   }
 }
@@ -61,7 +61,7 @@ function hook_field_widget_settings_form_alter(&$element, &$form_state, $context
     $element['mysetting'] = array(
       '#type' => 'checkbox',
       '#title' => t('My setting'),
-      '#default_value' => $context['formatter']->getSetting('mysetting'),
+      '#default_value' => $context['type']->getSetting('mysetting'),
     );
   }
 }
@@ -84,7 +84,7 @@ function hook_field_formatter_settings_summary_alter(&$summary, $context) {
   // Append a message to the summary when an instance of foo_field has
   // mysetting set to TRUE for the current view mode.
   if ($context['field']['type'] == 'foo_field') {
-    if ($context['formatter']->getSetting('mysetting')) {
+    if ($context['type']->getSetting('mysetting')) {
       $summary[] = t('My setting enabled.');
     }
   }
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
index 841c056..da6184c 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
@@ -38,8 +38,8 @@ public function getFormID() {
   /**
    * {@inheritdoc}
    */
-  protected function buildFieldRow($field_id, FieldInstanceInterface $instance, EntityDisplayBaseInterface $entity_display, array $form, array &$form_state) {
-    $field_row = parent::buildFieldRow($field_id, $instance, $entity_display, $form, $form_state);
+  protected function buildFieldRow($type, $field_id, FieldInstanceInterface $instance, EntityDisplayBaseInterface $entity_display, array $form, array &$form_state) {
+    $field_row = parent::buildFieldRow($type, $field_id, $instance, $entity_display, $form, $form_state);
     $display_options = $entity_display->getComponent($field_id);
 
     // Insert the label column.
@@ -191,7 +191,7 @@ protected function getFieldLabelOptions() {
    */
   protected function alterSettingsForm(array &$settings_form, $plugin, FieldInstanceInterface $instance, array $form, array &$form_state) {
     $context = array(
-      'formatter' => $plugin,
+      'type' => $plugin,
       'field' => $instance->getField(),
       'instance' => $instance,
       'view_mode' => $this->mode,
@@ -205,7 +205,7 @@ protected function alterSettingsForm(array &$settings_form, $plugin, FieldInstan
    */
   protected function alterSettingsSummary(array &$summary, $plugin, FieldInstanceInterface $instance) {
     $context = array(
-      'formatter' => $plugin,
+      'type' => $plugin,
       'field' => $instance->getField(),
       'instance' => $instance,
       'view_mode' => $this->mode,
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverviewBase.php b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverviewBase.php
index 5a45c21..1ba34ba 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverviewBase.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverviewBase.php
@@ -112,12 +112,12 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
 
     // Field rows.
     foreach ($instances as $field_id => $instance) {
-      $table[$field_id] = $this->buildFieldRow($field_id, $instance, $entity_display, $form, $form_state);
+      $table[$field_id] = $this->buildFieldRow('field', $field_id, $instance, $entity_display, $form, $form_state);
     }
 
     // Non-field elements.
     foreach ($extra_fields as $field_id => $extra_field) {
-      $table[$field_id] = $this->buildExtraFieldRow($field_id, $extra_field, $entity_display);
+      $table[$field_id] = $this->buildExtraFieldRow('extra_field', $field_id, $extra_field, $entity_display);
     }
 
     $form['fields'] = $table;
@@ -189,6 +189,8 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
   /**
    * Builds the table row structure for a single field.
    *
+   * @param string $type
+   *   The component type.
    * @param string $field_id
    *   The field ID.
    * @param \Drupal\field\FieldInstanceInterface $instance
@@ -203,9 +205,9 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
    * @return array
    *   A table row array.
    */
-  protected function buildFieldRow($field_id, FieldInstanceInterface $instance, EntityDisplayBaseInterface $entity_display, array $form, array &$form_state) {
+  protected function buildFieldRow($type, $field_id, FieldInstanceInterface $instance, EntityDisplayBaseInterface $entity_display, array $form, array &$form_state) {
     $field = $instance->getField();
-    $display_options = $entity_display->getComponent($field_id);
+    $display_options = $entity_display->getComponent($type, $field_id);
 
     $field_row = array(
       '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
@@ -373,8 +375,8 @@ protected function buildFieldRow($field_id, FieldInstanceInterface $instance, En
    * @return array
    *   A table row array.
    */
-  protected function buildExtraFieldRow($field_id, $extra_field, $entity_display) {
-    $display_options = $entity_display->getComponent($field_id);
+  protected function buildExtraFieldRow($type, $field_id, $extra_field, $entity_display) {
+    $display_options = $entity_display->getComponent($type, $field_id);
 
     $extra_field_row = array(
       '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
@@ -440,7 +442,7 @@ public function submitForm(array &$form, array &$form_state) {
       $values = $form_values['fields'][$field_name];
 
       if ($values['type'] == 'hidden') {
-        $display->removeComponent($field_name);
+        $display->removeComponent('field', $field_name);
       }
       else {
         // Get plugin settings. They lie either directly in submitted form
@@ -453,7 +455,7 @@ public function submitForm(array &$form, array &$form_state) {
         elseif (isset($form_state['plugin_settings'][$field_name])) {
           $settings = $form_state['plugin_settings'][$field_name];
         }
-        elseif ($current_options = $display->getComponent($field_name)) {
+        elseif ($current_options = $display->getComponent('field', $field_name)) {
           $settings = $current_options['settings'];
         }
 
@@ -473,17 +475,17 @@ public function submitForm(array &$form, array &$form_state) {
           $component_values['label'] = $values['label'];
         }
 
-        $display->setComponent($field_name, $component_values);
+        $display->setComponent('field', $field_name, $component_values);
       }
     }
 
     // Collect data for 'extra' fields.
     foreach ($form['#extra'] as $name) {
       if ($form_values['fields'][$name]['type'] == 'hidden') {
-        $display->removeComponent($name);
+        $display->removeComponent('extra_field', $name);
       }
       else {
-        $display->setComponent($name, array(
+        $display->setComponent('extra_field', $name, array(
           'weight' => $form_values['fields'][$name]['weight'],
         ));
       }
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php
index 8e7e770..afc1198 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php
@@ -357,14 +357,14 @@ public function submitForm(array &$form, array &$form_state) {
         // default widget and settings). It stays hidden for other form modes
         // until it is explicitly configured.
         entity_get_form_display($this->entity_type, $this->bundle, 'default')
-          ->setComponent($field['field_name'])
+          ->setComponent('widget', $field['field_name'])
           ->save();
 
         // Make sure the field is displayed in the 'default' view mode (using
         // default formatter and settings). It stays hidden for other view
         // modes until it is explicitly configured.
         entity_get_display($this->entity_type, $this->bundle, 'default')
-          ->setComponent($field['field_name'])
+          ->setComponent('field', $field['field_name'])
           ->save();
 
         // Always show the field settings step, as the cardinality needs to be
@@ -403,14 +403,14 @@ public function submitForm(array &$form, array &$form_state) {
           // default widget and settings). It stays hidden for other form modes
           // until it is explicitly configured.
           entity_get_form_display($this->entity_type, $this->bundle, 'default')
-            ->setComponent($field['field_name'])
+            ->setComponent('widget', $field['field_name'])
             ->save();
 
           // Make sure the field is displayed in the 'default' view mode (using
           // default formatter and settings). It stays hidden for other view
           // modes until it is explicitly configured.
           entity_get_display($this->entity_type, $this->bundle, 'default')
-            ->setComponent($field['field_name'])
+            ->setComponent('field', $field['field_name'])
             ->save();
 
           $destinations[] = $this->adminPath . '/fields/' . $new_instance->id();
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/FormDisplayOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/FormDisplayOverview.php
index d2ab86a..6237682 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/FormDisplayOverview.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/FormDisplayOverview.php
@@ -38,8 +38,8 @@ public function getFormID() {
   /**
    * {@inheritdoc}
    */
-  protected function buildFieldRow($field_id, FieldInstanceInterface $instance, EntityDisplayBaseInterface $entity_display, array $form, array &$form_state) {
-    $field_row = parent::buildFieldRow($field_id, $instance, $entity_display, $form, $form_state);
+  protected function buildFieldRow($type, $field_id, FieldInstanceInterface $instance, EntityDisplayBaseInterface $entity_display, array $form, array &$form_state) {
+    $field_row = parent::buildFieldRow($type, $field_id, $instance, $entity_display, $form, $form_state);
 
     // Update the (invisible) title of the 'plugin' column.
     $field_row['plugin']['#title'] = t('Formatter for @title', array('@title' => $instance['label']));
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php
index a5d8790..8cf2a95 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php
@@ -45,7 +45,7 @@ function testFormatterUI() {
 
     // Clear the test-side cache and get the saved field instance.
     $display = entity_get_display('node', $this->type, 'default');
-    $display_options = $display->getComponent('field_test');
+    $display_options = $display->getComponent('field', 'field_test');
     $format = $display_options['type'];
     $default_settings = field_info_formatter_settings($format);
     $setting_name = key($default_settings);
@@ -54,23 +54,23 @@ function testFormatterUI() {
     // Display the "Manage display" screen and check that the expected formatter is
     // selected.
     $this->drupalGet($manage_display);
-    $this->assertFieldByName('fields[field_test][type]', $format, 'The expected formatter is selected.');
+    $this->assertFieldByName('fields[field_test][formatter]', $format, 'The expected formatter is selected.');
     $this->assertText("$setting_name: $setting_value", 'The expected summary is displayed.');
 
     // Change the formatter and check that the summary is updated.
-    $edit = array('fields[field_test][type]' => 'field_test_multiple', 'refresh_rows' => 'field_test');
+    $edit = array('fields[field_test][formatter]' => 'field_test_multiple', 'refresh_rows' => 'field_test');
     $this->drupalPostAJAX(NULL, $edit, array('op' => t('Refresh')));
     $format = 'field_test_multiple';
     $default_settings = field_info_formatter_settings($format);
     $setting_name = key($default_settings);
     $setting_value = $default_settings[$setting_name];
-    $this->assertFieldByName('fields[field_test][type]', $format, 'The expected formatter is selected.');
+    $this->assertFieldByName('fields[field_test][formatter]', $format, 'The expected formatter is selected.');
     $this->assertText("$setting_name: $setting_value", 'The expected summary is displayed.');
 
     // Submit the form and check that the display is updated.
     $this->drupalPost(NULL, array(), t('Save'));
     $display = entity_get_display('node', $this->type, 'default');
-    $display_options = $display->getComponent('field_test');
+    $display_options = $display->getComponent('field', 'field_test');
     $current_format = $display_options['type'];
     $current_setting_value = $display_options['settings'][$setting_name];
     $this->assertEqual($current_format, $format, 'The formatter was updated.');
@@ -195,7 +195,7 @@ function testViewModeCustom() {
     // Change fomatter for 'default' mode, check that the field is displayed
     // accordingly in 'rss' mode.
     $edit = array(
-      'fields[field_test][type]' => 'field_test_with_prepare_view',
+      'fields[field_test][formatter]' => 'field_test_with_prepare_view',
     );
     $this->drupalPost('admin/structure/types/manage/' . $this->type . '/display', $edit, t('Save'));
     $this->assertNodeViewText($node, 'rss', $output['field_test_with_prepare_view'], "The field is displayed as expected in view modes that use 'default' settings.");
@@ -210,7 +210,7 @@ function testViewModeCustom() {
     // Set the field to 'hidden' in the view mode, check that the field is
     // hidden.
     $edit = array(
-      'fields[field_test][type]' => 'hidden',
+      'fields[field_test][formatter]' => 'hidden',
     );
     $this->drupalPost('admin/structure/types/manage/' . $this->type . '/display/rss', $edit, t('Save'));
     $this->assertNodeViewNoText($node, 'rss', $value, "The field is hidden in 'rss' mode.");
@@ -250,7 +250,7 @@ function testNonInitializedFields() {
     // Check that the field appears as 'hidden' on the 'Manage display' page
     // for the 'teaser' mode.
     $this->drupalGet('admin/structure/types/manage/' . $this->type . '/display/teaser');
-    $this->assertFieldByName('fields[field_test][type]', 'hidden', 'The field is displayed as \'hidden \'.');
+    $this->assertFieldByName('fields[field_test][formatter]', 'hidden', 'The field is displayed as \'hidden \'.');
   }
 
   /**
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php
index cd7037f..65c9c08 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php
@@ -56,7 +56,7 @@ function setUp() {
     entity_create('field_instance', $instance)->save();
 
     entity_get_form_display('node', 'article', 'default')
-      ->setComponent('field_' . $vocabulary->id())
+      ->setComponent('widget', 'field_' . $vocabulary->id())
       ->save();
   }
 
@@ -287,7 +287,7 @@ function testDefaultValue() {
     $instance->save();
 
     entity_get_form_display('node', $this->type, 'default')
-      ->setComponent($field_name)
+      ->setComponent('widget', $field_name)
       ->save();
 
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
@@ -324,7 +324,7 @@ function testDefaultValue() {
 
     // Change the widget to TestFieldWidgetNoDefault.
     entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default')
-      ->setComponent($field_name, array(
+      ->setComponent('widget', $field_name, array(
         'type' => 'test_field_widget_no_default',
       ))
       ->save();
@@ -398,7 +398,7 @@ function testLockedField() {
       'bundle' => $this->type,
     ))->save();
     entity_get_form_display('node', $this->type, 'default')
-      ->setComponent($field->id, array(
+      ->setComponent('widget', $field->id, array(
         'type' => 'test_field_widget',
       ))
       ->save();
@@ -434,7 +434,7 @@ function testHiddenFields() {
     );
     entity_create('field_instance', $instance)->save();
     entity_get_form_display('node', $this->type, 'default')
-      ->setComponent($field_name)
+      ->setComponent('widget', $field_name)
       ->save();
     $this->assertTrue(field_read_instance('node', $field_name, $this->type), format_string('An instance of the field %field was created programmatically.', array('%field' => $field_name)));
 
@@ -521,7 +521,7 @@ function testHelpDescriptions() {
       'bundle' => 'article',
     ))->save();
 
-    entity_get_form_display('node', 'article', 'default')->setComponent('field_image')->save();
+    entity_get_form_display('node', 'article', 'default')->setComponent('widget', 'field_image')->save();
 
     $edit = array(
       'instance[description]' => '<strong>Test with an upload field.',
diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldDisplayTest.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldDisplayTest.php
index 29ba4ef..b3af5ad 100644
--- a/core/modules/file/lib/Drupal/file/Tests/FileFieldDisplayTest.php
+++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldDisplayTest.php
@@ -46,7 +46,7 @@ function testNodeDisplay() {
     $file_formatters = array('file_table', 'file_url_plain', 'hidden', 'file_default');
     foreach ($file_formatters as $formatter) {
       $edit = array(
-        "fields[$field_name][type]" => $formatter,
+        "fields[$field_name][formatter]" => $formatter,
       );
       $this->drupalPost("admin/structure/types/manage/$type_name/display", $edit, t('Save'));
       $this->drupalGet('node/' . $node->nid);
diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldRSSContentTest.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldRSSContentTest.php
index e241dea..4bcbb95 100644
--- a/core/modules/file/lib/Drupal/file/Tests/FileFieldRSSContentTest.php
+++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldRSSContentTest.php
@@ -54,7 +54,7 @@ function testFileFieldRSSContent() {
 
     // Change the format to 'RSS enclosure'.
     $this->drupalGet("admin/structure/types/manage/$type_name/display/rss");
-    $edit = array("fields[$field_name][type]" => 'file_rss_enclosure');
+    $edit = array("fields[$field_name][formatter]" => 'file_rss_enclosure');
     $this->drupalPost(NULL, $edit, t('Save'));
 
     // Create a new node with a file field set. Promote to frontpage
diff --git a/core/modules/forum/forum.install b/core/modules/forum/forum.install
index e0219ff..915309c 100644
--- a/core/modules/forum/forum.install
+++ b/core/modules/forum/forum.install
@@ -93,14 +93,14 @@ function forum_enable() {
 
     // Assign display settings for the 'default' and 'teaser' view modes.
     entity_get_display('node', 'forum', 'default')
-      ->setComponent('taxonomy_forums', array(
-        'type' => 'taxonomy_term_reference_link',
+      ->setComponent('field', 'taxonomy_forums', array(
+        'formatter' => 'taxonomy_term_reference_link',
         'weight' => 10,
       ))
       ->save();
     entity_get_display('node', 'forum', 'teaser')
-      ->setComponent('taxonomy_forums', array(
-        'type' => 'taxonomy_term_reference_link',
+      ->setComponent('field', 'taxonomy_forums', array(
+        'formatter' => 'taxonomy_term_reference_link',
         'weight' => 10,
       ))
       ->save();
diff --git a/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php b/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php
index 2e99768..09a7165 100644
--- a/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php
+++ b/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php
@@ -125,7 +125,7 @@ protected static function replaceImageStyle(ImageStyle $style) {
           $view_modes = array('default') + array_keys($view_modes);
           foreach ($view_modes as $view_mode) {
             $display = entity_get_display($instance['entity_type'], $instance['bundle'], $view_mode);
-            $display_options = $display->getComponent($instance['field_name']);
+            $display_options = $display->getComponent('field', $instance['field_name']);
 
             // Check if the formatter involves an image style.
             if ($display_options && $display_options['type'] == 'image' && $display_options['settings']['image_style'] == $style->getOriginalID()) {
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php
index 973a8ef..7a9c3c5 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php
@@ -260,8 +260,8 @@ function testStyleReplacement() {
     $field_name = strtolower($this->randomName(10));
     $this->createImageField($field_name, 'article');
     entity_get_display('node', 'article', 'default')
-      ->setComponent($field_name, array(
-        'type' => 'image',
+      ->setComponent('field', $field_name, array(
+        'formatter' => 'image',
         'settings' => array('image_style' => $style_name),
       ))
       ->save();
@@ -349,7 +349,7 @@ function testConfigImport() {
     $field_name = strtolower($this->randomName(10));
     $this->createImageField($field_name, 'article');
     entity_get_display('node', 'article', 'default')
-      ->setComponent($field_name, array(
+      ->setComponent('field', $field_name, array(
         'type' => 'image',
         'settings' => array('image_style' => $style_name),
       ))
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php
index 164cbad..71e38f6 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php
@@ -72,7 +72,7 @@ function testDefaultImages() {
       ->setComponent($field->id(), $widget_settings)
       ->save();
     entity_get_display('node', 'page', 'default')
-      ->setComponent($field->id())
+      ->setComponent('field', $field->id())
       ->save();
 
     // Confirm the defaults are present on the article field settings form.
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
index c0f0cfd..73e6049 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
@@ -69,11 +69,11 @@ function _testImageFieldFormatters($scheme) {
 
     // Test the image linked to file formatter.
     $display_options = array(
-      'type' => 'image',
+      'formatter' => 'image',
       'settings' => array('image_link' => 'file'),
     );
     $display = entity_get_display('node', $node->type, 'default');
-    $display->setComponent($field_name, $display_options)
+    $display->setComponent('field', $field_name, $display_options)
       ->save();
 
     $default_output = l(theme('image', $image_info), file_create_url($image_uri), array('html' => TRUE));
@@ -98,7 +98,7 @@ function _testImageFieldFormatters($scheme) {
 
     // Test the image linked to content formatter.
     $display_options['settings']['image_link'] = 'content';
-    $display->setComponent($field_name, $display_options)
+    $display->setComponent('field', $field_name, $display_options)
       ->save();
     $default_output = l(theme('image', $image_info), 'node/' . $nid, array('html' => TRUE, 'attributes' => array('class' => 'active')));
     $this->drupalGet('node/' . $nid);
@@ -107,7 +107,7 @@ function _testImageFieldFormatters($scheme) {
     // Test the image style 'thumbnail' formatter.
     $display_options['settings']['image_link'] = '';
     $display_options['settings']['image_style'] = 'thumbnail';
-    $display->setComponent($field_name, $display_options)
+    $display->setComponent('field', $field_name, $display_options)
       ->save();
 
     // Ensure the derivative image is generated so we do not have to deal with
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php
index 3b9be9f..738199c 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php
@@ -99,7 +99,7 @@ function createImageField($name, $type_name, $field_settings = array(), $instanc
       ->save();
 
     entity_get_display('node', $type_name, 'default')
-      ->setComponent($field['field_name'])
+      ->setComponent('field', $field['field_name'])
       ->save();
 
     return $field_instance;
diff --git a/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php b/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php
index b4033ff..107fc58 100644
--- a/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php
+++ b/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php
@@ -89,8 +89,8 @@ function testURLValidation() {
       ))
       ->save();
     entity_get_display('entity_test', 'entity_test', 'full')
-      ->setComponent($field_name, array(
-        'type' => 'link',
+      ->setComponent('field', $field_name, array(
+        'formatter' => 'link',
       ))
       ->save();
 
@@ -166,8 +166,8 @@ function testLinkTitle() {
       ))
       ->save();
     entity_get_display('entity_test', 'entity_test', 'full')
-      ->setComponent($field_name, array(
-        'type' => 'link',
+      ->setComponent('field', $field_name, array(
+        'formatter' => 'link',
         'label' => 'hidden',
       ))
       ->save();
@@ -285,7 +285,7 @@ function testLinkFormatter() {
       'label' => 'hidden',
     );
     entity_get_display('entity_test', 'entity_test', 'full')
-      ->setComponent($field_name, $display_options)
+      ->setComponent('field', $field_name, $display_options)
       ->save();
 
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
@@ -343,7 +343,7 @@ function testLinkFormatter() {
           $display_options['settings'] = $new_value;
         }
         entity_get_display('entity_test', 'entity_test', 'full')
-          ->setComponent($field_name, $display_options)
+          ->setComponent('field', $field_name, $display_options)
           ->save();
 
         $this->renderTestEntity($id);
@@ -427,7 +427,7 @@ function testLinkSeparateFormatter() {
       ))
       ->save();
     entity_get_display('entity_test', 'entity_test', 'full')
-      ->setComponent($field_name, $display_options)
+      ->setComponent('field', $field_name, $display_options)
       ->save();
 
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
@@ -465,7 +465,7 @@ function testLinkSeparateFormatter() {
         // Update the field formatter settings.
         $display_options['settings'] = array($setting => $new_value);
         entity_get_display('entity_test', 'entity_test', 'full')
-          ->setComponent($this->field['field_name'], $display_options)
+          ->setComponent('field', $this->field['field_name'], $display_options)
           ->save();
 
         $this->renderTestEntity($id);
diff --git a/core/modules/node/lib/Drupal/node/NodeRenderController.php b/core/modules/node/lib/Drupal/node/NodeRenderController.php
index a58a96f..aef85e6 100644
--- a/core/modules/node/lib/Drupal/node/NodeRenderController.php
+++ b/core/modules/node/lib/Drupal/node/NodeRenderController.php
@@ -65,7 +65,7 @@ public function buildContent(array $entities, array $displays, $view_mode, $lang
       );
 
       // Add Language field text element to node render array.
-      if ($display->getComponent('language')) {
+      if ($display->getComponent('extra_field', 'language')) {
         $entity->content['language'] = array(
           '#type' => 'item',
           '#title' => t('Language'),
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeAccessFieldTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeAccessFieldTest.php
index e1a33aa..d84185f 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeAccessFieldTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeAccessFieldTest.php
@@ -71,7 +71,7 @@ public function setUp() {
       'bundle' => 'page',
     ))->save();
     entity_get_display('node', 'page', 'default')
-      ->setComponent($this->field_name)
+      ->setComponent('field', $this->field_name)
       ->save();
     entity_get_form_display('node', 'page', 'default')
       ->setComponent($this->field_name)
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php
index 1a0b7ed..bfa5b07 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php
@@ -86,7 +86,7 @@ function testNodeTypeInitialLanguageDefaults() {
     $language_display = $this->xpath('//*[@id="language"]');
     $this->assert(!empty($language_display), 'Language field is visible on manage display tab.');
     // Tests if the language field is hidden by default.
-    $this->assertOptionSelected('edit-fields-language-type', 'hidden', 'Language is hidden by default on manage display tab.');
+    $this->assertOptionSelected('edit-fields-language-visibility', 'hidden', 'Language is hidden by default on manage display tab.');
 
     // Changes the inital language settings.
     $edit = array(
@@ -121,11 +121,11 @@ function testLanguageFieldVisibility() {
 
     // Changes Language field visibility to true and check if it is saved.
     $edit = array(
-      'fields[language][type]' => 'visible',
+      'fields[language][visibility]' => 'visible',
     );
     $this->drupalPost('admin/structure/types/manage/article/display', $edit, t('Save'));
     $this->drupalGet('admin/structure/types/manage/article/display');
-    $this->assertOptionSelected('edit-fields-language-type', 'visible', 'Language field has been set to visible.');
+    $this->assertOptionSelected('edit-fields-language-visibility', 'visible', 'Language field has been set to visible.');
 
     // Loads node page and check if Language field is shown.
     $this->drupalGet('node/' . $node->nid);
diff --git a/core/modules/node/lib/Drupal/node/Tests/PagePreviewTest.php b/core/modules/node/lib/Drupal/node/Tests/PagePreviewTest.php
index b485545..fadc3cf 100644
--- a/core/modules/node/lib/Drupal/node/Tests/PagePreviewTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/PagePreviewTest.php
@@ -94,13 +94,13 @@ function setUp() {
 
     // Show on default display and teaser.
     entity_get_display('node', 'page', 'default')
-      ->setComponent($this->field_name, array(
-        'type' => 'taxonomy_term_reference_link',
+      ->setComponent('field', $this->field_name, array(
+        'formatter' => 'taxonomy_term_reference_link',
       ))
       ->save();
     entity_get_display('node', 'page', 'teaser')
-      ->setComponent($this->field_name, array(
-        'type' => 'taxonomy_term_reference_link',
+      ->setComponent('field', $this->field_name, array(
+        'formatter' => 'taxonomy_term_reference_link',
       ))
       ->save();
   }
diff --git a/core/modules/node/lib/Drupal/node/Tests/SummaryLengthTest.php b/core/modules/node/lib/Drupal/node/Tests/SummaryLengthTest.php
index e627c6e..87416c9 100644
--- a/core/modules/node/lib/Drupal/node/Tests/SummaryLengthTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/SummaryLengthTest.php
@@ -48,9 +48,9 @@ function testSummaryLength() {
 
     // Change the teaser length for "Basic page" content type.
     $display = entity_get_display('node', $node->type, 'teaser');
-    $display_options = $display->getComponent('body');
+    $display_options = $display->getComponent('field', 'body');
     $display_options['settings']['trim_length'] = 200;
-    $display->setComponent('body', $display_options)
+    $display->setComponent('field', 'body', $display_options)
       ->save();
 
     // Render the node as a teaser again and check that the summary is now only
diff --git a/core/modules/node/node.api.php b/core/modules/node/node.api.php
index 51abca3..e495e02 100644
--- a/core/modules/node/node.api.php
+++ b/core/modules/node/node.api.php
@@ -806,7 +806,7 @@ function hook_node_view(\Drupal\Core\Entity\EntityInterface $node, \Drupal\entit
   // Only do the extra work if the component is configured to be displayed.
   // This assumes a 'mymodule_addition' extra field has been defined for the
   // node type in hook_field_extra_fields().
-  if ($display->getComponent('mymodule_addition')) {
+  if ($display->getComponent('extra_field', 'mymodule_addition')) {
     $node->content['mymodule_addition'] = array(
       '#markup' => mymodule_addition($node),
       '#theme' => 'mymodule_my_additional_field',
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index d01b8ae..92b5274 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -195,11 +195,9 @@ function node_entity_bundle_info() {
 function node_entity_display_alter(EntityDisplay $display, $context) {
   // Hide field labels in search index.
   if ($context['entity_type'] == 'node' && $context['view_mode'] == 'search_index') {
-    foreach ($display->getComponents() as $name => $options) {
-      if (isset($options['label'])) {
-        $options['label'] = 'hidden';
-        $display->setComponent($name, $options);
-      }
+    foreach ($display->getComponents('field') as $name => $options) {
+      $options['label'] = 'hidden';
+      $display->setComponent('field', $name, $options);
     }
   }
 }
@@ -417,20 +415,20 @@ function node_add_body_field(NodeTypeInterface $type, $label = 'Body') {
 
     // Assign widget settings for the 'default' form mode.
     entity_get_form_display('node', $type->type, 'default')
-      ->setComponent($field->id(), array(
+      ->setComponent('widget', $field->id(), array(
         'type' => 'text_textarea_with_summary',
       ))
       ->save();
 
     // Assign display settings for the 'default' and 'teaser' view modes.
     entity_get_display('node', $type->type, 'default')
-      ->setComponent($field->id(), array(
+      ->setComponent('field', $field->id(), array(
         'label' => 'hidden',
         'type' => 'text_default',
       ))
       ->save();
     entity_get_display('node', $type->type, 'teaser')
-      ->setComponent($field->id(), array(
+      ->setComponent('field', $field->id(), array(
         'label' => 'hidden',
         'type' => 'text_summary_or_trimmed',
       ))
diff --git a/core/modules/node/node.tokens.inc b/core/modules/node/node.tokens.inc
index 241b83b..8f0d3a2 100644
--- a/core/modules/node/node.tokens.inc
+++ b/core/modules/node/node.tokens.inc
@@ -154,7 +154,7 @@ function node_tokens($type, $tokens, array $data = array(), array $options = arr
 
                 // Get the 'trim_length' size used for the 'teaser' mode, if
                 // present, or use the default trim_length size.
-                $display_options = entity_get_display('node', $node->type, 'teaser')->getComponent('body');
+                $display_options = entity_get_display('node', $node->type, 'teaser')->getComponent('field', 'body');
                 if (isset($display_options['settings']['trim_length'])) {
                   $length = $display_options['settings']['trim_length'];
                 }
diff --git a/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php b/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php
index 8bea406..0070aa8 100644
--- a/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php
+++ b/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php
@@ -86,8 +86,8 @@ function testNumberDecimalField() {
       ))
       ->save();
     entity_get_display('entity_test', 'entity_test', 'default')
-      ->setComponent($this->field->id(), array(
-        'type' => 'number_decimal',
+      ->setComponent('field', $this->field->id(), array(
+        'formatter' => 'number_decimal',
       ))
       ->save();
 
@@ -174,11 +174,11 @@ function testNumberIntegerField() {
     // check that the settings summary does not generate warnings.
     $this->drupalGet("admin/structure/types/manage/$type/display");
     $edit = array(
-      "fields[field_$field_name][type]" => 'number_integer',
+      "fields[field_$field_name][formatter]" => 'number_integer',
     );
     $this->drupalPost(NULL, $edit, t('Save'));
     $edit = array(
-      "fields[field_$field_name][type]" => 'number_unformatted',
+      "fields[field_$field_name][formatter]" => 'number_unformatted',
     );
     $this->drupalPost(NULL, $edit, t('Save'));
   }
diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php
index d34f178..7422d20 100644
--- a/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php
+++ b/core/modules/options/lib/Drupal/options/Tests/OptionsFieldUITest.php
@@ -328,7 +328,7 @@ function testNodeDisplay() {
     $file_formatters = array('list_default', 'list_key');
     foreach ($file_formatters as $formatter) {
       $edit = array(
-        "fields[$this->field_name][type]" => $formatter,
+        "fields[$this->field_name][formatter]" => $formatter,
       );
       $this->drupalPost('admin/structure/types/manage/' . $this->type_name . '/display', $edit, t('Save'));
       $this->drupalGet('node/' . $node->nid);
diff --git a/core/modules/picture/lib/Drupal/picture/Tests/PictureFieldDisplayTest.php b/core/modules/picture/lib/Drupal/picture/Tests/PictureFieldDisplayTest.php
index b79ad21..e270987 100644
--- a/core/modules/picture/lib/Drupal/picture/Tests/PictureFieldDisplayTest.php
+++ b/core/modules/picture/lib/Drupal/picture/Tests/PictureFieldDisplayTest.php
@@ -134,12 +134,11 @@ public function _testPictureFieldFormatters($scheme) {
 
     // Use the picture formatter linked to file formatter.
     $display_options = array(
-      'type' => 'picture',
-      'module' => 'picture',
+      'formatter' => 'picture',
       'settings' => array('image_link' => 'file'),
     );
     $display = entity_get_display('node', 'article', 'default');
-    $display->setComponent($field_name, $display_options)
+    $display->setComponent('field', $field_name, $display_options)
       ->save();
 
     $default_output = l(theme('image', $image_info), file_create_url($image_uri), array('html' => TRUE));
@@ -164,7 +163,7 @@ public function _testPictureFieldFormatters($scheme) {
 
     // Use the picture formatter with a picture mapping.
     $display_options['settings']['picture_mapping'] = 'mapping_one';
-    $display->setComponent($field_name, $display_options)
+    $display->setComponent('field', $field_name, $display_options)
       ->save();
 
     // Output should contain all image styles and all breakpoints.
@@ -179,7 +178,7 @@ public function _testPictureFieldFormatters($scheme) {
     // Test the fallback image style.
     $display_options['settings']['image_link'] = '';
     $display_options['settings']['fallback_image_style'] = 'large';
-    $display->setComponent($field_name, $display_options)
+    $display->setComponent('field', $field_name, $display_options)
       ->save();
 
     $this->drupalGet(image_style_url('large', $image_uri));
diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php
index 79abf93..e948cb8 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php
@@ -46,14 +46,16 @@ public function testEntityDisplayUpgrade() {
     // Check that the 'body' field is configured as expected.
     $expected = array(
       'default' => array(
+        'handler_type' => 'field',
         'label' => 'hidden',
-        'type' => 'text_default',
+        'formatter' => 'text_default',
         'weight' => 0,
         'settings' => array(),
       ),
       'teaser' => array(
+        'handler_type' => 'field',
         'label' => 'hidden',
-        'type' => 'text_summary_or_trimmed',
+        'formatter' => 'text_summary_or_trimmed',
         'weight' => 0,
         'settings' => array(
           'trim_length' => 600,
@@ -70,10 +72,12 @@ public function testEntityDisplayUpgrade() {
     // Check that the 'language' extra field is configured as expected.
     $expected = array(
       'default' => array(
+        'handler_type' => 'extra_field',
         'weight' => -1,
         'visible' => 1,
       ),
       'teaser' => array(
+        'handler_type' => 'extra_field',
         'visible' => 0,
       ),
     );
diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php
index dd9bcf9..d1d076f 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php
@@ -60,12 +60,12 @@ public function testUserPictureUpgrade() {
     $this->assertEqual($instance['description'], 'These are user picture guidelines.', 'User picture guidelines are now the user picture field description.');
     $this->assertEqual($instance['settings']['file_directory'], 'user_pictures_dir', 'User picture directory path has been migrated.');
 
-    $display_options = entity_get_display('user', 'user', 'default')->getComponent('user_picture');
+    $display_options = entity_get_display('user', 'user', 'default')->getComponent('field', 'user_picture');
     $this->assertEqual($display_options['settings']['image_style'], 'thumbnail', 'User picture image style setting has been migrated.');
 
     // Verify compact view mode default settings.
     $this->drupalGet('admin/config/people/accounts/display/compact');
-    $this->assertFieldByName('fields[member_for][type]', 'hidden');
+    $this->assertFieldByName('fields[member_for][visibility]', 'hidden');
 
     // Check the user picture and file usage record.
     $user = user_load(1);
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module
index 55d0dac..2d26425 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.module
+++ b/core/modules/system/tests/modules/entity_test/entity_test.module
@@ -160,7 +160,7 @@ function entity_test_entity_view_mode_info_alter(&$view_modes) {
  * Implements hook_field_extra_fields().
  */
 function entity_test_field_extra_fields() {
-  $extra['entity_test']['entity_test'] = array(
+  $extra['entity_test']['bundle_with_extra_fields'] = array(
     'display' => array(
       // Note: those extra fields do not currently display anything, they are
       // just used in \Drupal\entity\Tests\EntityDisplayTest to test the
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermRenderController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermRenderController.php
index e7f8882..fd3e1fb 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermRenderController.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermRenderController.php
@@ -25,7 +25,7 @@ public function buildContent(array $entities, array $displays, $view_mode, $lang
     foreach ($entities as $entity) {
       // Add the description if enabled.
       $display = $displays[$entity->bundle()];
-      if (!empty($entity->description->value) && $display->getComponent('description')) {
+      if (!empty($entity->description->value) && $display->getComponent('extra_field', 'description')) {
         $entity->content['description'] = array(
           '#markup' => check_markup($entity->description->value, $entity->format->value, '', TRUE),
           '#prefix' => '<div class="taxonomy-term-description">',
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php
index c9b8078..5cd2be4 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php
@@ -62,8 +62,8 @@ function setUp() {
       ))
       ->save();
     entity_get_display('node', 'article', 'default')
-      ->setComponent($this->field_name, array(
-        'type' => 'taxonomy_term_reference_link',
+      ->setComponent('field', $this->field_name, array(
+        'formatter' => 'taxonomy_term_reference_link',
       ))
       ->save();
   }
@@ -87,7 +87,7 @@ function testTaxonomyRss() {
     // Change the format to 'RSS category'.
     $this->drupalGet("admin/structure/types/manage/article/display/rss");
     $edit = array(
-      "fields[taxonomy_" . $this->vocabulary->id() . "][type]" => 'taxonomy_term_reference_rss_category',
+      'fields[taxonomy_' . $this->vocabulary->id() . '][formatter]' => 'taxonomy_term_reference_rss_category',
     );
     $this->drupalPost(NULL, $edit, t('Save'));
 
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php
index c19ce9d..e0a4e26 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php
@@ -70,8 +70,8 @@ function setUp() {
       ))
       ->save();
     entity_get_display('entity_test', 'entity_test', 'full')
-      ->setComponent($this->field_name, array(
-        'type' => 'taxonomy_term_reference_link',
+      ->setComponent('field', $this->field_name, array(
+        'formatter' => 'taxonomy_term_reference_link',
       ))
       ->save();
   }
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php
index e893001..035056b 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php
@@ -69,8 +69,8 @@ function setUp() {
       ))
       ->save();
     entity_get_display('entity_test', 'entity_test', 'full')
-      ->setComponent($this->field_name, array(
-        'type' => 'taxonomy_term_reference_link',
+      ->setComponent('field', $this->field_name, array(
+        'formatter' => 'taxonomy_term_reference_link',
       ))
       ->save();
   }
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermIndexTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermIndexTest.php
index 8fa30c3..7423f11 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermIndexTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermIndexTest.php
@@ -57,8 +57,8 @@ function setUp() {
       ))
       ->save();
     entity_get_display('node', 'article', 'default')
-      ->setComponent($this->field_name_1, array(
-        'type' => 'taxonomy_term_reference_link',
+      ->setComponent('field', $this->field_name_1, array(
+        'formatter' => 'taxonomy_term_reference_link',
       ))
       ->save();
 
@@ -87,8 +87,8 @@ function setUp() {
       ))
       ->save();
     entity_get_display('node', 'article', 'default')
-      ->setComponent($this->field_name_2, array(
-        'type' => 'taxonomy_term_reference_link',
+      ->setComponent('field', $this->field_name_2, array(
+        'formatter' => 'taxonomy_term_reference_link',
       ))
       ->save();
   }
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php
index caf5397..ada33af 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php
@@ -55,8 +55,8 @@ function setUp() {
       ))
       ->save();
     entity_get_display('node', 'article', 'default')
-      ->setComponent($this->instance['field_name'], array(
-        'type' => 'taxonomy_term_reference_link',
+      ->setComponent('field', $this->instance['field_name'], array(
+        'formatter' => 'taxonomy_term_reference_link',
       ))
       ->save();
   }
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php
index eec5921..030a643 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php
@@ -54,8 +54,8 @@ function setUp() {
       ))
       ->save();
     entity_get_display('node', 'article', 'default')
-      ->setComponent($this->field_name, array(
-        'type' => 'taxonomy_term_reference_link',
+      ->setComponent('field', $this->field_name, array(
+        'formatter' => 'taxonomy_term_reference_link',
       ))
       ->save();
   }
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/Views/TaxonomyTestBase.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/Views/TaxonomyTestBase.php
index e7c7031..c7b0234 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/Views/TaxonomyTestBase.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/Views/TaxonomyTestBase.php
@@ -106,14 +106,14 @@ protected function mockStandardInstall() {
       ->save();
 
     entity_get_display('node', 'article', 'default')
-      ->setComponent($this->field_name, array(
-        'type' => 'taxonomy_term_reference_link',
+      ->setComponent('field', $this->field_name, array(
+        'formatter' => 'taxonomy_term_reference_link',
         'weight' => 10,
       ))
       ->save();
     entity_get_display('node', 'article', 'teaser')
-      ->setComponent($this->field_name, array(
-        'type' => 'taxonomy_term_reference_link',
+      ->setComponent('field', $this->field_name, array(
+        'formatter' => 'taxonomy_term_reference_link',
         'weight' => 10,
       ))
       ->save();
diff --git a/core/modules/taxonomy/taxonomy.api.php b/core/modules/taxonomy/taxonomy.api.php
index ca3af07..0b39230 100644
--- a/core/modules/taxonomy/taxonomy.api.php
+++ b/core/modules/taxonomy/taxonomy.api.php
@@ -264,7 +264,7 @@ function hook_taxonomy_term_view(\Drupal\taxonomy\Plugin\Core\Entity\Term $term,
   // Only do the extra work if the component is configured to be displayed.
   // This assumes a 'mymodule_addition' extra field has been defined for the
   // vocabulary in hook_field_extra_fields().
-  if ($display->getComponent('mymodule_addition')) {
+  if ($display->getComponent('extra_field', 'mymodule_addition')) {
     $term->content['mymodule_addition'] = array(
       '#markup' => mymodule_addition($term),
       '#theme' => 'mymodule_my_additional_field',
diff --git a/core/modules/telephone/lib/Drupal/telephone/Tests/TelephoneFieldTest.php b/core/modules/telephone/lib/Drupal/telephone/Tests/TelephoneFieldTest.php
index 6158f07..795a08b 100644
--- a/core/modules/telephone/lib/Drupal/telephone/Tests/TelephoneFieldTest.php
+++ b/core/modules/telephone/lib/Drupal/telephone/Tests/TelephoneFieldTest.php
@@ -74,8 +74,8 @@ function testTelephoneField() {
       ->save();
 
     entity_get_display('node', 'article', 'default')
-      ->setComponent('field_telephone', array(
-        'type' => 'telephone_link',
+      ->setComponent('field', 'field_telephone', array(
+        'formatter' => 'telephone_link',
         'weight' => 1,
       ))
       ->save();
diff --git a/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php b/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php
index 0a2b900..8593519 100644
--- a/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php
+++ b/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php
@@ -85,7 +85,7 @@ function setUp() {
 
     $this->view_mode = 'default';
     $this->display = entity_get_display($this->entity_type, $this->bundle, $this->view_mode)
-      ->setComponent($this->field_name, array(
+      ->setComponent('field', $this->field_name, array(
         'type' => $this->formatter_type,
         'settings' => $this->formatter_settings,
       ));
diff --git a/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php b/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php
index c349d6d..98f7d19 100644
--- a/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php
+++ b/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php
@@ -115,7 +115,7 @@ function _testTextfieldWidgets($field_type, $widget_type) {
       ))
       ->save();
     entity_get_display('entity_test', 'entity_test', 'full')
-      ->setComponent($this->field_name)
+      ->setComponent('field', $this->field_name)
       ->save();
 
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
@@ -180,7 +180,7 @@ function _testTextfieldWidgetsFormatted($field_type, $widget_type) {
       ))
       ->save();
     entity_get_display('entity_test', 'entity_test', 'full')
-      ->setComponent($this->field_name)
+      ->setComponent('field', $this->field_name)
       ->save();
 
     $langcode = Language::LANGCODE_NOT_SPECIFIED;
diff --git a/core/modules/user/user.api.php b/core/modules/user/user.api.php
index 2f337d9..8681358 100644
--- a/core/modules/user/user.api.php
+++ b/core/modules/user/user.api.php
@@ -329,7 +329,7 @@ function hook_user_view(\Drupal\user\UserInterface $account, \Drupal\entity\Plug
   // Only do the extra work if the component is configured to be displayed.
   // This assumes a 'mymodule_addition' extra field has been defined for the
   // user entity type in hook_field_extra_fields().
-  if ($display->getComponent('mymodule_addition')) {
+  if ($display->getComponent('extra_field', 'mymodule_addition')) {
     $account->content['mymodule_addition'] = array(
       '#markup' => mymodule_addition($account),
       '#theme' => 'mymodule_my_additional_field',
diff --git a/core/modules/user/user.install b/core/modules/user/user.install
index 37dc770..202de34 100644
--- a/core/modules/user/user.install
+++ b/core/modules/user/user.install
@@ -315,9 +315,9 @@ function user_install_picture_field() {
 
   // Assign display settings for the 'default' and 'compact' view modes.
   entity_get_display('user', 'user', 'default')
-    ->setComponent('user_picture', array(
+    ->setComponent('field', 'user_picture', array(
       'label' => 'hidden',
-      'type' => 'image',
+      'formatter' => 'image',
       'settings' => array(
         'image_style' => 'thumbnail',
         'image_link' => 'content',
@@ -325,16 +325,16 @@ function user_install_picture_field() {
     ))
     ->save();
   entity_get_display('user', 'user', 'compact')
-    ->setComponent('user_picture', array(
+    ->setComponent('field', 'user_picture', array(
       'label' => 'hidden',
-      'type' => 'image',
+      'formatter' => 'image',
       'settings' => array(
         'image_style' => 'thumbnail',
         'image_link' => 'content',
       ),
     ))
     // Additionally, hide 'summary' pseudo-field from compact view mode..
-    ->removeComponent('member_for')
+    ->removeComponent('extra_field', 'member_for')
     ->save();
 }
 
@@ -712,8 +712,9 @@ function user_update_8011() {
   // Assign display settings for the 'default' and 'compact' view modes.
   $display = _update_8000_entity_get_display('user', 'user', 'default');
   $display->set('content.user_picture', array(
+      'handler_type' => 'field',
       'label' => 'hidden',
-      'type' => $formatter,
+      'formatter' => $formatter,
       'settings' => array(
         'image_style' => 'thumbnail',
         'image_link' => 'content',
@@ -724,8 +725,9 @@ function user_update_8011() {
 
   $display = _update_8000_entity_get_display('user', 'user', 'compact');
   $display->set('content.user_picture', array(
+      'handler_type' => 'field',
       'label' => 'hidden',
-      'type' => $formatter,
+      'formatter' => $formatter,
       'settings' => array(
         'image_style' => update_variable_get('user_picture_style', ''),
         'image_link' => 'content',
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index eb6b4f3..71ceb32 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -599,7 +599,7 @@ function user_search_execute($keys = NULL, $conditions = NULL) {
  * Implements hook_user_view().
  */
 function user_user_view(UserInterface $account, EntityDisplay $display) {
-  if ($display->getComponent('member_for')) {
+  if ($display->getComponent('extra_field', 'member_for')) {
     $account->content['member_for'] = array(
       '#type' => 'item',
       '#title' => t('Member for'),
diff --git a/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php b/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php
index 2f870d8..5efb8ba 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php
@@ -85,15 +85,15 @@ function setUp() {
       ))
       ->save();
 
-    entity_get_display('node', $this->node_type_with_tags->type, 'default')
+    entity_get_display('field', 'node', $this->node_type_with_tags->type, 'default')
       ->setComponent('field_views_testing_tags', array(
-        'type' => 'taxonomy_term_reference_link',
+        'formatter' => 'taxonomy_term_reference_link',
         'weight' => 10,
       ))
       ->save();
-    entity_get_display('node', $this->node_type_with_tags->type, 'teaser')
+    entity_get_display('field', 'node', $this->node_type_with_tags->type, 'teaser')
       ->setComponent('field_views_testing_tags', array(
-        'type' => 'taxonomy_term_reference_link',
+        'formatter' => 'taxonomy_term_reference_link',
         'weight' => 10,
       ))
       ->save();
diff --git a/core/profiles/standard/config/entity.display.node.article.default.yml b/core/profiles/standard/config/entity.display.node.article.default.yml
index 330de2d..b907284 100644
--- a/core/profiles/standard/config/entity.display.node.article.default.yml
+++ b/core/profiles/standard/config/entity.display.node.article.default.yml
@@ -4,18 +4,21 @@ bundle: article
 mode: default
 content:
   body:
+    handler_type: field
     label: hidden
-    type: text_default
+    formatter: text_default
     weight: '0'
     settings: {  }
   field_tags:
-    type: taxonomy_term_reference_link
+    handler_type: field
+    formatter: taxonomy_term_reference_link
     weight: '10'
     label: above
     settings: {  }
   field_image:
+    handler_type: field
     label: hidden
-    type: image
+    formatter: image
     settings:
       image_style: large
       image_link: ''
diff --git a/core/profiles/standard/config/entity.display.node.article.teaser.yml b/core/profiles/standard/config/entity.display.node.article.teaser.yml
index 44add7e..203c784 100644
--- a/core/profiles/standard/config/entity.display.node.article.teaser.yml
+++ b/core/profiles/standard/config/entity.display.node.article.teaser.yml
@@ -4,19 +4,22 @@ bundle: article
 mode: teaser
 content:
   body:
+    handler_type: field
     label: hidden
-    type: text_summary_or_trimmed
+    formatter: text_summary_or_trimmed
     weight: '0'
     settings:
       trim_length: '600'
   field_tags:
-    type: taxonomy_term_reference_link
+    handler_type: field
+    formatter: taxonomy_term_reference_link
     weight: '10'
     label: above
     settings: {  }
   field_image:
+    handler_type: field
     label: hidden
-    type: image
+    formatter: image
     settings:
       image_style: medium
       image_link: content
