Which implementation is better for custom breadcrumb and why? As per answers received here, we can implement custom breadcrumb either via module or via HOOK_preprocess_breadcrumb.

Via module:

In custom_breadcrumb.module file

&lt;?php

namespace Drupal\custom_breadcrumb;

use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
use Drupal\Core\Link;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\node\NodeInterface;

/**
 * Class Breadcrumbs.
 *
 * @package Drupal\custom_breadcrumb
 */
class Breadcrumbs implements BreadcrumbBuilderInterface {
  use StringTranslationTrait;

  /**
   * {@inheritDoc}
   */
  public function applies(RouteMatchInterface $route_match) {
    return $route_match-&gt;getRouteName() == 'entity.node.canonical' &amp;&amp; $route_match-&gt;getParameter('node') instanceof NodeInterface;
  }

  /**
   * {@inheritDoc}
   */
  public function build(RouteMatchInterface $route_match) {
    $node = $route_match-&gt;getParameter('node');
    $breadcrumb = new Breadcrumb();

    // By setting a "cache context" to the "url", each requested URL gets it's
    // own cache. This way a single breadcrumb isn't cached for all pages on the
    // site.
    $breadcrumb-&gt;addCacheContexts(["url"]);

    // By adding "cache tags" for this specific node, the cache is invalidated
    // when the node is edited.
    $breadcrumb-&gt;addCacheTags(["node:{$node-&gt;nid-&gt;value}"]);

    // Add "Home" breadcrumb link.
    $breadcrumb-&gt;addLink(Link::createFromRoute($this-&gt;t('Home'), '&lt;front&gt;'));

    // Given we have a taxonomy term reference field named "field_tags" and that
    // field has data, add that term as a breadcrumb link.
    if (!empty($node-&gt;field_tags-&gt;entity)) {
      $breadcrumb-&gt;addLink($node-&gt;field_tags-&gt;entity-&gt;toLink());
    }
    return $breadcrumb;
  }

}


and then in custom_breadcrumb.services.yml

services:
  custom_breadcrumb.breadcrumbs:
    class: Drupal\custom_breadcrumb\Breadcrumbs
    tags:
      - { name: breadcrumb_builder, priority: 100 }


Via HOOK_preprocess_breadcrumb, as mentioned in the answer here

Both the ways are achievable, but the question is which one should be followed and why as a best practice?
When you build a module which for example provides a new content or entity type you can include a breadcrumb builder, because you might have data fields that the standard breadcrumb builder doesn't know of and you want to process them in your breadcrumbs. An example for this would be  Drupal\book\BookBreadcrumbBuilder from the core book module.

When you build a theme and want to modify the breadcrumbs already built by the installed core, contrib and custom modules you use a theme based solution in a preprocess hook.

So best practice depends on which level you are working on. Not a good idea would be in this example if the book module would use a preprocess hook.