diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php
index bc99b02..2d47e76 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php
@@ -2130,11 +2130,59 @@ public function executeHookMenuLinkDefaults(array &$existing_links) {
    * Render this display.
    */
   public function render() {
+    $view_id = $this->view->storage->id();
     $element = array(
       '#theme' => $this->themeFunctions(),
       '#view' => $this->view,
+      '#attached' => &$this->view->element['#attached'],
+      '#cache' => array(
+        'keys' => array('views', 'view', $view_id, $this->view->current_display, $this->view->getCurrentPage()),
+        'tags' => array('view' => array($view_id => $view_id)),
+      ),
+      '#pre_render' => array(array(get_class($this), 'preRender')),
     );
-    $element['#attached'] = &$this->view->element['#attached'];
+
+    return $element;
+  }
+
+  /**
+   * Pre render callback.
+   *
+   * @see self::render()
+   *
+   * @param array $element
+   *
+   * @return array
+   */
+  public static function preRender($element) {
+    $view = $element['#view'];
+    $empty = empty($view->result);
+
+    $element['#rows'] = (!$empty || $view->style_plugin->evenEmpty()) ? $view->style_plugin->render($view->result) : array();
+
+    // Force a render array so CSS/JS can be added.
+    if (!is_array($element['#rows'])) {
+      $element['#rows'] = array('#markup' => $element['#rows']);
+    }
+
+    $element['#header'] = $view->display_handler->renderArea('header', $empty);
+    $element['#footer'] = $view->display_handler->renderArea('footer', $empty);
+    $element['#empty'] = $empty ? $view->display_handler->renderArea('empty', $empty) : array();
+    $element['#exposed'] = !empty($view->exposed_widgets) ? $view->exposed_widgets : array();
+    $element['#more'] = $view->display_handler->renderMoreLink();
+    $element['#feed_icon'] = !empty($view->feed_icon) ? $view->feed_icon : array();
+
+    if ($view->display_handler->renderPager()) {
+      $exposed_input = isset($view->exposed_raw_input) ? $view->exposed_raw_input : NULL;
+      $element['#pager'] = $view->renderPager($exposed_input);
+    }
+
+    if (!empty($view->attachment_before)) {
+      $element['#attachment_before'] = $view->attachment_before;
+    }
+    if (!empty($view->attachment_after)) {
+      $element['#attachment_after'] = $view->attachment_after;
+    }
 
     return $element;
   }
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/display/Feed.php b/core/modules/views/lib/Drupal/views/Plugin/views/display/Feed.php
index ed7a571..7a4c9db 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/display/Feed.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/display/Feed.php
@@ -79,7 +79,7 @@ public function execute() {
 
     $response = $this->view->getResponse();
 
-    $response->setContent($output);
+    $response->setContent(drupal_render($output));
 
     return $response;
   }
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/style/Rss.php b/core/modules/views/lib/Drupal/views/Plugin/views/style/Rss.php
index 0a6f8cb..db26dbb 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/style/Rss.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/style/Rss.php
@@ -41,14 +41,10 @@ public function attachTo($display_id, $path, $title) {
     $url = url($this->view->getUrl(NULL, $path), $url_options);
     if ($display->hasPath()) {
       if (empty($this->preview)) {
-        $build['#attached']['drupal_add_feed'][] = array($url, $title);
-        drupal_render($build);
+        drupal_add_feed($url, $title);
       }
     }
     else {
-      if (empty($this->view->feed_icon)) {
-        $this->view->feed_icon = '';
-      }
       $feed_icon = array(
         '#theme' => 'feed_icon',
         '#url' => $url,
@@ -60,7 +56,7 @@ public function attachTo($display_id, $path, $title) {
         'title' => $title,
         'href' => $url,
       );
-      $this->view->feed_icon .= drupal_render($feed_icon);
+      $this->view->feed_icon = $feed_icon;
     }
   }
 
@@ -141,7 +137,7 @@ public function render() {
       '#rows' => $rows,
     );
     unset($this->view->row_index);
-    return drupal_render($build);
+    return $build;
   }
 
 }
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/style/StylePluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/style/StylePluginBase.php
index 0426e68..108473c 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/style/StylePluginBase.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/style/StylePluginBase.php
@@ -470,9 +470,7 @@ public function renderGroupingSets($sets, $level = 0) {
         if ($this->usesRowPlugin()) {
           foreach ($set['rows'] as $index => $row) {
             $this->view->row_index = $index;
-            $render = $this->view->rowPlugin->render($row);
-            // Row render arrays cannot be contained by style render arrays.
-            $set['rows'][$index] = drupal_render($render);
+            $set['rows'][$index] = $this->view->rowPlugin->render($row);
           }
         }
 
diff --git a/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/style/StyleTest.php b/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/style/StyleTest.php
index 02dd245..93e062c 100644
--- a/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/style/StyleTest.php
+++ b/core/modules/views/tests/modules/views_test_data/lib/Drupal/views_test_data/Plugin/views/style/StyleTest.php
@@ -96,14 +96,14 @@ public function getOutput() {
    * Overrides Drupal\views\Plugin\views\style\StylePluginBase::render()
    */
   public function render() {
-    $output = '';
     if (!$this->usesRowPlugin()) {
       $output = $this->getOutput();
     }
     else {
+      $output = array();
       foreach ($this->view->result as $index => $row) {
         $this->view->row_index = $index;
-        $output .= $this->view->rowPlugin->render($row) . "\n";
+        $output[$index] = $this->view->rowPlugin->render($row) . "\n";
       }
     }
 
diff --git a/core/modules/views/views.module b/core/modules/views/views.module
index 922a8d9..fe97638 100644
--- a/core/modules/views/views.module
+++ b/core/modules/views/views.module
@@ -126,7 +126,21 @@ function views_theme($existing, $type, $theme, $path) {
     // For displays, we pass in a dummy array as the first parameter, since
     // $view is an object but the core contextual_preprocess() function only
     // attaches contextual links when the primary theme argument is an array.
-    'display' => array('view_array' => array(), 'view' => NULL),
+    'display' => array(
+      'view_array' => array(),
+      'view' => NULL,
+      'rows' => array(),
+      'header' => array(),
+      'footer' => array(),
+      'empty' => array(),
+      'exposed' => array(),
+      'more' => array(),
+      'feed_icon' => array(),
+      'pager' => array(),
+      'title' => '',
+      'attachment_before' => array(),
+      'attachment_after' => array(),
+    ),
     'style' => array('view' => NULL, 'options' => NULL, 'rows' => NULL, 'title' => NULL),
     'row' => array('view' => NULL, 'options' => NULL, 'row' => NULL, 'field_alias' => NULL),
     'exposed_form' => array('view' => NULL, 'options' => NULL),
diff --git a/core/modules/views/views.theme.inc b/core/modules/views/views.theme.inc
index eaf3d86..ce24634 100644
--- a/core/modules/views/views.theme.inc
+++ b/core/modules/views/views.theme.inc
@@ -23,15 +23,10 @@
  */
 function template_preprocess_views_view(&$variables) {
   $view = $variables['view'];
+  $id = $view->storage->id();
 
-  $variables['rows'] = (!empty($view->result) || $view->style_plugin->evenEmpty()) ? $view->style_plugin->render($view->result) : array();
-  // Force a render array so CSS/JS can be added.
-  if (!is_array($variables['rows'])) {
-    $variables['rows'] = array('#markup' => $variables['rows']);
-  }
-
-  $variables['css_name'] = drupal_clean_css_identifier($view->storage->id());
-  $variables['id'] = $view->storage->id();
+  $variables['css_name'] = drupal_clean_css_identifier($id);
+  $variables['id'] = $id;
   $variables['display_id'] = $view->current_display;
 
   // Basic classes.
@@ -49,39 +44,6 @@ function template_preprocess_views_view(&$variables) {
     $variables['attributes']['class'][] = $variables['css_class'];
   }
 
-  $empty = empty($view->result);
-  $variables['header'] = $view->display_handler->renderArea('header', $empty);
-  $variables['footer'] = $view->display_handler->renderArea('footer', $empty);
-  $variables['empty'] = $empty ? $view->display_handler->renderArea('empty', $empty) : FALSE;
-
-  $variables['exposed']    = !empty($view->exposed_widgets) ? $view->exposed_widgets : '';
-  $variables['more']       = $view->display_handler->renderMoreLink();
-  $variables['feed_icon']  = !empty($view->feed_icon) ? $view->feed_icon : '';
-
-  $variables['pager']      = '';
-
-  // @todo: Figure out whether this belongs into views_ui_preprocess_views_view.
-  // Render title for the admin preview.
-  $variables['title'] = !empty($view->views_ui_context) ? filter_xss_admin($view->getTitle()) : '';
-
-  if ($view->display_handler->renderPager()) {
-    $exposed_input = isset($view->exposed_raw_input) ? $view->exposed_raw_input : NULL;
-    $variables['pager'] = $view->renderPager($exposed_input);
-  }
-
-  if (!empty($view->attachment_before)) {
-    $variables['attachment_before'] = $view->attachment_before;
-  }
-  else {
-    $variables['attachment_before'] = array();
-  }
-  if (!empty($view->attachment_after)) {
-    $variables['attachment_after'] = $view->attachment_after;
-  }
-  else {
-    $variables['attachment_after'] = array();
-  }
-
   // Add contextual links to the view. We need to attach them to the dummy
   // $view_array variable, since contextual_preprocess() requires that they be
   // attached to an array (not an object) in order to process them. For our
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
index f959d0d..43bf409 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
@@ -566,7 +566,6 @@ public function renderPreview($display_id, $args = array()) {
     if (empty($errors)) {
       $this->ajax = TRUE;
       $this->executable->live_preview = TRUE;
-      $this->views_ui_context = TRUE;
 
       // AJAX happens via HTTP POST but everything expects exposed data to
       // be in GET. Copy stuff but remove ajax-framework specific keys.
diff --git a/core/modules/views_ui/views_ui.module b/core/modules/views_ui/views_ui.module
index 7f140d3..2574bad 100644
--- a/core/modules/views_ui/views_ui.module
+++ b/core/modules/views_ui/views_ui.module
@@ -12,6 +12,7 @@
 use Drupal\views\Analyzer;
 use Drupal\Core\Ajax\AjaxResponse;
 use Drupal\Core\Ajax\ReplaceCommand;
+use Drupal\Component\Utility\Xss;
 
 /**
  * Implements hook_help().
@@ -166,6 +167,12 @@ function views_ui_permission() {
  */
 function views_ui_preprocess_views_view(&$variables) {
   $view = $variables['view'];
+
+  // Render title for the admin preview.
+  if (!empty($view->live_preview)) {
+    $variables['title'] = Xss::filterAdmin($view->getTitle());
+  }
+
   if (!empty($view->live_preview) && \Drupal::moduleHandler()->moduleExists('contextual')) {
     $view->setShowAdminLinks(FALSE);
     foreach (array('title', 'header', 'exposed', 'rows', 'pager', 'more', 'footer', 'empty', 'attachment_after', 'attachment_before') as $section) {
