diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/PluginBagItemBase.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/PluginBagItemBase.php
new file mode 100644
index 0000000..9e62d0e
--- /dev/null
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/PluginBagItemBase.php
@@ -0,0 +1,106 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Field\Plugin\Field\FieldType\PluginBagItemBase.
+ */
+
+namespace Drupal\Core\Field\Plugin\Field\FieldType;
+
+use Drupal\Component\Plugin\ConfigurablePluginInterface;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\Core\Field\FieldItemBase;
+use Drupal\Core\TypedData\DataDefinition;
+use Drupal\Core\TypedData\DataReferenceDefinition;
+
+/**
+ * Provides a base for plugin bag field items.
+ */
+abstract class PluginBagItemBase extends FieldItemBase {
+
+  /**
+   * Returns the plugin manager.
+   *
+   * @return \Drupal\Component\Plugin\PluginManagerInterface
+   */
+  abstract protected function getPluginManager();
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
+    $properties['plugin_id'] = DataDefinition::create('string')
+      ->setLabel(t('Plugin ID'));
+    $properties['plugin_configuration'] = DataReferenceDefinition::create('map')
+      ->setLabel(t('Plugin configuration'));
+    $properties['plugin'] = DataReferenceDefinition::create('any')
+      ->setLabel(t('Plugin'))
+      ->setComputed(TRUE)
+      ->setReadOnly(FALSE);
+
+    return $properties;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function onChange($property_name) {
+    if ($property_name == 'plugin') {
+      /** @var \Drupal\Component\Plugin\PluginInspectionInterface $plugin */
+      $plugin = $this->get('plugin')->getValue();
+      $this->properties['plugin_id']->setValue($plugin->getPluginId(), FALSE);
+      if ($plugin instanceof ConfigurablePluginInterface) {
+        /** @var \Drupal\Component\Plugin\ConfigurablePluginInterface $plugin */
+        $this->properties['plugin_configuration']->setValue($plugin->getConfiguration(), FALSE);
+      }
+    }
+    if ($property_name == 'plugin_id') {
+      /** @var \Drupal\Component\Plugin\PluginInspectionInterface $plugin */
+      $plugin = $this->getPluginManager()->createInstance($this->get('plugin_id')->getValue());
+      $this->properties['plugin']->setValue($plugin, FALSE);
+      if ($plugin instanceof ConfigurablePluginInterface) {
+        /** @var \Drupal\Component\Plugin\ConfigurablePluginInterface $plugin */
+        $plugin_configuration = $plugin->getConfiguration();
+      }
+      else {
+        $plugin_configuration = array();
+      }
+      $this->properties['plugin_configuration']->setValue($plugin_configuration, FALSE);
+    }
+    parent::onChange($property_name);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function mainPropertyName() {
+    return 'plugin';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
+    $columns = array(
+      'plugin_id' => array(
+        'description' => 'The plugin ID.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+      ),
+      'plugin_configuration' => array(
+        'description' => 'The plugin configuration.',
+        'type' => 'blob',
+        'not null' => TRUE,
+        'serialize' => TRUE,
+      ),
+    );
+
+    $schema = array(
+      'columns' => $columns,
+    );
+
+    return $schema;
+  }
+
+}
