 config/install/jsonapi.settings.yml |  4 ++++
 config/schema/jsonapi.schema.yml    |  7 +++++++
 jsonapi.install                     | 35 +++++++++++++++++++++++++++++++
 jsonapi.module                      | 11 +++++-----
 tests/src/Functional/FileTest.php   | 41 +++++++++++++++++++++++++++++++++++--
 5 files changed, 91 insertions(+), 7 deletions(-)

diff --git a/config/install/jsonapi.settings.yml b/config/install/jsonapi.settings.yml
new file mode 100644
index 0000000..2b8c70a
--- /dev/null
+++ b/config/install/jsonapi.settings.yml
@@ -0,0 +1,4 @@
+# Before Drupal 8.5, the File entity type did not expose the file URL as a
+# computed property on the 'uri' base field. Sites built with JSON API
+# before Drupal 8.5 will have JSON API's added computed field.
+bc_file_download_url: false
diff --git a/config/schema/jsonapi.schema.yml b/config/schema/jsonapi.schema.yml
new file mode 100644
index 0000000..3bee798
--- /dev/null
+++ b/config/schema/jsonapi.schema.yml
@@ -0,0 +1,7 @@
+jsonapi.settings:
+  type: config_object
+  label: 'JSON API settings'
+  mapping:
+    bc_file_download_url:
+      type: boolean
+      label: 'Whether to retain the JSON API work-around for the missing file URL field on File entities before Drupal 8.5.'
diff --git a/jsonapi.install b/jsonapi.install
new file mode 100644
index 0000000..4e5ddf0
--- /dev/null
+++ b/jsonapi.install
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * @file
+ * Update functions for the JSON API module.
+ */
+
+/**
+ * Implements hook_install().
+ */
+function jsonapi_install() {
+  // For new sites, also still enable JSON API's custom base field, if it's a
+  // new site starting on Drupal <8.5. Because only in Drupal >=8.5, core ships
+  // with an alternative.
+  // @todo Remove this when JSON API requires Drupal 8.5.
+  if (floatval(\Drupal::VERSION) < 8.5) {
+    $config_factory = \Drupal::configFactory();
+    $config_factory->getEditable('jsonapi.settings')
+      ->set('bc_file_download_url', TRUE)
+      ->save(TRUE);
+  }
+}
+
+/**
+ * Add jsonapi.settings::bc_file_download_url configuration.
+ *
+ * All existing JSON API sites are using JSON API's custom base field, so enable
+ * the BC layer for them.
+ */
+function jsonapi_update_8101() {
+  $config_factory = \Drupal::configFactory();
+  $config_factory->getEditable('jsonapi.settings')
+    ->set('bc_file_download_url', TRUE)
+    ->save(TRUE);
+}
diff --git a/jsonapi.module b/jsonapi.module
index 997d981..613cb15 100644
--- a/jsonapi.module
+++ b/jsonapi.module
@@ -33,13 +33,14 @@ function jsonapi_help($route_name, RouteMatchInterface $route_match) {
 /**
  * Implements hook_entity_base_field_info().
  *
- * @todo This should probably live in core, but for now we will keep it as a
- * temporary solution. There are similar unresolved efforts already happening
- * there.
- *
- * @see https://www.drupal.org/node/2825487
+ * @todo Remove this when JSON API requires Drupal 8.5 or newer.
  */
 function jsonapi_entity_base_field_info(EntityTypeInterface $entity_type) {
+  $jsonapi_settings = \Drupal::config('jsonapi.settings');
+  if ($jsonapi_settings->get('bc_file_download_url') !== TRUE) {
+    return;
+  }
+
   $fields = [];
   if ($entity_type->id() == 'file') {
     $fields['url'] = BaseFieldDefinition::create('string')
diff --git a/tests/src/Functional/FileTest.php b/tests/src/Functional/FileTest.php
index 3266f1d..a437833 100644
--- a/tests/src/Functional/FileTest.php
+++ b/tests/src/Functional/FileTest.php
@@ -2,10 +2,14 @@
 
 namespace Drupal\Tests\jsonapi\Functional;
 
+use Drupal\Component\Serialization\Json;
+use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Cache\Cache;
 use Drupal\Core\Url;
 use Drupal\file\Entity\File;
 use Drupal\Tests\rest\Functional\BcTimestampNormalizerUnixTestTrait;
 use Drupal\user\Entity\User;
+use GuzzleHttp\RequestOptions;
 
 /**
  * JSON API integration test for the "File" content entity type.
@@ -141,8 +145,6 @@ class FileTest extends ResourceTestBase {
           'filesize' => (int) $this->entity->getSize(),
           'langcode' => 'en',
           'status' => TRUE,
-          // @todo Decide what to do with this in https://www.drupal.org/project/jsonapi/issues/2926463
-          'url' => base_path() . $this->siteDirectory . '/files/drupal.txt',
           'uri' => [
             'url' => base_path() . $this->siteDirectory . '/files/drupal.txt',
             'value' => 'public://drupal.txt',
@@ -167,6 +169,9 @@ class FileTest extends ResourceTestBase {
     if (floatval(\Drupal::VERSION) < 8.5) {
       $normalization['data']['attributes']['uri'] = $normalization['data']['attributes']['uri']['url'];
     }
+    if ($this->config('jsonapi.settings')->get('bc_file_download_url') == TRUE) {
+      $normalization['data']['attributes']['url'] = base_path() . $this->siteDirectory . '/files/drupal.txt';
+    }
     return $normalization;
 
   }
@@ -226,4 +231,36 @@ class FileTest extends ResourceTestBase {
     return parent::testGetIndividual();
   }
 
+  /**
+   * Tests the BC layer for the pre-8.5 JSON API work-around for File entities.
+   */
+  public function testGetIndividualBc() {
+    if (floatval(\Drupal::VERSION) < 8.5) {
+      $this->markTestSkipped('The "url" property on the "uri" field on File entities is only available for normalization in Drupal 8.5 and later.');
+      return;
+    }
+
+    // Enable the BC layer.
+    // @see jsonapi_entity_base_field_info()
+    $config_factory = \Drupal::configFactory();
+    $config_factory->getEditable('jsonapi.settings')
+      ->set('bc_file_download_url', TRUE)
+      ->save(TRUE);
+    Cache::invalidateTags(['entity_field_info']);
+
+    // @todo Remove line below in favor of commented line in https://www.drupal.org/project/jsonapi/issues/2878463.
+    $url = Url::fromRoute(sprintf('jsonapi.file--file.individual', static::$resourceTypeName), [static::$entityTypeId => $this->entity->uuid()]);
+    /* $url = $this->entity->toUrl('jsonapi'); */
+    $request_options = [];
+    $request_options[RequestOptions::HEADERS]['Accept'] = 'application/vnd.api+json';
+    $request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions());
+    $this->setUpAuthorization('GET');
+    $response = $this->request('GET', $url, $request_options);
+    $expected = $this->getExpectedDocument();
+    static::recursiveKSort($expected);
+    $actual = Json::decode((string) $response->getBody());
+    static::recursiveKSort($actual);
+    $this->assertSame($expected, $actual);
+  }
+
 }
