How to prevent assets manager from always regenerate already generated assets files ?

Hi,

I use assets manager in order to download public libs from public CDN and minified personnal assets from my website.

To do that I create an initialize method in ControllerBase class, like this :

<?php

// ...

class ControllerBase extends Controller
{
    public function initialize()
    {
        $this->assets->collection('headerCdn')
            ->addCss('//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css', false, false);

        $this->assets->collection('localCss')
            ->setTargetPath('css/style.min.css')
            ->setTargetUri('css/style.min.css')
            ->addCss('css/style.css')
            ->addFilter(new Phalcon\Assets\Filters\Cssmin());

        $this->assets->collection('footerCdn')
            ->addJs('//ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js', false, false)
            ->addJs('//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js', false, false);

        $this->assets->collection('localJs')
            ->setTargetPath('js/script.min.js')
            ->setTargetUri('js/script.min.js')
            ->addJs('js/script.js')
            ->addFilter(new Phalcon\Assets\Filters\Jsmin());
    }

// ...

}

Then rendering methods are called in main index.volt file, like this :

<!DOCTYPE html>
<html>
    <head>
        {# ... #}
        {{ assets.outputCss('headerCdn') }}
        {{ assets.outputCss('localCss') }}
        {# ... #}
    </head>
    <body>
        {# ... #}
        {{ assets.outputJs('footerCdn') }}
        {{ assets.outputJs('localJs') }}
    </body>
</html>

Now, while reloading the page, I note that script.min.js and style.min.css modification dates are always the same than the date when I reload my page (same date and same hour). I deduce that minified files are generated each time an HTTP call is performed and a page is rendered.

The ideal for me would be that the assets generation is performed only once and that the generated minified files are not overridden as long as they exist.

How could we do that ?



2.8k
edited Oct '17

So far I managed to avoid continuous minified files generation thanks to previously deployed view cache. Here is a solution :

1) I use a view cache that I initialize in my services.php file. For example :

<?php

// ...
use Phalcon\Cache\Backend\Factory;

//...

$di->set('viewCache', function() {
    $config = $this->getConfig();

    return Factory::load([
        'frontend' => [
            'lifetime' => $config->cache->view->lifetime,
            'adapter' => 'output',
        ],
        'adapter' => $config->cache->view->enabled ? 'libmemcached' : 'memory',
        'servers' => $config->cache->memcached->servers->toArray(),
    ]);
});

In this example I use libmemcached as a backend to store view fragments.

2) I move assets building from ControllerBase::initialize() method to the services.php file. Here is my service :

<? php

//...

$di->setShared('assets', function() {
    $manager = new Phalcon\Assets\Manager();

    $manager->collection('headerCdn')
        ->addCss('//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css', false, false);

    $manager->collection('localCss')
        ->setTargetPath('css/style.min.css')
        ->setTargetUri('css/style.min.css')
        ->addCss('css/style.css')
        ->addFilter(new Phalcon\Assets\Filters\Cssmin());

    $manager->collection('footerCdn')
        ->addJs('//ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js', false, false)
        ->addJs('//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js', false, false);

    $manager->collection('localJs')
        ->setTargetPath('js/script.min.js')
        ->setTargetUri('js/script.min.js')
        ->addJs('js/script.js')
        ->addFilter(new Phalcon\Assets\Filters\Jsmin());

    return $manager;
});

ControllerBase::initialize() is removed.

3) I use the Volt cache directive in main index.volt, to store assets declaration HTML fragments in the view cache, so the assets.outputCss() and assets.outputJs() won't be ran anymore, at least as long as cache is valid :

<!DOCTYPE html>
<html>
    <head>
        {# ... #}
        {% cache 'headerAssets' %}
        {{ assets.outputCss('headerCdn') }}
        {{ assets.outputCss('localCss') }}
        {% endcache %}
        {# ... #}
    </head>
    <body>
        {# ... #}
        {% cache 'footerAssets' %}
        {{ assets.outputJs('footerCdn') }}
        {{ assets.outputJs('localJs') }}
        {% endcache %}
    </body>
</html>

So far, thanks to custom assets service and view cache service, minified assets files are generated once per cache validity duration (24h in my case).

But I still wonder if there is a way to not continuously generate minified files each time a view is rendered by only using assets management methods.



6.2k

In my personal opinion, in big projects, minifying js and css should not be part of the framework but frontend deployment. I use separated config files for assets divided by environment, so in local we use single css files, and in stage and production we put the minified and merged version.



2.8k

My project is not very big, I have only one CSS and one JS, so far it has been more easy to have only one procedure for back and front deployment, that's why I use the built-in phalcon tool