diff --git a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
index 25d4a5a..fd47128 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
@@ -118,10 +118,10 @@ public function onFieldDefinitionDelete(FieldDefinitionInterface $field_definiti
    */
   public function purgeFieldData(FieldDefinitionInterface $field_definition, $batch_size) {
     $items_by_entity = $this->readFieldItemsToPurge($field_definition, $batch_size);
-
     foreach ($items_by_entity as $items) {
-      $items->delete();
+      $items->preDelete();
       $this->purgeFieldItems($items->getEntity(), $field_definition);
+      $items->delete();
     }
     return count($items_by_entity);
   }
@@ -183,8 +183,17 @@ protected function invokeTranslationHooks(ContentEntityInterface $entity) {
    * {@inheritdoc}
    */
   protected function invokeHook($hook, EntityInterface $entity) {
-    if ($hook == 'presave') {
-      $this->invokeFieldMethod('preSave', $entity);
+    $map = [
+      'presave' => 'preSave',
+      'insert' => 'insert',
+      'update' => 'update',
+      'predelete' => 'preDelete',
+      'delete' => 'delete',
+      'revision_predelete' => 'preDeleteRevision',
+      'revision_delete' => 'deleteRevision',
+      ];
+    if (isset($map[$hook])) {
+      $this->invokeFieldMethod($map[$hook], $entity);
     }
     parent::invokeHook($hook, $entity);
   }
diff --git a/core/lib/Drupal/Core/Entity/EntityStorageBase.php b/core/lib/Drupal/Core/Entity/EntityStorageBase.php
index 55d5317..69703ae 100644
--- a/core/lib/Drupal/Core/Entity/EntityStorageBase.php
+++ b/core/lib/Drupal/Core/Entity/EntityStorageBase.php
@@ -163,8 +163,8 @@ protected function setStaticCache(array $entities) {
    * Invokes a hook on behalf of the entity.
    *
    * @param string $hook
-   *   One of 'presave', 'insert', 'update', 'predelete', 'delete', or
-   *  'revision_delete'.
+   *   One of 'presave', 'insert', 'update', 'predelete', 'delete',
+   *  'revision_predelete' or 'revision_delete'.
    * @param \Drupal\Core\Entity\EntityInterface  $entity
    *   The entity object.
    */
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index 924f6a8..f9463da 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -753,10 +753,10 @@ public function deleteRevision($revision_id) {
         throw new EntityStorageException('Default revision can not be deleted');
       }
 
+      $this->invokeHook('revision_predelete', $revision);
       $this->database->delete($this->revisionTable)
         ->condition($this->revisionKey, $revision->getRevisionId())
         ->execute();
-      $this->invokeFieldMethod('deleteRevision', $revision);
       $this->deleteRevisionFromDedicatedTables($revision);
       $this->invokeHook('revision_delete', $revision);
     }
@@ -903,7 +903,6 @@ protected function doDelete($entities) {
     }
 
     foreach ($entities as $entity) {
-      $this->invokeFieldMethod('delete', $entity);
       $this->deleteFromDedicatedTables($entity);
     }
   }
@@ -989,7 +988,6 @@ protected function doSave($id, EntityInterface $entity) {
         $this->saveToSharedTables($entity, $this->revisionDataTable);
       }
     }
-    $this->invokeFieldMethod($is_new ? 'insert' : 'update', $entity);
     $this->saveToDedicatedTables($entity, !$is_new);
 
     if (!$is_new && $this->dataTable) {
diff --git a/core/lib/Drupal/Core/Field/FieldItemBase.php b/core/lib/Drupal/Core/Field/FieldItemBase.php
index 1bb5486..3061ca4 100644
--- a/core/lib/Drupal/Core/Field/FieldItemBase.php
+++ b/core/lib/Drupal/Core/Field/FieldItemBase.php
@@ -212,6 +212,11 @@ public function update() { }
   /**
    * {@inheritdoc}
    */
+  public function preDelete() { }
+
+  /**
+   * {@inheritdoc}
+   */
   public function delete() { }
 
   /**
@@ -222,6 +227,11 @@ public static function generateSampleValue(FieldDefinitionInterface $field_defin
   /**
    * {@inheritdoc}
    */
+  public function preDeleteRevision() { }
+
+  /**
+   * {@inheritdoc}
+   */
   public function deleteRevision() { }
 
   /**
diff --git a/core/lib/Drupal/Core/Field/FieldItemInterface.php b/core/lib/Drupal/Core/Field/FieldItemInterface.php
index a2339ac..fd63c8e 100644
--- a/core/lib/Drupal/Core/Field/FieldItemInterface.php
+++ b/core/lib/Drupal/Core/Field/FieldItemInterface.php
@@ -192,33 +192,50 @@ public function preSave();
    * Defines custom insert behavior for field values.
    *
    * This method is called during the process of inserting an entity, just
-   * before values are written into storage.
+   * after values are written into storage.
    */
   public function insert();
 
   /**
    * Defines custom update behavior for field values.
    *
-   * This method is called during the process of updating an entity, just before
+   * This method is called during the process of updating an entity, just after
    * values are written into storage.
    */
   public function update();
 
   /**
-   * Defines custom delete behavior for field values.
+   * Defines custom predelete behavior for field values.
    *
    * This method is called during the process of deleting an entity, just before
    * values are deleted from storage.
    */
+  public function preDelete();
+
+  /**
+   * Defines custom delete behavior for field values.
+   *
+   * This method is called during the process of deleting an entity, just after
+   * values are deleted from storage.
+   */
   public function delete();
 
   /**
-   * Defines custom revision delete behavior for field values.
+   * Defines custom revision predelete behavior for field values.
    *
    * This method is called from during the process of deleting an entity
    * revision, just before the field values are deleted from storage. It is only
    * called for entity types that support revisioning.
    */
+  public function preDeleteRevision();
+
+  /**
+   * Defines custom revision delete behavior for field values.
+   *
+   * This method is called from during the process of deleting an entity
+   * revision, just after the field values are deleted from storage. It is only
+   * called for entity types that support revisioning.
+   */
   public function deleteRevision();
 
   /**
diff --git a/core/lib/Drupal/Core/Field/FieldItemList.php b/core/lib/Drupal/Core/Field/FieldItemList.php
index 86bac79..814e114 100644
--- a/core/lib/Drupal/Core/Field/FieldItemList.php
+++ b/core/lib/Drupal/Core/Field/FieldItemList.php
@@ -226,6 +226,13 @@ public function update() {
   /**
    * {@inheritdoc}
    */
+  public function preDelete() {
+    $this->delegateMethod('preDelete');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function delete() {
     $this->delegateMethod('delete');
   }
@@ -233,6 +240,13 @@ public function delete() {
   /**
    * {@inheritdoc}
    */
+  public function preDeleteRevision() {
+    $this->delegateMethod('preDeleteRevision');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function deleteRevision() {
     $this->delegateMethod('deleteRevision');
   }
diff --git a/core/lib/Drupal/Core/Field/FieldItemListInterface.php b/core/lib/Drupal/Core/Field/FieldItemListInterface.php
index e4ea12c..65c1d22 100644
--- a/core/lib/Drupal/Core/Field/FieldItemListInterface.php
+++ b/core/lib/Drupal/Core/Field/FieldItemListInterface.php
@@ -138,7 +138,7 @@ public function preSave();
   /**
    * Defines custom insert behavior for field values.
    *
-   * This method is called after the save() method, and before values are
+   * This method is called after the save() method, and after values are
    * written into storage.
    */
   public function insert();
@@ -146,26 +146,43 @@ public function insert();
   /**
    * Defines custom update behavior for field values.
    *
-   * This method is called after the save() method, and before values are
+   * This method is called after the save() method, and after values are
    * written into storage.
    */
   public function update();
 
   /**
-   * Defines custom delete behavior for field values.
+   * Defines custom predelete behavior for field values.
    *
    * This method is called during the process of deleting an entity, just before
    * values are deleted from storage.
    */
+  public function preDelete();
+
+  /**
+   * Defines custom delete behavior for field values.
+   *
+   * This method is called during the process of deleting an entity, just after
+   * values are deleted from storage.
+   */
   public function delete();
 
   /**
-   * Defines custom revision delete behavior for field values.
+   * Defines custom revision predelete behavior for field values.
    *
    * This method is called from during the process of deleting an entity
    * revision, just before the field values are deleted from storage. It is only
    * called for entity types that support revisioning.
    */
+  public function preDeleteRevision();
+
+  /**
+   * Defines custom revision delete behavior for field values.
+   *
+   * This method is called from during the process of deleting an entity
+   * revision, just after the field values are deleted from storage. It is only
+   * called for entity types that support revisioning.
+   */
   public function deleteRevision();
 
   /**
diff --git a/core/modules/field/src/Tests/BulkDeleteTest.php b/core/modules/field/src/Tests/BulkDeleteTest.php
index de49be1..087491a 100644
--- a/core/modules/field/src/Tests/BulkDeleteTest.php
+++ b/core/modules/field/src/Tests/BulkDeleteTest.php
@@ -246,12 +246,13 @@ function testPurgeField() {
     }
 
     // Check hooks invocations.
-    // FieldItemInterface::delete() should have been called once for each entity in the
-    // bundle.
+    // FieldItemInterface::preDelete() and FieldItemInterface::delete() should
+    // have been called once for each entity in the bundle.
     $actual_hooks = field_test_memorize();
     $hooks = array();
     $entities = $this->entitiesByBundles[$bundle];
     foreach ($entities as $id => $entity) {
+      $hooks['field_test_field_predelete'][] = $entity;
       $hooks['field_test_field_delete'][] = $entity;
     }
     $this->checkHooksInvocations($hooks, $actual_hooks);
@@ -297,12 +298,13 @@ function testPurgeFieldStorage() {
     field_purge_batch(10);
 
     // Check hooks invocations.
-    // FieldItemInterface::delete() should have been called once for each entity in the
-    // bundle.
+    // FieldItemInterface::preDelete() and FieldItemInterface::delete() should
+    // have been called once for each entity in the bundle.
     $actual_hooks = field_test_memorize();
     $hooks = array();
     $entities = $this->entitiesByBundles[$bundle];
     foreach ($entities as $id => $entity) {
+      $hooks['field_test_field_predelete'][] = $entity;
       $hooks['field_test_field_delete'][] = $entity;
     }
     $this->checkHooksInvocations($hooks, $actual_hooks);
@@ -338,6 +340,7 @@ function testPurgeFieldStorage() {
     $hooks = array();
     $entities = $this->entitiesByBundles[$bundle];
     foreach ($entities as $id => $entity) {
+      $hooks['field_test_field_predelete'][] = $entity;
       $hooks['field_test_field_delete'][] = $entity;
     }
     $this->checkHooksInvocations($hooks, $actual_hooks);
diff --git a/core/modules/field/tests/modules/field_test/src/Plugin/Field/FieldType/TestItem.php b/core/modules/field/tests/modules/field_test/src/Plugin/Field/FieldType/TestItem.php
index 9886b03..ce07680 100644
--- a/core/modules/field/tests/modules/field_test/src/Plugin/Field/FieldType/TestItem.php
+++ b/core/modules/field/tests/modules/field_test/src/Plugin/Field/FieldType/TestItem.php
@@ -106,8 +106,16 @@ public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
   /**
    * {@inheritdoc}
    */
+  public function preDelete() {
+    // Reports that preDelete() method is executed for testing purposes.
+    field_test_memorize('field_test_field_predelete', array($this->getEntity()));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function delete() {
-    // Reports that delete() method is executed for testing purposes.
+    // Reports that preDelete() method is executed for testing purposes.
     field_test_memorize('field_test_field_delete', array($this->getEntity()));
   }
 
diff --git a/core/modules/file/src/Plugin/Field/FieldType/FileFieldItemList.php b/core/modules/file/src/Plugin/Field/FieldType/FileFieldItemList.php
index f8ee03c..8f495cd 100644
--- a/core/modules/file/src/Plugin/Field/FieldType/FileFieldItemList.php
+++ b/core/modules/file/src/Plugin/Field/FieldType/FileFieldItemList.php
@@ -83,8 +83,8 @@ public function update() {
   /**
    * {@inheritdoc}
    */
-  public function delete() {
-    parent::delete();
+  public function preDelete() {
+    parent::preDelete();
     $entity = $this->getEntity();
 
     // Delete all file usages within this entity.
diff --git a/core/modules/path/src/Plugin/Field/FieldType/PathItem.php b/core/modules/path/src/Plugin/Field/FieldType/PathItem.php
index c06271d..d0cf4f7 100644
--- a/core/modules/path/src/Plugin/Field/FieldType/PathItem.php
+++ b/core/modules/path/src/Plugin/Field/FieldType/PathItem.php
@@ -83,7 +83,7 @@ public function update() {
   /**
    * {@inheritdoc}
    */
-  public function delete() {
+  public function preDelete() {
     // Delete all aliases associated with this entity.
     $entity = $this->getEntity();
     \Drupal::service('path.alias_storage')->delete(array('source' => $entity->urlInfo()->getInternalPath()));
diff --git a/core/modules/system/entity.api.php b/core/modules/system/entity.api.php
index 9d9b33e..0376e10 100644
--- a/core/modules/system/entity.api.php
+++ b/core/modules/system/entity.api.php
@@ -1179,6 +1179,40 @@ function hook_ENTITY_TYPE_delete(Drupal\Core\Entity\EntityInterface $entity) {
 }
 
 /**
+ * Act before entity revision deletion.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ *   The entity object for the entity revision that is about to be deleted.
+ *
+ * @ingroup entity_crud
+ * @see hook_ENTITY_TYPE_revision_predelete()
+ */
+function hook_entity_revision_predelete(Drupal\Core\Entity\EntityInterface $entity) {
+  // Delete the entity's entry from a fictional table of all entities.
+  db_delete('example_entity')
+    ->condition('type', $entity->getEntityTypeId())
+    ->condition('id', $entity->id())
+    ->execute();
+}
+
+/**
+ * Act before entity revision deletion of a particular entity type.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ *   The entity object for the entity revision that is about to be deleted.
+ *
+ * @ingroup entity_crud
+ * @see hook_entity_revision_predelete()
+ */
+function hook_ENTITY_TYPE_revision_predelete(Drupal\Core\Entity\EntityInterface $entity) {
+  // Delete the entity's entry from a fictional table of all entities.
+  db_delete('example_entity')
+    ->condition('type', $entity->getEntityTypeId())
+    ->condition('id', $entity->id())
+    ->execute();
+}
+
+/**
  * Respond to entity revision deletion.
  *
  * This hook runs once the entity revision has been deleted from the storage.
