diff --git a/core/config/schema/core.data_types.schema.yml b/core/config/schema/core.data_types.schema.yml
index 73db361..9972985 100644
--- a/core/config/schema/core.data_types.schema.yml
+++ b/core/config/schema/core.data_types.schema.yml
@@ -580,6 +580,9 @@ field.field_settings.entity_reference:
   type: mapping
   label: 'Entity reference field settings'
   mapping:
+    serialize_embedded_entities:
+      type: boolean
+      label: 'Serialize entity references together with the parent entity'
     handler:
       type: string
       label: 'Reference method'
diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php
index 3834dae..309a37d 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php
@@ -325,7 +325,7 @@ protected function has($id, EntityInterface $entity) {
    * @return \Drupal\Core\Entity\EntityInterface[]
    *   Array of entities from the entity cache.
    */
-  protected function getFromStaticCache(array $ids) {
+  public function getFromStaticCache(array $ids) {
     $entities = array();
     // Load any available entities from the internal cache.
     if ($this->entityType->isStaticallyCacheable() && !empty($this->entities)) {
@@ -347,7 +347,7 @@ protected function getFromStaticCache(array $ids) {
    * @param \Drupal\Core\Entity\EntityInterface[] $entities
    *   Entities to store in the cache.
    */
-  protected function setStaticCache(array $entities) {
+  public function setStaticCache(array $entities) {
     if ($this->entityType->isStaticallyCacheable()) {
       $config_overrides_key = $this->overrideFree ? '' : implode(':', $this->configFactory->getCacheKeys());
       foreach ($entities as $id => $entity) {
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index 1d69be2..b3fbc18 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -3,6 +3,7 @@
 namespace Drupal\Core\Entity;
 
 use Drupal\Component\Utility\SafeMarkup;
+use Drupal\Core\Cache\Cache;
 use Drupal\Core\Entity\Plugin\DataType\EntityReference;
 use Drupal\Core\Field\BaseFieldDefinition;
 use Drupal\Core\Language\Language;
@@ -51,6 +52,16 @@
   protected $fieldDefinitions;
 
   /**
+   * Local cache for field definitions filtered by setting.
+   *
+   * @see ContentEntityBase::getFieldDefinitionsFilteredBySetting()
+   *
+   * @var array
+   */
+  protected $fieldDefinitionsFilteredBySetting;
+
+
+  /**
    * Local cache for the available language objects.
    *
    * @var \Drupal\Core\Language\LanguageInterface[]
@@ -407,15 +418,72 @@ protected function clearTranslationCache() {
   }
 
   /**
+   * Gets an array of field definitions of all contained fields filtered by the
+   * given setting and its value.
+   *
+   * @param string $setting
+   *   The name of the setting.
+   * @param string $value
+   *   The value of the setting.
+   *
+   * @return \Drupal\Core\Field\FieldDefinitionInterface[]
+   *   An array of field definitions, keyed by field name.
+   *
+   * @see \Drupal\Core\Entity\EntityFieldManagerInterface::getFieldDefinitions()
+   */
+  protected function getFieldDefinitionsFilteredBySetting($setting, $value) {
+    if (!isset($this->fieldDefinitionsFilteredBySetting[$setting][$value])) {
+      // Initialize the combination of setting and a value in case there is
+      // nothing found to not iterate over the field definitions again.
+      $this->fieldDefinitionsFilteredBySetting[$setting][$value] = [];
+      foreach ($this->getFieldDefinitions() as $name => $definition) {
+        if ($definition->getSetting($setting) == $value) {
+          $this->fieldDefinitionsFilteredBySetting[$setting][$value][$name] = $definition;
+        }
+      }
+    }
+
+    return $this->fieldDefinitionsFilteredBySetting[$setting][$value];
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function __sleep() {
+    $serialize_fields_with_embedded_entities = $this->getFieldDefinitionsFilteredBySetting('serialize_embedded_entities', TRUE);
+    $langcodes = array_keys($this->getTranslationLanguages());
+    foreach ($serialize_fields_with_embedded_entities as $name => $definition) {
+      // Initialize not yet initialized fields for which the computed field
+      // values have to be serialized.
+      $iterate_langcodes = $definition->isTranslatable() ? $langcodes : [$this->language()->getId()];
+      foreach ($iterate_langcodes as $langcode) {
+        if (!isset($this->fields[$name][$langcode])) {
+          $this->getTranslatedField($name, $langcode);
+        }
+      }
+    }
+
     // Get the values of instantiated field objects, only serialize the values.
     foreach ($this->fields as $name => $fields) {
       foreach ($fields as $langcode => $field) {
-        $this->values[$name][$langcode] = $field->getValue();
+
+        // TODO remove this check after https://www.drupal.org/node/2828133
+        // gets in.
+        if (!$serialize_fields_with_embedded_entities[$name]->isTranslatable() && ($langcode != LanguageInterface::LANGCODE_DEFAULT)) {
+          continue;
+        }
+
+        $this->values[$name][$langcode] = $field->getValue(isset($serialize_fields_with_embedded_entities[$name]));
+        if (isset($serialize_fields_with_embedded_entities[$name])) {
+            foreach ($this->values[$name][$langcode] as $value) {
+            if (isset($value['entity']) && ($value['entity'] instanceof EntityInterface)) {
+              $this->cacheTags = Cache::mergeTags($this->cacheTags, $value['entity']->getCacheTags());
+            }
+          }
+        }
       }
     }
+
     $this->fields = array();
     $this->fieldDefinitions = NULL;
     $this->languages = NULL;
@@ -424,6 +492,37 @@ public function __sleep() {
     return parent::__sleep();
   }
 
+  public function __wakeup() {
+    parent::__wakeup();
+
+    $entity_storages = [];
+    foreach (array_keys($this->getFieldDefinitionsFilteredBySetting('serialize_embedded_entities', TRUE)) as $field_name) {
+      foreach ($this->values[$field_name] as $langcode => $values) {
+        foreach ($values as $delta => $value) {
+          /** @var EntityInterface $entity */
+          $entity = isset($value['entity']) ? $value['entity'] : NULL;
+          if ($entity && !$entity->isNew()) {
+            // Cover the case where an entity reference field might reference
+            // different entity types at once.
+            $entity_type_id = $entity->getEntityTypeId();
+            $current_entity_storage = isset($entity_storages[$entity_type_id]) ? $entity_storages[$entity_type_id] : $this->entityTypeManager()->getStorage($entity_type_id);
+            $consider_static_cache = $entity->getEntityType()->isRevisionable() && $entity instanceof RevisionableInterface && $entity->isDefaultRevision() || !($entity instanceof RevisionableInterface);
+            if (!$consider_static_cache) {
+              continue;
+            }
+            elseif ($static_cache_entities = $current_entity_storage->getFromStaticCache([$entity->id()])) {
+              $value['entity'] = $static_cache_entities[$entity->id()];
+            }
+            else {
+              $current_entity_storage->setStaticCache([$entity->id() => $entity]);
+            }
+          }
+        }
+      }
+    }
+
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -807,7 +906,7 @@ protected function initializeTranslation($langcode) {
    * {@inheritdoc}
    */
   public function hasTranslation($langcode) {
-    if ($langcode == $this->defaultLangcode) {
+    if ($langcode == $this->defaultLangcode) {#
       $langcode = LanguageInterface::LANGCODE_DEFAULT;
     }
     return !empty($this->translations[$langcode]['status']);
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
index afdce40..5daf137 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
@@ -596,7 +596,7 @@ protected function getFromPersistentCache(array &$ids = NULL) {
       foreach ($ids as $index => $id) {
         $cid = $cid_map[$id];
         if (isset($cache[$cid])) {
-          $entities[$id] = $cache[$cid]->data;
+          $entities[$id] = unserialize($cache[$cid]->data);
           unset($ids[$index]);
         }
       }
@@ -620,7 +620,11 @@ protected function setPersistentCache($entities) {
       'entity_field_info',
     );
     foreach ($entities as $id => $entity) {
-      $this->cacheBackend->set($this->buildCacheId($id), $entity, CacheBackendInterface::CACHE_PERMANENT, $cache_tags);
+      // We first have to serialize the entity as during the serialization
+      // process the entity cache tags might be extended.
+      $serialized_entity = serialize($entity);
+      $entity_cache_tags = Cache::mergeTags($cache_tags, $entity->getCacheTags());
+      $this->cacheBackend->set($this->buildCacheId($id), $serialized_entity, CacheBackendInterface::CACHE_PERMANENT, $entity_cache_tags);
     }
   }
 
diff --git a/core/lib/Drupal/Core/Entity/EntityStorageBase.php b/core/lib/Drupal/Core/Entity/EntityStorageBase.php
index f583121..634dc95 100644
--- a/core/lib/Drupal/Core/Entity/EntityStorageBase.php
+++ b/core/lib/Drupal/Core/Entity/EntityStorageBase.php
@@ -132,7 +132,7 @@ public function resetCache(array $ids = NULL) {
    * @return \Drupal\Core\Entity\EntityInterface[]
    *   Array of entities from the entity cache.
    */
-  protected function getFromStaticCache(array $ids) {
+  public function getFromStaticCache(array $ids) {
     $entities = array();
     // Load any available entities from the internal cache.
     if ($this->entityType->isStaticallyCacheable() && !empty($this->entities)) {
@@ -147,7 +147,7 @@ protected function getFromStaticCache(array $ids) {
    * @param \Drupal\Core\Entity\EntityInterface[] $entities
    *   Entities to store in the cache.
    */
-  protected function setStaticCache(array $entities) {
+  public function setStaticCache(array $entities) {
     if ($this->entityType->isStaticallyCacheable()) {
       $this->entities += $entities;
     }
diff --git a/core/lib/Drupal/Core/Field/EntityReferenceInlineWidgetBase.php b/core/lib/Drupal/Core/Field/EntityReferenceInlineWidgetBase.php
new file mode 100644
index 0000000..251129c
--- /dev/null
+++ b/core/lib/Drupal/Core/Field/EntityReferenceInlineWidgetBase.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Drupal\Core\Field;
+
+/**
+ * Base class for 'Entity Reference Inline Widget' plugin implementations.
+ *
+ * @ingroup field_widget
+ */
+abstract class EntityReferenceInlineWidgetBase extends WidgetBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function isApplicable(FieldDefinitionInterface $field_definition) {
+    return (bool) $field_definition->getSetting('serialize_embedded_entities');
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
index 63bd90d..fd84fa1 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
@@ -53,6 +53,7 @@ public static function defaultStorageSettings() {
    */
   public static function defaultFieldSettings() {
     return array(
+      'serialize_embedded_entities' => FALSE,
       'handler' => 'default',
       'handler_settings' => array(),
     ) + parent::defaultFieldSettings();
@@ -189,7 +190,7 @@ public function setValue($values, $notify = TRUE) {
         // If the entity has been saved and we're trying to set both the
         // target_id and the entity values with a non-null target ID, then the
         // value for target_id should match the ID of the entity value.
-        if (!$this->entity->isNew() && $values['target_id'] !== NULL && ($entity_id !== $values['target_id'])) {
+        if (!$this->entity->isNew() && $values['target_id'] !== NULL && ($entity_id != $values['target_id'])) {
           throw new \InvalidArgumentException('The target id and entity passed to the entity reference item do not match.');
         }
       }
@@ -204,12 +205,12 @@ public function setValue($values, $notify = TRUE) {
   /**
    * {@inheritdoc}
    */
-  public function getValue() {
+  public function getValue($include_computed = FALSE) {
     $values = parent::getValue();
 
     // If there is an unsaved entity, return it as part of the field item values
     // to ensure idempotency of getValue() / setValue().
-    if ($this->hasNewEntity()) {
+    if ($include_computed || $this->hasNewEntity()) {
       $values['entity'] = $this->entity;
     }
     return $values;
@@ -339,6 +340,14 @@ public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
       '#element_validate' => array(array(get_class($this), 'fieldSettingsFormValidate')),
 
     );
+
+    $form['serialize_embedded_entities'] = array(
+      '#type' => 'checkbox',
+      '#title' => $this->t('Serialize entity references together with the parent entity'),
+      '#description' => $this->t('If the field widget to be used for this field is an entity reference inline widget then the setting must be set.'),
+      '#default_value' => $field->getSetting('serialize_embedded_entities'),
+    );
+
     $form['handler'] = array(
       '#type' => 'details',
       '#title' => t('Reference type'),
diff --git a/core/modules/field/field.install b/core/modules/field/field.install
index ecd2b31..0c30a1b 100644
--- a/core/modules/field/field.install
+++ b/core/modules/field/field.install
@@ -104,3 +104,30 @@ function field_update_8003() {
     }
   }
 }
+
+/**
+ * Populate the new 'serialize_embedded_entities' setting for entity reference
+ * fields.
+ */
+function field_update_8004() {
+  $config = \Drupal::configFactory();
+  /** @var \Drupal\Core\Field\FieldTypePluginManager $field_type_manager */
+  $field_type_manager = \Drupal::service('plugin.manager.field.field_type');
+
+  // Iterate over all fields.
+  foreach ($config->listAll('field.field.') as $field_id) {
+    $field = $config->getEditable($field_id);
+    $class = $field_type_manager->getPluginClass($field->get('field_type'));
+
+    // Deal only with entity reference fields and descendants.
+    if ($class == EntityReferenceItem::class || is_subclass_of($class, EntityReferenceItem::class)) {
+      $settings = $field->get('settings');
+
+      if (!isset($settings['serialize_embedded_entities'])) {
+        $settings['serialize_embedded_entities'] = FALSE;
+      }
+
+      $field->set('settings', $settings)->save(TRUE);
+    }
+  }
+}
