Minified and Cachebusted JS Helper output

How hard would it be to get the js helper auto loaded javascript output to use a minified file extension (.min.js) and also work with Bastians’ cache buster plugin?

Right now, only the plain JS helper works with the cachebuster.

I would like the helper to use minified file extensions if a config variable is set to true. That way, it can be set in a config for the live domain whilst the local config does not use minified files.

Any ideas?

1 Like

I have created an Issue some days ago regarding this.

  1. Add an option. Something like this: c::set('auto.js.filename', '{name}.js.gz');
  2. Add a extra parameter to the helper function
  3. Some extra syntax in the @auto string. js('@auto:{name}.js.gz'); (kinda ugly)
  4. Or perhaps the option to add a ending like js('@auto.js.gz'); or only js('@auto.gz');

Awesome… that would do it :slight_smile: If only I knew PHP… :frowning:

I could provide a PR for this. I like the first option the most but everything has its pros and cons.
But actually I’m not sure if this is something that would get into the core. @lukasbestle @bastianallgeier?

An alternative could be a custom JS component…

Actually you can easily extend the component.
This implements the first approach.

You can set auto.js.filename to match your files.

 c::set('auto.js.filename', '{name}.js'); // default
 c::set('auto.js.filename', '{name}.js.gz');
 c::set('auto.js.filename', '{name}.min.js');

Good work! :slight_smile:

Sorry to dig this one up again, but using the component written by @lukaskleinschmidt doesnt work with @bastianallgeier Cachebuster plugin.

How can I get this work?

You can modify following lines of code.

    // auto template css files
    if($src == '@auto') {
      
      $filename = c::get('auto.js.filename', '{name}.js');
      $template = $this->kirby->site()->page()->template();
      $filename = str::template($filename, array('name' => $template));
      $filename = str::template($filename, array('modified' => f::modified($file)));
      
      $file = str::template($filename, array('name' => $template));
      $root = $this->kirby->roots()->autojs() . DS . $file;
      $src  = $this->kirby->urls()->autojs() . '/' . $file;

      if(!file_exists($root)) return false;

    }

You can then use c::set('auto.js.filename', '{name}.min.{modified}.js') so the filename matches the .htaccess rules.

Edit:
I updated the gist to match the latest changes of the js helper function.

Sorry to resurrect this one, but i think it no longer works with the latest Kirby (2.5.8).

I get a whoops on line 42 of the js-component.php plugin

$filename = str::template($filename, array('modified' => f::modified($file)));

The error is:

Class 'LukasKleinschmidt\Component\f' not found

@lukaskleinschmidt Any chance you could patch it up for current Kirby. I am using your version of the cachebuster plugin that does not require changing .htacess. I get the same error with Bastians original CacheBuster.

Add use F at the top of the file, where it say use HTML etc.

Duh. Of course. I added that, however, I get a new whoops now on the same line

Undefined variable: file

$file is set inside the cachebuster plugin. It’s as if its not being passed through to the js-component.php.

Is this a load order issue? Both these plugins extend \Kirby\Component\JS. How does it decide which one to run first, or does that even matter? It’s odd because it works fine with slightly earlier versions of Kirby. I think 2.5.4 was the last version I used it with.

Would surprise me if that worked before if the variable is not defined. You have to define $file in the plugin before you can use it.

And since both component extends the original Kirby component, the function of the class that is loaded last overwrites the other. You can see which version is used by dumping:

dump(kirby::instance()->component('js'));

Since you get the error message, that will be the Lukas Kleinschmitt one. Maybe you didn’t use @auto JS when it worked?

Hmm strange. Perhaps it was a slightly earlier version of the gist i had working, cant remember.

According to the dump, its using the LukasKleinschmidt\Component\JS Object which is the js-component.php plugin from the Gist.

So I guess from what your saying then the two need to be merged? Modify the Cachebuster plugin to include the functionality from the Gist.

All i really need is the cachebuster to work with auto loaded js, which it currently doesnt.

I’m not quite sure what @lukaskleinschmidt is trying to do there with the auto loaded files, somehow it’s going round in circles.

I think if you don’t need the c::get part, you can replace the if auto statement like this:

    // auto template css files
    if($src == '@auto') {
      $template = $this->kirby->site()->page()->template();
      $file =  $template . '.js';
      $root = $this->kirby->roots()->autojs() . DS . $file;
      if(file_exists($root)) {
        $mod = f::modified($root);
        $src  = $this->kirby->urls()->autojs() . '/' . $template . '.' . $mod . '.js';
      } else {
        return false;
      }
    }

ooo! so close… except its reversed things. Now only the auto-loaded file is cachebusted and the other files are not. I think its time for bed. I’ll come back to it with fresh eyes tomorrow. Thank you @texnixe so far.

p.s i think you are using Bastians cachebuster rather then this one

No, of course not, I was using @lukaskleinschmidt plugin, not the cachebuster. This is not surprising, since that code does not handle non auto files::

<?php
namespace LukasKleinschmidt\Component;
use HTML;
use STR;
use C;
use F;
/**
 * Kirby Script Tag Component
 *
 * @package   Kirby CMS
 * @author    Bastian Allgeier <bastian@getkirby.com>
 * @link      http://getkirby.com
 * @copyright Bastian Allgeier
 * @license   http://getkirby.com/license
 */
class JS extends \Kirby\Component\JS {
  /**
   * Builds the html script tag for the given javascript file
   *
   * @param string $src
   * @param boolean async
   * @return string
   */
  public function tag($src, $async = false) {
    if(is_array($src)) {
      $js = array();
      foreach($src as $s) $js[] = $this->tag($s, $async);
      return implode(PHP_EOL, $js) . PHP_EOL;
    }
    // auto template css files
    // auto template css files
    if($src == '@auto') {
      $template = $this->kirby->site()->page()->template();
      $file =  $template . '.js';
      $root = $this->kirby->roots()->autojs() . DS . $file;
      if(file_exists($root)) {
        $mod = f::modified($root);
        $src  = $this->kirby->urls()->autojs() . '/' . $template . '.' . $mod . '.js';
      } else {
        return false;
      }
    } else {
      $file = kirby()->roots()->index() . DS . $src;

      if(file_exists($file)) {
        $mod = f::modified($file);
        $src = dirname($src) . '/' . f::name($src) . '.' . $mod . '.js';
      }
    }

    // build the array of HTML attributes
    $attr = array('src' => url($src));
    if(is_array($async)) {
      $attr = array_merge($attr, $async);
    } else if($async === true) {
      $attr['async'] = true;
    }
    return html::tag('script', '', $attr);
  }
}
$kirby->set('component', 'js', __NAMESPACE__ . '\\JS');

@texnixe Of course, it cancels the plugin out. Sorry, it’s late, my brain is dead. I thought you were using it becuase of the way filename was constructed, because @lukaskleinschmidt CacheBuster uses a query string to avoid .htaccess edits, whereas Bastians modified the filename.

Your amended version works great, thank you so much.

I tweaked the output slightly to use a query string instead of modifying the filename:

<?php
namespace LukasKleinschmidt\Component;

use HTML;
use STR;
use C;
use F;

/**
 * Kirby Script Tag Component
 *
 * @package   Kirby CMS
 * @author    Bastian Allgeier <bastian@getkirby.com>
 * @link      http://getkirby.com
 * @copyright Bastian Allgeier
 * @license   http://getkirby.com/license
 */
class JS extends \Kirby\Component\JS
{
    /**
     * Builds the html script tag for the given javascript file
     *
     * @param string $src
     * @param boolean async
     * @return string
     */
    public function tag($src, $async = false)
    {
        if (is_array($src)) {
            $js = array();
            foreach ($src as $s) {
                $js[] = $this->tag($s, $async);
            }
            return implode(PHP_EOL, $js) . PHP_EOL;
        }

        // auto template css files
        if ($src == '@auto') {
            $template = $this->kirby->site()->page()->template();
            $file =  $template . '.js';
            $root = $this->kirby->roots()->autojs() . DS . $file;
            if (file_exists($root)) {
                $mod = f::modified($root);
                $src  = $this->kirby->urls()->autojs() . '/' . $template . '.js' . '?v=' . $mod;
            } else {
                return false;
            }
        } else {
            $file = kirby()->roots()->index() . DS . $src;

            if (file_exists($file)) {
                $mod = f::modified($file);
                $src = dirname($src) . '/' . f::filename($src) . '?v=' . $mod;
            }
        }

        // build the array of HTML attributes
        $attr = array('src' => url($src));
        if (is_array($async)) {
            $attr = array_merge($attr, $async);
        } elseif ($async === true) {
            $attr['async'] = true;
        }
        return html::tag('script', '', $attr);
    }
}
$kirby->set('component', 'js', __NAMESPACE__ . '\\JS');