diff --git a/core/modules/node/src/Form/NodePreviewForm.php b/core/modules/node/src/Form/NodePreviewForm.php
index 8a4cce9..1d61f1f 100644
--- a/core/modules/node/src/Form/NodePreviewForm.php
+++ b/core/modules/node/src/Form/NodePreviewForm.php
@@ -7,6 +7,7 @@
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Form\FormBase;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Routing\RedirectDestinationInterface;
 use Drupal\Core\Url;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -33,7 +34,11 @@ class NodePreviewForm extends FormBase {
    * {@inheritdoc}
    */
   public static function create(ContainerInterface $container) {
-    return new static($container->get('entity.manager'), $container->get('config.factory'));
+    return new static(
+      $container->get('entity.manager'),
+      $container->get('config.factory'),
+      $container->get('redirect.destination')
+    );
   }
 
   /**
@@ -43,10 +48,15 @@ public static function create(ContainerInterface $container) {
    *   The entity manager service.
    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
    *   The configuration factory.
+   * @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination
+   *   The redirect destination service.
+   *
+   * @todo Make $redirect_destination required in Drupal 9.0.x.
    */
-  public function __construct(EntityManagerInterface $entity_manager, ConfigFactoryInterface $config_factory) {
+  public function __construct(EntityManagerInterface $entity_manager, ConfigFactoryInterface $config_factory, RedirectDestinationInterface $redirect_destination = NULL) {
     $this->entityManager = $entity_manager;
     $this->configFactory = $config_factory;
+    $this->redirectDestination = $redirect_destination;
   }
 
   /**
@@ -72,7 +82,15 @@ public function getFormId() {
   public function buildForm(array $form, FormStateInterface $form_state, EntityInterface $node = NULL) {
     $view_mode = $node->preview_view_mode;
 
-    $query_options = array('query' => array('uuid' => $node->uuid()));
+    $query_options = [];
+    if ($node->isNew()) {
+      $query_options['query']['uuid'] = $node->uuid();
+    }
+    $query = $this->getRequest()->query;
+    if ($destination = $query->has('destination')) {
+      $query_options['query']['destination'] = $query->get('destination');
+    }
+
     $form['backlink'] = array(
       '#type' => 'link',
       '#title' => $this->t('Back to content editing'),
@@ -116,10 +134,12 @@ public function buildForm(array $form, FormStateInterface $form_state, EntityInt
    * {@inheritdoc}
    */
   public function submitForm(array &$form, FormStateInterface $form_state) {
-    $form_state->setRedirect('entity.node.preview', array(
+    $route_parameters = [
       'node_preview' => $form_state->getValue('uuid'),
       'view_mode_id' => $form_state->getValue('view_mode'),
-    ));
+    ];
+    $options = ['query' => $this->redirectDestination->getAsArray()];
+    $form_state->setRedirect('entity.node.preview', $route_parameters, $options);
   }
 
 }
diff --git a/core/modules/node/src/NodeForm.php b/core/modules/node/src/NodeForm.php
index 3a9ed54..e5b9517 100644
--- a/core/modules/node/src/NodeForm.php
+++ b/core/modules/node/src/NodeForm.php
@@ -7,6 +7,7 @@
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Routing\RedirectDestinationInterface;
 use Drupal\user\PrivateTempStoreFactory;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -23,11 +24,6 @@ class NodeForm extends ContentEntityForm {
   protected $tempStoreFactory;
 
   /**
-   * Whether this node has been previewed or not.
-   */
-  protected $hasBeenPreviewed = FALSE;
-
-  /**
    * Constructs a NodeForm object.
    *
    * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
@@ -38,10 +34,15 @@ class NodeForm extends ContentEntityForm {
    *   The entity type bundle service.
    * @param \Drupal\Component\Datetime\TimeInterface $time
    *   The time service.
+   * @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination
+   *   The redirect destination service.
+   *
+   * @todo Make $redirect_destination required in Drupal 9.0.x.
    */
-  public function __construct(EntityManagerInterface $entity_manager, PrivateTempStoreFactory $temp_store_factory, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL) {
+  public function __construct(EntityManagerInterface $entity_manager, PrivateTempStoreFactory $temp_store_factory, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL, RedirectDestinationInterface $redirect_destination = NULL) {
     parent::__construct($entity_manager, $entity_type_bundle_info, $time);
     $this->tempStoreFactory = $temp_store_factory;
+    $this->redirectDestination = $redirect_destination;
   }
 
   /**
@@ -52,7 +53,8 @@ public static function create(ContainerInterface $container) {
       $container->get('entity.manager'),
       $container->get('user.private_tempstore'),
       $container->get('entity_type.bundle.info'),
-      $container->get('datetime.time')
+      $container->get('datetime.time'),
+      $container->get('redirect.destination')
     );
   }
 
@@ -73,8 +75,8 @@ public function form(array $form, FormStateInterface $form_state) {
       $form_state->setStorage($preview->getStorage());
       $form_state->setUserInput($preview->getUserInput());
 
-      // Rebuild the form.
-      $form_state->setRebuild();
+      // Cache the form state for submission request.
+      $form_state->setRequestMethod('POST')->setCached();
 
       // The combination of having user input and rebuilding the form means
       // that it will attempt to cache the form state which will fail if it is
@@ -84,7 +86,7 @@ public function form(array $form, FormStateInterface $form_state) {
       $this->entity = $preview->getFormObject()->getEntity();
       $this->entity->in_preview = NULL;
 
-      $this->hasBeenPreviewed = TRUE;
+      $form_state->set('has_been_previewed', TRUE);
     }
 
     /** @var \Drupal\node\NodeInterface $node */
@@ -186,7 +188,7 @@ protected function actions(array $form, FormStateInterface $form_state) {
     $node = $this->entity;
     $preview_mode = $node->type->entity->getPreviewMode();
 
-    $element['submit']['#access'] = $preview_mode != DRUPAL_REQUIRED || $this->hasBeenPreviewed;
+    $element['submit']['#access'] = $preview_mode != DRUPAL_REQUIRED || $form_state->get('has_been_previewed');
 
     // If saving is an option, privileged users get dedicated form submit
     // buttons to adjust the publishing status while saving in one go.
@@ -267,10 +269,19 @@ public function preview(array $form, FormStateInterface $form_state) {
     $store = $this->tempStoreFactory->get('node_preview');
     $this->entity->in_preview = TRUE;
     $store->set($this->entity->uuid(), $form_state);
-    $form_state->setRedirect('entity.node.preview', array(
+
+    $route_parameters = [
       'node_preview' => $this->entity->uuid(),
       'view_mode_id' => 'default',
-    ));
+    ];
+
+    $options = [];
+    $query = $this->getRequest()->query;
+    if ($query->has('destination')) {
+      $options['query'] = $this->redirectDestination->getAsArray();
+      $query->remove('destination');
+    }
+    $form_state->setRedirect('entity.node.preview', $route_parameters, $options);
   }
 
   /**
diff --git a/core/modules/node/src/Tests/PagePreviewTest.php b/core/modules/node/src/Tests/PagePreviewTest.php
index 2afcc8d..fe76ef1 100644
--- a/core/modules/node/src/Tests/PagePreviewTest.php
+++ b/core/modules/node/src/Tests/PagePreviewTest.php
@@ -6,6 +6,7 @@
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Language\LanguageInterface;
+use Drupal\Core\Url;
 use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
 use Drupal\field\Entity\FieldConfig;
 use Drupal\field\Entity\FieldStorageConfig;
@@ -292,6 +293,18 @@ function testPagePreview() {
     $this->clickLink(t('Back to content editing'));
     $this->assertRaw('edit-submit');
 
+    // Check that destination is remembered when clicking on preview. When going
+    // back to the edit form and clicking save, we should go back to the
+    // original destination, if set.
+    $destination = 'node';
+    $this->drupalPostForm($node->toUrl('edit-form'), [], t('Preview'), ['query' => ['destination' => $destination]]);
+    $parameters = ['node_preview' => $node->uuid(), 'view_mode_id' => 'default'];
+    $options = ['absolute' => TRUE, 'query' => ['destination' => $destination]];
+    $this->assertUrl(Url::fromRoute('entity.node.preview', $parameters, $options));
+    $this->clickLink(t('Back to content editing'));
+    $this->drupalPostForm(NULL, [], t('Save'));
+    $this->assertUrl($destination);
+
     // Assert multiple items can be added and are not lost when previewing.
     $test_image_1 = current($this->drupalGetTestFiles('image', 39325));
     $edit_image_1['files[field_image_0][]'] = drupal_realpath($test_image_1->uri);
