# Cashbusting files to template

**URL:** <https://forum.getkirby.com/t/cashbusting-files-to-template/12809>\
**Category:** Questions\
**Tags:** v3\
**Created:** [February 11, 2019, 10:21am UTC](https://forum.getkirby.com/t/cashbusting-files-to-template/12809 "2019-02-11T10:21:44Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![MSchaffer](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/mschaffer/32/6190_2.png) [@MSchaffer](https://forum.getkirby.com/u/MSchaffer)\
**Post date:** [February 11, 2019, 10:21am UTC](https://forum.getkirby.com/t/cashbusting-files-to-template/12809/1 "2019-02-11T10:21:44Z")

</div>

Hello there,  
I have been coding WordPress themes for the last years and now I am building my first website with Kirby CMS. Looks very promising and I am looking forward to doing a lot more Kirby projects in the future. I have added the yarn/webpack pipeline from the Sage WP theme ([GitHub - roots/sage: WordPress starter theme with Laravel Blade components and templates, Tailwind CSS, and block editor support](https://github.com/roots/sage)), which has integrated cachebusting. Now I am facing the question how I can get the generated hashed versions of JS or CSS files to the website code.

Can anyone give me some support here?

Thanks and best regards from Austria,  
Matthias

---

<div class="post-metadata">

**Author:** ![bvdputte](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/bvdputte/32/8179_2.png) [@bvdputte](https://forum.getkirby.com/u/bvdputte)\
**Post date:** [February 11, 2019, 10:32am UTC](https://forum.getkirby.com/t/cashbusting-files-to-template/12809/2 "2019-02-11T10:32:46Z")

</div>

In Kirby we tend to do the cache busting for CSS/JS in a tooling agnostic manner via plugins who automate this for your via PHP. Then you can safely remove the cache busting part from your development pipeline.

A good start would be to have a look at [https://github.com/bnomei/kirby3-fingerprint](https://github.com/bnomei/kirby3-fingerprint) .

---

<div class="post-metadata">

**Author:** ![MSchaffer](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/mschaffer/32/6190_2.png) [@MSchaffer](https://forum.getkirby.com/u/MSchaffer)\
**Post date:** [February 11, 2019, 1:41pm UTC](https://forum.getkirby.com/t/cashbusting-files-to-template/12809/3 "2019-02-11T13:41:08Z")

</div>

Thanks for your answer - I will try with the plugin!

---

<div class="post-metadata">

**Author:** ![lukaskleinschmidt](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/lukaskleinschmidt/32/13388_2.png) [@lukaskleinschmidt](https://forum.getkirby.com/u/lukaskleinschmidt)\
**Post date:** [February 11, 2019, 5:22pm UTC](https://forum.getkirby.com/t/cashbusting-files-to-template/12809/4 "2019-02-11T17:22:36Z")

</div>

A more lightweight method would be to add a `css` and `js` component in a plugin.  
You can do something like this and use the default `css()` and `js()` helper functions.

This solution will “only” add a query string with the current timestamp of the file. But in most cases this is sufficient. And if you do not user the `@auto` feature you can ditch the complete if statement.

```php
<?php

Kirby::plugin('lukaskleinschmidt/cachebuster', [
    'components' => [
        'css' => function ($kirby, $url, $options) {
            if ($url === '@auto') {
                if (!$url = Url::toTemplateAsset('styles/templates', 'css')) {
                    return null;
                }
            }

            return $url . '?v=' . F::modified($url);
        },
        'js' => function ($kirby, $url, $options) {
            if ($url === '@auto') {
                if (!$url = Url::toTemplateAsset('scripts/templates', 'js')) {
                    return null;
                }
            }

            return $url . '?v=' . F::modified($url);
        }
    ],
]);

```

---

<div class="post-metadata">

**Author:** ![MSchaffer](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/mschaffer/32/6190_2.png) [@MSchaffer](https://forum.getkirby.com/u/MSchaffer)\
**Post date:** [February 11, 2019, 5:36pm UTC](https://forum.getkirby.com/t/cashbusting-files-to-template/12809/5 "2019-02-11T17:36:01Z")

</div>

Thanks for your input, Lukas. That solution looks very clean and nice to me.

---

<div class="post-metadata">

**Author:** ![bnomei](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/bnomei/32/775_2.png) [@bnomei](https://forum.getkirby.com/u/bnomei)\
**Post date:** [February 11, 2019, 7:58pm UTC](https://forum.getkirby.com/t/cashbusting-files-to-template/12809/6 "2019-02-11T19:58:34Z")

</div>

you could also use laravel-mix to generate the assets and use the included manifest file to get proper hashes.

---

<div class="post-metadata">

**Author:** ![bvdputte](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/bvdputte/32/8179_2.png) [@bvdputte](https://forum.getkirby.com/u/bvdputte)\
**Post date:** [February 11, 2019, 7:59pm UTC](https://forum.getkirby.com/t/cashbusting-files-to-template/12809/7 "2019-02-11T19:59:37Z")

</div>

Query strings for cache busting is an anti-pattern as it confuses proxies etc. Adding it to the file name should do the trick.

Imho this should be in core, as it works this way for the assets from the plugins. I’ve added this as enhancement request in github: [https://github.com/getkirby/kirby/issues/1474](https://github.com/getkirby/kirby/issues/1474)

Let’s see what the devs say.

---

<div class="post-metadata">

**Author:** ![MSchaffer](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/mschaffer/32/6190_2.png) [@MSchaffer](https://forum.getkirby.com/u/MSchaffer)\
**Post date:** [February 12, 2019, 6:59am UTC](https://forum.getkirby.com/t/cashbusting-files-to-template/12809/8 "2019-02-12T06:59:26Z")

</div>

Thanks everybody for your support!

---

<div class="post-metadata">

**Author:** ![MSchaffer](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/mschaffer/32/6190_2.png) [@MSchaffer](https://forum.getkirby.com/u/MSchaffer)\
**Post date:** [February 12, 2019, 9:50am UTC](https://forum.getkirby.com/t/cashbusting-files-to-template/12809/9 "2019-02-12T09:50:12Z")

</div>

Hey Lukas,

what do you think about something like this:

```
<?php

/**
 * Get cache-busting hashed filename from assets.json.
 *
 * @param string $filename Original name of the file.
 * @return string Current cache-busting hashed name of the file.
 */
function get_hashed_asset( $filename ) {

  // Cache the decoded manifest so that we only read it in once.
  static $manifest = null;
  if ( null === $manifest ) {
    $manifest_path = kirby::instance()->roots()->assets() . '/assets.json';
    $manifest = file_exists( $manifest_path )
      ? json_decode( file_get_contents( $manifest_path ), true )
      : [];
  }

  // Get rid of asset folder in path to match filename in manifest
  $filename = str_replace('assets/', '', $filename);

  // If the manifest contains the requested file, return the hashed name.
  if ( array_key_exists( $filename, $manifest ) ) {
    $hashed_filename = $manifest[$filename];
    // Add asset folder path to hashed file again
    return 'assets/' . $hashed_filename;
  }

  // Assume the file has not been hashed, when it was not found within the manifest and add asset folder path
  return 'assets/' . $filename;
}

Kirby::plugin('test/cachebusting', [
  'components' => [
    'css' => function ($kirby, $url, $options) {
      return get_hashed_asset($url);
    },
    'js' => function ($kirby, $url, $options) {
      return get_hashed_asset($url);
    }
  ],
]);

```

It works, but for sure it can be improved. It checks, if an json-manifest file exists + simply compares the filenames. If there is a hashed version the filename is adjusted. I appreciate your suggestions or feedback. Thanks!

---

<div class="post-metadata">

**Author:** ![bnomei](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/bnomei/32/775_2.png) [@bnomei](https://forum.getkirby.com/u/bnomei)\
**Post date:** [February 14, 2019, 8:58am UTC](https://forum.getkirby.com/t/cashbusting-files-to-template/12809/10 "2019-02-14T08:58:19Z")

</div>

maybe something like this (untested)

```php
/////////////////////////////////////////
// src/Cachebusting.php
namespace Test;

class Cachebusting {

    static private $manifest = null;

    private static function manifest(): array {
        if(static::$manifest) {
            return static::manifest;
        }

        $m = option('test.cachebusting.manifest');
        if(is_callable($m)) {
            $m = $m();
        }
        $m = array_map(function($a) {
            if(Kirby\Toolkit\F::exists(kirby()->root('assets') . '/' . $a)) {
                return kirby()->url('assets') . '/' . $a;
            }
            return $a;
        }, $m);

        static::$manifest = $m;
        return static::$manifest;
    }

    public static function fingerprint(string $url) {
        return \Kirby\Toolkit\A::get(static::manifest(), $url, $url);
    }
}

/////////////////////////////////////////
// index.php
load([
    'test\\cachebusting' => 'src/Cachebusting.php'
], __DIR__ );

Kirby::plugin('test/cachebusting', [
    'options' => [
        'manifest.file' => 'assets.json',

        // this is an option so you could also just hardcode the array in the config file
        'manifest' => function(): array {
            $path = kirby()->root('assets') . '/' . option('test.cachebusting.manifest.file');
            return \Kirby\Toolkit\F::exists($path) ? \Kirby\Data\Json::read($path) : [];
        }
    ],
    'components' => [
        'css' => function ($kirby, string $url, $options) {
            return \Test\Cachebusting::fingerprint($url);
        },
        'js' => function ($kirby, string $url, $options) {
            return \Test\Cachebusting::fingerprint($url);
        }
    ],
]);

```

---

<div class="post-metadata">

**Author:** ![MSchaffer](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.getkirby.com/mschaffer/32/6190_2.png) [@MSchaffer](https://forum.getkirby.com/u/MSchaffer)\
**Post date:** [February 14, 2019, 6:43pm UTC](https://forum.getkirby.com/t/cashbusting-files-to-template/12809/11 "2019-02-14T18:43:47Z")

</div>

Great, looks a lot better. I will test it soon, thanks a lot!
