diff --git a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
index 3db181a..aca6b35 100644
--- a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
@@ -3,6 +3,7 @@
 namespace Drupal\Core\EventSubscriber;
 
 use Drupal\Component\Datetime\DateTimePlus;
+use Drupal\Core\Cache\Cache;
 use Drupal\Core\Cache\CacheableResponseInterface;
 use Drupal\Core\Cache\Context\CacheContextsManager;
 use Drupal\Core\Config\ConfigFactoryInterface;
@@ -227,7 +228,16 @@ protected function setResponseCacheable(Response $response, Request $request) {
       $this->setExpiresNoCache($response);
     }
 
-    $max_age = $this->config->get('cache.page.max_age');
+    if ($this->config->get('cache.page.max_age_provider') == 'dynamic') {
+      $max_age = $response->getCacheableMetadata()->getCacheMaxAge();
+      if ($max_age == Cache::PERMANENT) {
+        // Cache for 30 days.
+        $max_age = 30 * 24 * 60 * 60;
+      }
+    }
+    else {
+      $max_age = $this->config->get('cache.page.max_age');
+    }
     $response->headers->set('Cache-Control', 'public, max-age=' . $max_age);
 
     // In order to support HTTP cache-revalidation, ensure that there is a
diff --git a/core/modules/node/config/optional/views.view.glossary.yml b/core/modules/node/config/optional/views.view.glossary.yml
index 2b4e330..f43643e 100644
--- a/core/modules/node/config/optional/views.view.glossary.yml
+++ b/core/modules/node/config/optional/views.view.glossary.yml
@@ -355,7 +355,7 @@ display:
         - url.query_args
         - 'user.node_grants:view'
         - user.permissions
-      max-age: 0
+      max-age: -1
       tags: {  }
   attachment_1:
     id: attachment_1
diff --git a/core/modules/page_cache/src/StackMiddleware/PageCache.php b/core/modules/page_cache/src/StackMiddleware/PageCache.php
index a4d9053..a820fae 100644
--- a/core/modules/page_cache/src/StackMiddleware/PageCache.php
+++ b/core/modules/page_cache/src/StackMiddleware/PageCache.php
@@ -264,8 +264,19 @@ protected function fetch(Request $request, $type = self::MASTER_REQUEST, $catch
       }
     }
     else {
-      $date = $response->getExpires()->getTimestamp();
-      $expire = ($date > $request_time) ? $date : Cache::PERMANENT;
+      $expires_header = $response->getExpires()->getTimestamp();
+      // First check the expires header, respect that if set to a future date.
+      if ($expires_header > $request_time) {
+        $expire = $expires_header;
+      }
+      else {
+        $max_age = $response->getCacheableMetadata()->getCacheMaxAge();
+        // Fall back to checking the max age, which can either be unlimited, in
+        // which case it should be used as-is, a positive value for a certain
+        // expiration date or 0 if the page is not cacheable. 0 means that
+        // expire is the request time, which means it will not be cached below.
+        $expire = $max_age > Cache::PERMANENT ? $request_time + $max_age : Cache::PERMANENT;
+      }
     }
 
     if ($expire === Cache::PERMANENT || $expire > $request_time) {
diff --git a/core/modules/system/config/install/system.performance.yml b/core/modules/system/config/install/system.performance.yml
index 11392bd..b71e128 100644
--- a/core/modules/system/config/install/system.performance.yml
+++ b/core/modules/system/config/install/system.performance.yml
@@ -1,6 +1,7 @@
 cache:
   page:
     max_age: 0
+    max_age_provider: fixed
 css:
   preprocess: true
   gzip: true
diff --git a/core/modules/system/config/schema/system.schema.yml b/core/modules/system/config/schema/system.schema.yml
index e34d375..f040b68 100644
--- a/core/modules/system/config/schema/system.schema.yml
+++ b/core/modules/system/config/schema/system.schema.yml
@@ -146,6 +146,9 @@ system.performance:
             max_age:
               type: integer
               label: 'Max age'
+            max_age_provider:
+              type: string
+              label: 'Max age provider'
     css:
       type: mapping
       label: 'CSS performance settings'
diff --git a/core/modules/system/src/Form/PerformanceForm.php b/core/modules/system/src/Form/PerformanceForm.php
index d9e0917..e7240a8 100644
--- a/core/modules/system/src/Form/PerformanceForm.php
+++ b/core/modules/system/src/Form/PerformanceForm.php
@@ -118,6 +118,16 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       '#open' => TRUE,
       '#description' => $this->t('Note: Drupal provides an internal page cache module that is recommended for small to medium-sized websites.'),
     );
+    $form['caching']['page_cache_maximum_age_provider'] = array(
+      '#type' => 'select',
+      '#title' => t('Cache period'),
+      '#options' => array(
+        'fixed' => t('Fixed'),
+        'dynamic' => t('Dynamic'),
+      ),
+      '#default_value' => $config->get('cache.page.max_age_provider') ?: 'fixed',
+      '#description' => $this->t('Select how to set max age of page cache. Allowed values are fixed: Fixed number of time (from period field below). Dynamic: Allows page components to decide.'),
+    );
     // Identical options to the ones for block caching.
     // @see \Drupal\Core\Block\BlockBase::buildConfigurationForm()
     $period = array(0, 60, 180, 300, 600, 900, 1800, 2700, 3600, 10800, 21600, 32400, 43200, 86400);
@@ -129,6 +139,11 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       '#default_value' => $config->get('cache.page.max_age'),
       '#options' => $period,
       '#description' => t('The maximum time a page can be cached by browsers and proxies. This is used as the value for max-age in Cache-Control headers.'),
+      '#states' => array(
+        'visible' => array(
+          'select[name="page_cache_maximum_age_provider"]' => array('value' => 'fixed'),
+        ),
+      ),
     );
 
     $directory = 'public://';
@@ -174,6 +189,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
     $this->renderCache->deleteAll();
 
     $this->config('system.performance')
+      ->set('cache.page.max_age_provider', $form_state->getValue('page_cache_maximum_age_provider'))
       ->set('cache.page.max_age', $form_state->getValue('page_cache_maximum_age'))
       ->set('css.preprocess', $form_state->getValue('preprocess_css'))
       ->set('js.preprocess', $form_state->getValue('preprocess_js'))
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 7db1eae..92aee5f 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -1746,3 +1746,12 @@ function system_update_8202() {
 /**
  * @} End of "addtogroup updates-8.2.3".
  */
+
+/**
+ * Set default page cache max-age provider to 'fixed'
+ */
+function system_update_8203() {
+  \Drupal::configFactory()->getEditable('system.performance')
+    ->set('cache.page.max_age_provider', 'fixed')
+    ->save();
+}
diff --git a/core/modules/views/src/Plugin/views/style/Table.php b/core/modules/views/src/Plugin/views/style/Table.php
index c49f6e9..c4e94fc 100644
--- a/core/modules/views/src/Plugin/views/style/Table.php
+++ b/core/modules/views/src/Plugin/views/style/Table.php
@@ -3,6 +3,7 @@
 namespace Drupal\views\Plugin\views\style;
 
 use Drupal\Component\Utility\Html;
+use Drupal\Core\Cache\Cache;
 use Drupal\Core\Cache\CacheableDependencyInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\views\Plugin\views\wizard\WizardInterface;
@@ -425,7 +426,7 @@ public function wizardSubmit(&$form, FormStateInterface $form_state, WizardInter
    * {@inheritdoc}
    */
   public function getCacheMaxAge() {
-    return 0;
+    return Cache::PERMANENT;
   }
 
   /**
