diff --git a/core/modules/views/src/Ajax/ViewAjaxResponse.php b/core/modules/views/src/Ajax/ViewAjaxResponse.php
index d19180044ffe3f7395ddc7045e823f7eeba8cf22..15a5774976c68cc301aecdaef4f69af40cd4bedd 100644
--- a/core/modules/views/src/Ajax/ViewAjaxResponse.php
+++ b/core/modules/views/src/Ajax/ViewAjaxResponse.php
@@ -2,7 +2,7 @@
 
 namespace Drupal\views\Ajax;
 
-use Drupal\Core\Ajax\AjaxResponse;
+use Drupal\Core\Cache\CacheableAjaxResponse;
 use Drupal\views\ViewExecutable;
 
 /**
@@ -10,7 +10,7 @@
  *
  * We use a special response object to be able to fire a proper alter hook.
  */
-class ViewAjaxResponse extends AjaxResponse {
+class ViewAjaxResponse extends CacheableAjaxResponse {
 
   /**
    * The view executed on this ajax request.
diff --git a/core/modules/views/src/Controller/ViewAjaxController.php b/core/modules/views/src/Controller/ViewAjaxController.php
index a4a3d2538dc25c61cd7e971e51b8f4e345caf856..f970b334c559231004e008f362716968a278eef4 100644
--- a/core/modules/views/src/Controller/ViewAjaxController.php
+++ b/core/modules/views/src/Controller/ViewAjaxController.php
@@ -6,6 +6,7 @@
 use Drupal\Component\Utility\UrlHelper;
 use Drupal\Core\Ajax\PrependCommand;
 use Drupal\Core\Ajax\ReplaceCommand;
+use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
@@ -218,6 +219,8 @@ public function ajaxView(Request $request) {
           $response->setAttachments($preview['#attached']);
         }
 
+        $response->addCacheableDependency(CacheableMetadata::createFromRenderArray($preview));
+
         return $response;
       }
       else {
diff --git a/core/modules/views/tests/src/Functional/ViewAjaxTest.php b/core/modules/views/tests/src/Functional/ViewAjaxTest.php
index 6c2e3ead5c03bdd5c83c24e33d83437ec592d182..12129e4815b8a71c7e743740df4c4fbb85a80241 100644
--- a/core/modules/views/tests/src/Functional/ViewAjaxTest.php
+++ b/core/modules/views/tests/src/Functional/ViewAjaxTest.php
@@ -66,4 +66,24 @@ public function testNonAjaxViewViaAjax(): void {
     $this->assertEquals(403, $response->getStatusCode());
   }
 
+  /**
+   * Tests that an ajax view response is cacheable.
+   */
+  public function testAjaxViewCache(): void {
+    $this->drupalGet('views/ajax', [
+      'query' => [
+        'view_name' => 'test_ajax_view',
+        'view_display_id' => 'page_1',
+      ],
+    ]);
+
+    $this->assertSession()->statusCodeEquals(200);
+    $this->assertSession()
+      ->responseHeaderEquals('X-Drupal-Cache-Tags', 'config:user.role.anonymous config:views.view.test_ajax_view http_response');
+    $this->assertSession()
+      ->responseHeaderEquals('X-Drupal-Cache-Contexts', 'languages:language_interface route theme url.query_args user.permissions');
+    $this->assertSession()
+      ->responseHeaderEquals('X-Drupal-Cache-Max-Age', '-1 (Permanent)');
+  }
+
 }
diff --git a/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php b/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php
index 75b22bd86a84ecc43a551dc68f9e1fb771b4d5a0..2fc9c27a1c3d42d7eec867158b8c6c9f475b61fb 100644
--- a/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php
+++ b/core/modules/views/tests/src/Unit/Controller/ViewAjaxControllerTest.php
@@ -4,6 +4,7 @@
 
 namespace Drupal\Tests\views\Unit\Controller;
 
+use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Render\RenderContext;
 use Drupal\Core\Render\Renderer;
 use Drupal\Core\Utility\CallableResolver;
@@ -365,6 +366,8 @@ public function testAjaxViewWithPager(): void {
     $this->assertEquals('.js-view-dom-id-' . $dom_id, $commands[0]['selector']);
 
     $this->assertViewResultCommand($response, 1);
+
+    $this->assertInstanceOf(CacheableMetadata::class, $response->getCacheableMetadata());
   }
 
   /**