How do I get an uploaded image URL or the default for use in a template (code improvement) I have a working preprocess function that allows me to grab an image for use as a background in the page template from a node if the field exists.  It falls back on a default image if supplied, the function looks like this:

&lt;?php
/**
 * Implements hook_preprocess_page() for page.html.twig.
 */
function mymodule_preprocess_page(array &amp;$vars) {

  // Preprocess the hero image if it exists (it should on all nodes).
  if (isset($vars['node']-&gt;field_hero)){
    $field_hero = $vars['node']-&gt;get('field_hero')-&gt;getValue();

    // If a file has been uploaded, get it.
    if (!empty($field_hero)){
      $hero_id = $field_hero[0]['target_id'];
      $file = File::load($hero_id);

    // Otherwise get the default if there is one.
    } else {
      $default_image = $vars['node']-&gt;getFields()['field_hero']-&gt;getFieldDefinition()-&gt;getSetting('default_image');
      $file = Drupal::service('entity.repository')-&gt;loadEntityByUuid('file', $default_image['uuid']);
    }

    // If a file has been found (there might not be a default), get its path.
    if ($file){
      $path = $file-&gt;getFileUri();
      $vars['hero'] = ImageStyle::load('hero_image')-&gt;buildUrl($path);
    }
  }

}


Finding the default file is a convoluted mess of steps that requires loading all of the fields... there has got to be a better way to do this.  Is there?
You don't need to load all the fields, you can just load the image field:

$uuid = $vars['node']-&gt;get('field_hero')-&gt;getFieldDefinition()-&gt;getSetting('default_image')['uuid'];
$file = \Drupal::service('entity.manager')-&gt;loadEntityByUuid('file', $uuid);


On a different note, the first line of your code assumes that $vars['node'] exists, which it won't on non-node pages, so you should change it to:

if (isset($vars['node'], $vars['node']-&gt;field_hero))