diff --git a/core/modules/views/src/Entity/View.php b/core/modules/views/src/Entity/View.php
index ecd541e..63d3ba1 100644
--- a/core/modules/views/src/Entity/View.php
+++ b/core/modules/views/src/Entity/View.php
@@ -433,4 +433,13 @@ public function isInstallable() {
     return (bool) \Drupal::service('views.views_data')->get($this->base_table);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function __sleep() {
+    $keys = parent::__sleep();
+    unset($keys[array_search('executable', $keys)]);
+    return $keys;
+  }
+
 }
diff --git a/core/modules/views/src/Form/ViewsExposedForm.php b/core/modules/views/src/Form/ViewsExposedForm.php
index 5e2eee9..0fdd2ea 100644
--- a/core/modules/views/src/Form/ViewsExposedForm.php
+++ b/core/modules/views/src/Form/ViewsExposedForm.php
@@ -121,7 +121,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
     $form['#id'] = Html::cleanCssIdentifier('views_exposed_form-' . String::checkPlain($view->storage->id()) . '-' . String::checkPlain($display['id']));
 
     /** @var \Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase $exposed_form_plugin */
-    $exposed_form_plugin = $form_state->get('exposed_form_plugin');
+    $exposed_form_plugin = $view->display_handler->getPlugin('exposed_form');
     $exposed_form_plugin->exposedFormAlter($form, $form_state);
 
     // Save the form.
@@ -134,15 +134,17 @@ public function buildForm(array $form, FormStateInterface $form_state) {
    * {@inheritdoc}
    */
   public function validateForm(array &$form, FormStateInterface $form_state) {
+    $view = $form_state->get('view');
+
     foreach (array('field', 'filter') as $type) {
       /** @var \Drupal\views\Plugin\views\ViewsHandlerInterface[] $handlers */
-      $handlers = &$form_state->get('view')->$type;
+      $handlers = &$view->$type;
       foreach ($handlers as $key => $handler) {
         $handlers[$key]->validateExposed($form, $form_state);
       }
     }
     /** @var \Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase $exposed_form_plugin */
-    $exposed_form_plugin = $form_state->get('exposed_form_plugin');
+    $exposed_form_plugin = $view->display_handler->getPlugin('exposed_form');
     $exposed_form_plugin->exposedFormValidate($form, $form_state);
   }
 
@@ -157,13 +159,14 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
         $handlers[$key]->submitExposed($form, $form_state);
       }
     }
+
     $view = $form_state->get('view');
     $view->exposed_data = $form_state->getValues();
     $view->exposed_raw_input = [];
 
-    $exclude = array('submit', 'form_build_id', 'form_id', 'form_token', 'exposed_form_plugin', '', 'reset');
+    $exclude = array('submit', 'form_build_id', 'form_id', 'form_token', 'exposed_form_plugin', 'reset');
     /** @var \Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase $exposed_form_plugin */
-    $exposed_form_plugin = $form_state->get('exposed_form_plugin');
+    $exposed_form_plugin = $view->display_handler->getPlugin('exposed_form');
     $exposed_form_plugin->exposedFormSubmit($form, $form_state, $exclude);
 
     foreach ($form_state->getValues() as $key => $value) {
diff --git a/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php b/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php
index 3652e8b..16f86a8 100644
--- a/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php
+++ b/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php
@@ -150,7 +150,6 @@ public function renderExposedForm($block = FALSE) {
       $form_state->set('ajax', TRUE);
     }
 
-    $form_state->set('exposed_form_plugin', $this);
     $form = \Drupal::formBuilder()->buildForm('\Drupal\views\Form\ViewsExposedForm', $form_state);
 
     if (!$this->view->display_handler->displaysExposed() || (!$block && $this->view->display_handler->getOption('exposed_block'))) {
diff --git a/core/modules/views/src/Plugin/views/relationship/RelationshipPluginBase.php b/core/modules/views/src/Plugin/views/relationship/RelationshipPluginBase.php
index bb6b803..34a2a9a 100644
--- a/core/modules/views/src/Plugin/views/relationship/RelationshipPluginBase.php
+++ b/core/modules/views/src/Plugin/views/relationship/RelationshipPluginBase.php
@@ -55,6 +55,13 @@
 abstract class RelationshipPluginBase extends HandlerBase {
 
   /**
+   * The relationship alias.
+   *
+   * @var string
+   */
+  public $alias;
+
+  /**
    * Overrides \Drupal\views\Plugin\views\HandlerBase::init().
    *
    * Init handler to let relationships live on tables other than
diff --git a/core/modules/views/src/ViewExecutable.php b/core/modules/views/src/ViewExecutable.php
index db01ad8..3d38a98 100644
--- a/core/modules/views/src/ViewExecutable.php
+++ b/core/modules/views/src/ViewExecutable.php
@@ -17,6 +17,7 @@
 use Drupal\views\Plugin\views\query\QueryPluginBase;
 use Drupal\views\ViewEntityInterface;
 use Drupal\Component\Utility\Tags;
+use Drupal\views_ui\ViewUI;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
 
@@ -26,7 +27,7 @@
  * An object to contain all of the data to generate a view, plus the member
  * functions to build the view query, execute the query and render the output.
  */
-class ViewExecutable {
+class ViewExecutable implements \Serializable {
   use DependencySerializationTrait;
 
   /**
@@ -2284,4 +2285,55 @@ public function calculateDependencies() {
     return $this->storage->calculateDependencies();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function serialize() {
+    if ($this->storage instanceof ViewUI) {
+      $storage = $this->storage;
+    }
+    else {
+      $storage = $this->storage->id();
+    }
+
+    return serialize([
+      $storage,
+      $this->current_display,
+      $this->args,
+      $this->current_page,
+      $this->exposed_input,
+      $this->exposed_raw_input,
+      $this->exposed_data,
+      $this->dom_id,
+      $this->executed,
+    ]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function unserialize($serialized) {
+    list($storage, $current_display, $args, $current_page, $exposed_input, $exposed_raw_input, $exposed_data, $dom_id, $executed) = unserialize($serialized);
+
+    $this->setRequest(\Drupal::request());
+    $this->user = \Drupal::currentUser();
+
+    $this->storage = is_object($storage) ? $storage : \Drupal::entityManager()->getStorage('view')->load($storage);
+
+    $this->setDisplay($current_display);
+    $this->setArguments($args);
+    $this->setCurrentPage($current_page);
+    $this->setExposedInput($exposed_input);
+    $this->exposed_data = $exposed_data;
+    $this->exposed_raw_input = $exposed_raw_input;
+    $this->dom_id = $dom_id;
+
+    $this->initHandlers();
+
+    // If the display was previously executed, execute it now.
+    if ($executed) {
+      $this->execute($this->current_display);
+    }
+  }
+
 }
diff --git a/core/modules/views/tests/src/Unit/ViewExecutableTest.php b/core/modules/views/tests/src/Unit/ViewExecutableTest.php
index 85b545c..51de164 100644
--- a/core/modules/views/tests/src/Unit/ViewExecutableTest.php
+++ b/core/modules/views/tests/src/Unit/ViewExecutableTest.php
@@ -465,4 +465,11 @@ protected function setupBaseViewAndDisplay() {
     return array($view, $display);
   }
 
+  /**
+   * Tests serialization of the ViewExecutable object.
+   */
+  public function testSerialization() {
+    // @todo
+  }
+
 }
diff --git a/core/modules/views_ui/src/ViewEditForm.php b/core/modules/views_ui/src/ViewEditForm.php
index 5d27d30..28b1175 100644
--- a/core/modules/views_ui/src/ViewEditForm.php
+++ b/core/modules/views_ui/src/ViewEditForm.php
@@ -266,6 +266,7 @@ public function validate(array $form, FormStateInterface $form_state) {
   public function save(array $form, FormStateInterface $form_state) {
     $view = $this->entity;
     $executable = $view->getExecutable();
+    $executable->initDisplay();
 
     // Go through and remove displayed scheduled for removal.
     $displays = $view->get('display');
diff --git a/core/modules/views_ui/src/ViewUI.php b/core/modules/views_ui/src/ViewUI.php
index 5d00c80..6a41d9b 100644
--- a/core/modules/views_ui/src/ViewUI.php
+++ b/core/modules/views_ui/src/ViewUI.php
@@ -173,10 +173,10 @@ class ViewUI implements ViewEntityInterface {
   public function __construct(ViewEntityInterface $storage, ViewExecutable $executable = NULL) {
     $this->entityType = 'view';
     $this->storage = $storage;
-    if (!isset($executable)) {
-      $executable = Views::executableFactory()->get($this);
+
+    if (isset($executable)) {
+      $this->executable = $executable;
     }
-    $this->executable = $executable;
   }
 
   /**
@@ -259,7 +259,7 @@ public function standardSubmit($form, FormStateInterface $form_state) {
     $display_id = $form_state->get('display_id');
     if ($revert) {
       // If it's revert just change the override and return.
-      $display = &$this->executable->displayHandlers->get($display_id);
+      $display = &$this->getExecutable()->displayHandlers->get($display_id);
       $display->optionsOverride($form, $form_state);
 
       // Don't execute the normal submit handling but still store the changed view into cache.
@@ -273,7 +273,7 @@ public function standardSubmit($form, FormStateInterface $form_state) {
     elseif ($was_defaulted && !$is_defaulted) {
       // We were using the default display's values, but we're now overriding
       // the default display and saving values specific to this display.
-      $display = &$this->executable->displayHandlers->get($display_id);
+      $display = &$this->getExecutable()->displayHandlers->get($display_id);
       // optionsOverride toggles the override of this section.
       $display->optionsOverride($form, $form_state);
       $display->submitOptionsForm($form, $form_state);
@@ -283,7 +283,7 @@ public function standardSubmit($form, FormStateInterface $form_state) {
       // to go back to the default display.
       // Overwrite the default display with the current form values, and make
       // the current display use the new default values.
-      $display = &$this->executable->displayHandlers->get($display_id);
+      $display = &$this->getExecutable()->displayHandlers->get($display_id);
       // optionsOverride toggles the override of this section.
       $display->optionsOverride($form, $form_state);
       $display->submitOptionsForm($form, $form_state);
@@ -481,7 +481,7 @@ public function submitItemAdd($form, FormStateInterface $form_state) {
     if ($was_defaulted && !$is_defaulted) {
       // We were using the default display's values, but we're now overriding
       // the default display and saving values specific to this display.
-      $display = &$this->executable->displayHandlers->get($display_id);
+      $display = &$this->getExecutable()->displayHandlers->get($display_id);
       // setOverride toggles the override of this section.
       $display->setOverride($section);
     }
@@ -490,7 +490,7 @@ public function submitItemAdd($form, FormStateInterface $form_state) {
       // to go back to the default display.
       // Overwrite the default display with the current form values, and make
       // the current display use the new default values.
-      $display = &$this->executable->displayHandlers->get($display_id);
+      $display = &$this->getExecutable()->displayHandlers->get($display_id);
       // optionsOverride toggles the override of this section.
       $display->setOverride($section);
     }
@@ -503,7 +503,7 @@ public function submitItemAdd($form, FormStateInterface $form_state) {
         if ($cut = strpos($field, '$')) {
           $field = substr($field, 0, $cut);
         }
-        $id = $this->executable->addHandler($display_id, $type, $table, $field);
+        $id = $this->getExecutable()->addHandler($display_id, $type, $table, $field);
 
         // check to see if we have group by settings
         $key = $type;
@@ -516,7 +516,7 @@ public function submitItemAdd($form, FormStateInterface $form_state) {
           'field' => $field,
         );
         $handler = Views::handlerManager($key)->getHandler($item);
-        if ($this->executable->displayHandlers->get('default')->useGroupBy() && $handler->usesGroupBy()) {
+        if ($this->getExecutable()->displayHandlers->get('default')->useGroupBy() && $handler->usesGroupBy()) {
           $this->addFormToStack('handler-group', $display_id, $type, $id);
         }
 
@@ -580,11 +580,11 @@ public function renderPreview($display_id, $args = array()) {
 
     $rows = array('query' => array(), 'statistics' => array());
 
-    $errors = $this->executable->validate();
-    $this->executable->destroy();
+    $errors = $this->getExecutable()->validate();
+    $this->getExecutable()->destroy();
     if (empty($errors)) {
       $this->ajax = TRUE;
-      $this->executable->live_preview = TRUE;
+      $this->getExecutable()->live_preview = TRUE;
 
       // AJAX happens via HTTP POST but everything expects exposed data to
       // be in GET. Copy stuff but remove ajax-framework specific keys.
@@ -597,19 +597,19 @@ public function renderPreview($display_id, $args = array()) {
           unset($exposed_input[$key]);
         }
       }
-      $this->executable->setExposedInput($exposed_input);
+      $this->getExecutable()->setExposedInput($exposed_input);
 
-      if (!$this->executable->setDisplay($display_id)) {
+      if (!$this->getExecutable()->setDisplay($display_id)) {
         return [
           '#markup' => t('Invalid display id @display', array('@display' => $display_id)),
         ];
       }
 
-      $this->executable->setArguments($args);
+      $this->getExecutable()->setArguments($args);
 
       // Store the current view URL for later use:
-      if ($this->executable->display_handler->getOption('path')) {
-        $path = $this->executable->getUrl();
+      if ($this->getExecutable()->display_handler->getOption('path')) {
+        $path = $this->getExecutable()->getUrl();
       }
 
       // Make view links come back to preview.
@@ -646,7 +646,7 @@ public function renderPreview($display_id, $args = array()) {
       }
 
       // Execute/get the view preview.
-      $preview = $this->executable->preview($display_id, $args);
+      $preview = $this->getExecutable()->preview($display_id, $args);
 
       if ($show_additional_queries) {
         $this->endQueryCapture();
@@ -660,13 +660,13 @@ public function renderPreview($display_id, $args = array()) {
       // below the view preview.
       if ($show_info || $show_query || $show_stats) {
         // Get information from the preview for display.
-        if (!empty($this->executable->build_info['query'])) {
+        if (!empty($this->getExecutable()->build_info['query'])) {
           if ($show_query) {
-            $query_string = $this->executable->build_info['query'];
+            $query_string = $this->getExecutable()->build_info['query'];
             // Only the sql default class has a method getArguments.
             $quoted = array();
 
-            if ($this->executable->query instanceof Sql) {
+            if ($this->getExecutable()->query instanceof Sql) {
               $quoted = $query_string->getArguments();
               $connection = Database::getConnection();
               foreach ($quoted as $key => $val) {
@@ -722,7 +722,7 @@ public function renderPreview($display_id, $args = array()) {
                   '#template' => "<strong>{% trans 'Title' %}</strong>",
                 ),
               ),
-              Xss::filterAdmin($this->executable->getTitle()),
+              Xss::filterAdmin($this->getExecutable()->getTitle()),
             );
             if (isset($path)) {
               // @todo Views should expect and store a leading /. See:
@@ -743,7 +743,7 @@ public function renderPreview($display_id, $args = array()) {
                   '#template' => "<strong>{% trans 'Query build time' %}</strong>",
                 ),
               ),
-              t('@time ms', array('@time' => intval($this->executable->build_time * 100000) / 100)),
+              t('@time ms', array('@time' => intval($this->getExecutable()->build_time * 100000) / 100)),
             );
 
             $rows['statistics'][] = array(
@@ -753,7 +753,7 @@ public function renderPreview($display_id, $args = array()) {
                   '#template' => "<strong>{% trans 'Query execute time' %}</strong>",
                 ),
               ),
-              t('@time ms', array('@time' => intval($this->executable->execute_time * 100000) / 100)),
+              t('@time ms', array('@time' => intval($this->getExecutable()->execute_time * 100000) / 100)),
             );
 
             $rows['statistics'][] = array(
@@ -763,7 +763,7 @@ public function renderPreview($display_id, $args = array()) {
                   '#template' => "<strong>{% trans 'View render time' %}</strong>",
                 ),
               ),
-              t('@time ms', array('@time' => intval($this->executable->render_time * 100000) / 100)),
+              t('@time ms', array('@time' => intval($this->getExecutable()->render_time * 100000) / 100)),
             );
           }
           \Drupal::moduleHandler()->alter('views_preview_info', $rows, $this->executable);
@@ -873,14 +873,14 @@ public function cacheSet() {
     if (isset($executable->current_display)) {
       // Add the knowledge of the changed display, too.
       $this->changed_display[$executable->current_display] = TRUE;
-      unset($executable->current_display);
+      $executable->current_display = NULL;
     }
 
-    // Unset handlers; we don't want to write these into the cache.
-    unset($executable->display_handler);
-    unset($executable->default_display);
+    // Unset handlers. We don't want to write these into the cache.
+    $executable->display_handler = NULL;
+    $executable->default_display = NULL;
     $executable->query = NULL;
-    unset($executable->displayHandlers);
+    $executable->displayHandlers = NULL;
     \Drupal::service('user.shared_tempstore')->get('views')->set($this->id(), $this);
   }
 
@@ -1132,7 +1132,11 @@ public static function postLoad(EntityStorageInterface $storage, array &$entitie
    * {@inheritdoc}
    */
   public function getExecutable() {
-    return $this->storage->getExecutable();
+    if (!isset($this->executable)) {
+      $this->executable = Views::executableFactory()->get($this);
+    }
+
+    return $this->executable;
   }
 
   /**
@@ -1242,13 +1246,6 @@ public function addDisplay($plugin_id = 'page', $title = NULL, $id = NULL) {
   /**
    * {@inheritdoc}
    */
-  public function getViewExecutable() {
-    return $this->storage->getViewExecutable();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function isInstallable() {
     return $this->storage->isInstallable();
   }
@@ -1287,4 +1284,11 @@ public function unsetThirdPartySetting($module, $key) {
   public function getThirdPartyProviders() {
     return $this->storage->getThirdPartyProviders();
   }
+
+  public function __sleep() {
+    $vars = get_object_vars($this);
+    unset($vars['executable']);
+    return array_keys($vars);
+  }
+
 }
