 jsonapi_extras.services.yml              |  7 +++
 src/EventSubscriber/ConfigSubscriber.php | 98 ++++++++++++++++++++++++++++++++
 src/JsonapiExtrasServiceProvider.php     |  5 ++
 src/Normalizer/EntityNormalizerTrait.php |  3 -
 4 files changed, 110 insertions(+), 3 deletions(-)

diff --git a/jsonapi_extras.services.yml b/jsonapi_extras.services.yml
index 627c7a2..0f8936a 100644
--- a/jsonapi_extras.services.yml
+++ b/jsonapi_extras.services.yml
@@ -22,3 +22,10 @@ services:
   plugin.manager.resource_field_enhancer:
     class: Drupal\jsonapi_extras\Plugin\ResourceFieldEnhancerManager
     parent: default_plugin_manager
+
+  # Event subscribers.
+  jsonapi_extras.config_subscriber:
+    class: Drupal\jsonapi_extras\EventSubscriber\ConfigSubscriber
+    arguments: ['@kernel', '@router.builder']
+    tags:
+      - { name: event_subscriber }
diff --git a/src/EventSubscriber/ConfigSubscriber.php b/src/EventSubscriber/ConfigSubscriber.php
index e69de29..d36e80a 100644
--- a/src/EventSubscriber/ConfigSubscriber.php
+++ b/src/EventSubscriber/ConfigSubscriber.php
@@ -0,0 +1,98 @@
+<?php
+
+namespace Drupal\jsonapi_extras\EventSubscriber;
+
+use Drupal\Core\Cache\CacheableResponseInterface;
+use Drupal\Core\Config\ConfigCrudEvent;
+use Drupal\Core\Config\ConfigEvents;
+use Drupal\Core\DrupalKernelInterface;
+use Drupal\Core\Routing\RouteBuilderInterface;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
+use Symfony\Component\HttpKernel\KernelEvents;
+
+/**
+ * Associates config cache tag and rebuilds container + routes when necessary.
+ */
+class ConfigSubscriber implements EventSubscriberInterface {
+
+  /**
+   * The Drupal kernel.
+   *
+   * @var \Drupal\Core\DrupalKernelInterface
+   */
+  protected $drupalKernel;
+
+  /**
+   * The route building service.
+   *
+   * @var \Drupal\Core\Routing\RouteBuilderInterface
+   */
+  protected $routeBuilder;
+
+  /**
+   * Constructs a ConfigSubscriber object.
+   *
+   * @param \Drupal\Core\DrupalKernelInterface $drupal_kernel
+   *   The Drupal kernel.
+   * @param \Drupal\Core\Routing\RouteBuilderInterface $route_builder
+   *   The route building service.
+   */
+  public function __construct(DrupalKernelInterface $drupal_kernel, RouteBuilderInterface $route_builder) {
+    $this->drupalKernel = $drupal_kernel;
+    $this->routeBuilder = $route_builder;
+  }
+
+  /**
+   * Rebuilds container and routes  when 'path_prefix' configuration is changed.
+   *
+   * @param \Drupal\Core\Config\ConfigCrudEvent $event
+   *   The Event to process.
+   */
+  public function onSave(ConfigCrudEvent $event) {
+    if ($event->getConfig()->getName() === 'jsonapi_extras.settings') {
+      // @see \Drupal\jsonapi_extras\JsonapiExtrasServiceProvider::alter()
+      if ($event->isChanged('path_prefix')) {
+        $this->drupalKernel->rebuildContainer();
+        $container = \Drupal::getContainer();
+        // Because \Drupal\jsonapi\Routing\Routes::routes() uses a container
+        // parameter, we need to ensure that it uses the freshly rebuilt
+        // container. Due to that, it's impossible to use an injected route
+        // builder service, at least until core updates it to support
+        // \Drupal\Core\DrupalKernelInterface::CONTAINER_INITIALIZE_SUBREQUEST_FINISHED
+        $this->service = $container->get('router.builder');
+        $container->get('router.builder')->rebuild();
+      }
+    }
+  }
+
+  /**
+   * Associates JSON API Extras' config cache tag with all JSON API responses.
+   * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
+   */
+  public function onResponse(FilterResponseEvent $event) {
+    if ($event->getRequest()->getRequestFormat() !== 'api_json') {
+      return;
+    }
+
+    $response = $event->getResponse();
+    if (!$response instanceof CacheableResponseInterface) {
+      return;
+    }
+
+    $response->getCacheableMetadata()
+      ->addCacheTags(['config:jsonapi_extras.settings']);
+  }
+
+    /**
+   * {@inheritdoc}
+   */
+  public static function getSubscribedEvents() {
+    $events[ConfigEvents::SAVE][] = ['onSave'];
+    // Run before \Drupal\jsonapi\EventSubscriber\ResourceResponseSubscriber::onResponse()
+    // (priority 128), so we can add JSON API's config cache tag.
+    $events[KernelEvents::RESPONSE][] = ['onResponse', 150];
+    return $events;
+  }
+
+}
diff --git a/src/JsonapiExtrasServiceProvider.php b/src/JsonapiExtrasServiceProvider.php
index 7ca2ffe..f6e0527 100644
--- a/src/JsonapiExtrasServiceProvider.php
+++ b/src/JsonapiExtrasServiceProvider.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\jsonapi_extras;
 
+use Drupal\Core\Config\BootstrapConfigStorageFactory;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\DependencyInjection\ServiceProviderBase;
 use Drupal\jsonapi_extras\ResourceType\ConfigurableResourceTypeRepository;
@@ -26,6 +27,10 @@ class JsonapiExtrasServiceProvider extends ServiceProviderBase {
       $definition->addArgument(new Reference('plugin.manager.resource_field_enhancer'));
       $definition->addArgument(new Reference('config.factory'));
     }
+
+    $settings = BootstrapConfigStorageFactory::get()
+      ->read('jsonapi_extras.settings');
+    $container->setParameter('jsonapi.base_path', '/' . $settings['path_prefix']);
   }
 
   /**
diff --git a/src/Normalizer/EntityNormalizerTrait.php b/src/Normalizer/EntityNormalizerTrait.php
index 15821f6..1187964 100644
--- a/src/Normalizer/EntityNormalizerTrait.php
+++ b/src/Normalizer/EntityNormalizerTrait.php
@@ -81,9 +81,6 @@ trait EntityNormalizerTrait {
         $resource_config
       );
     }
-    $context['cacheable_metadata']->addCacheableDependency(
-      \Drupal::config('jsonapi_extras.settings')
-    );
 
     return $output;
   }
