8000 Added "How to Use a Custom Version Strategy for Assets" by javiereguiluz · Pull Request #7141 · symfony/symfony-docs · GitHub
[go: up one dir, main page]

Skip to content

Added "How to Use a Custom Version Strategy for Assets" #7141

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Dec 12, 2016
Next Next commit
Cookbook entry: Asset - Custom Version Strategy
  • Loading branch information
teohhanhui authored and javiereguiluz committed Nov 15, 2016
commit 4f530d8e52b69c215014ece39ebeeda973e16881
254 changes: 254 additions & 0 deletions cookbook/asset/custom_version_strategy.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
.. index::
single: Asset; Custom Version Strategy

How to Use a Custom Version Strategy for Assets
===============================================

.. versionadded:: 2.7
The Asset component was introduced in Symfony 2.7.

Symfony by default does not perform asset versioning. You can specify the
:ref:`version <reference-framework-assets-version>` and
:ref:`version_format <reference-framework-assets-version-format>` configuration
options to add a simple version to all assets (or a specific set of assets
grouped as a :ref:`package <reference-framework-assets-packages>`):

.. configuration-block::

.. code-block:: yaml

# app/config/config.yml
framework:
assets:
version: "20150530"
version_format: "%%s?version=%%s"

.. code-block:: xml

<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:framework="http://symfony.com/schema/dic/symfony"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony
http://symfony.com/schema/dic/symfony/symfony-1.0.xsd"
>
<framework:config>
<framework:assets
version="20150530"
version-format="%%s?version=%%s"
/>
</framework:config>
</container>

.. code-block:: php

// app/config/config.php
$container->loadFromExtension('framework', array(
'assets' => array(
'version' => '20150530',
'version_format' => '%%s?version=%%s',
),
));

However, if you require more control, you need to create a custom version
strategy.

Default Package
---------------

Th 10000 e default package is used when you do not specify a package name in the
:ref:`asset <reference-twig-function-asset>` Twig function. In order to
override the version strategy used by the default package, it is necessary
to add a compiler pass.

This example shows how to integrate with `gulp-buster`_.

.. note::

busters.json as referenced below is the output from gulp-buster which
maps each asset file to its hash. A small snippet of the file's format
(JSON object):

.. code-block:: json

{
"js/script.js": "f9c7afd05729f10f55b689f36bb20172",
"css/style.css": "91cd067f79a5839536b46c494c4272d8"
}

Create Compiler Pass
~~~~~~~~~~~~~~~~~~~~

.. code-block:: php

// src/AppBundle/DependencyInjection/Compiler/OverrideAssetsDefaultPackagePass.php
namespace AppBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

class OverrideAssetsDefaultPackagePass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition('assets._default_package');
$definition->replaceArgument(1, new Reference('app.assets.buster_version_strategy'));
}
}

The code above fetches the service definition of the default package, and replaces
its second argument (the version strategy).

Register Compiler Pass
~~~~~~~~~~~~~~~~~~~~~~

.. code-block:: php

// src/AppBundle/AppBundle.php
namespace AppBundle;

use AppBundle\DependencyInjection\Compiler\OverrideAssetsDefaultPackagePass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;

class AppBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);

// only register in prod environment
if ('prod' === $container->getParameter('kernel.environment')) {
$container->addCompilerPass(new OverrideAssetsDefaultPackagePass());
}
}
}

See :doc:`/cookbook/service_container/compiler_passes` for more information
on how to use compiler passes.

Register Services
~~~~~~~~~~~~~~~~~

.. configuration-block::

.. code-block:: yaml

# app/config/services.yml
services:
app.assets.buster_version_strategy:
class: AppBundle\Asset\VersionStrategy\BusterVersionStrategy
arguments:
- "%kernel.root_dir%/../busters.json"
- "%%s?version=%%s"
public: false

.. code-block:: xml

<!-- app/config/services.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd"
>
<services>
<service id="app.assets.buster_version_strategy" class="AppBundle\Asset\VersionStrategy\BusterVersionStrategy" public="false">
<argument>%kernel.root_dir%/../busters.json</argument>
<argument>%%s?version=%%s</argument>
</service>
</services>
</container>

.. code-block:: php

// app/config/services.php
use Symfony\Component\DependencyInjection\Definition;

$definition = new Definition(
'AppBundle\Asset\VersionStrategy\BusterVersionStrategy',
array(
'%kernel.root_dir%/../busters.json',
'%%s?version=%%s',
)
);
$definition->setPublic(false);

$container->setDefinition('app.assets.buster_version_strategy', $definition);

Implement VersionStrategyInterface
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code-block:: php

// src/AppBundle/Asset/VersionStrategy/BusterVersionStrategy.php
namespace AppBundle\Asset\VersionStrategy;

use Symfony\Component\Asset\VersionStrategy\VersionStrategyInterface;

class BusterVersionStrategy implements VersionStrategyInterface
{
/**
* @var string
*/
private $manifestPath;

/**
* @var string
*/
private $format;

/**
* @var string[]
*/
private $hashes;

/**
* @param string $manifestPath
* @param string|null $format
*/
public function __construct($manifestPath, $format = null)
{
$this->manifestPath = $manifestPath;
$this->format = $format ?: '%s?%s';
}

public function getVersion($path)
{
if (!is_array($this->hashes)) {
$this->hashes = $this->loadManifest();
}

return isset($this->hashes[$path]) ? $this->hashes[$path] : '';
}

public function applyVersion($path)
{
$version = $this->getVersion($path);

if ('' === $version) {
return $path;
}

$versionized = sprintf($this->format, ltrim($path, '/'), $version);

if ($path && '/' === $path[0]) {
return '/'.$versionized;
}

return $versionized;
}

private function loadManifest(array $options)
{
$hashes = json_decode(file_get_contents($this->manifestPath), true);

return $hashes;
}
}

.. _`gulp-buster`: https://www.npmjs.com/package/gulp-buster
7 changes: 7 additions & 0 deletions cookbook/asset/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Asset
=====

.. toctree::
:maxdepth: 2

custom_version_strategy
76 changes: 76 additions & 0 deletions reference/configuration/framework.rst
6D47
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,7 @@ option.
``version``. This makes it easier to increment the cache on each
deployment.

.. _reference-framework-assets-version-format:
.. _reference-templating-version-format:
.. _reference-assets-version-format:

Expand Down Expand Up @@ -1255,6 +1256,81 @@ templating loaders. Templating loaders are used to find and load templates
from a resource (e.g. a filesystem or database). Templating loaders must
implement :class:`Symfony\\Component\\Templating\\Loader\\LoaderInterface`.

.. _reference-framework-assets-packages:

packages
........

You can group assets into packages, to specify different base URLs for them:

.. configuration-block::

.. code-block:: yaml

# app/config/config.yml
framework:
# ...
templating:
packages:
avatars:
base_urls: 'http://static_cdn.example.com/avatars'

.. code-block:: xml

<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:framework="http://symfony.com/schema/dic/symfony"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">

<framework:config>

<framework:templating>

<framework:package
name="avatars"
base-url="http://static_cdn.example.com/avatars">

</framework:templating>

</framework:config>
</container>

.. code-block:: php

// app/config/config.php
$container->loadFromExtension('framework', array(
// ...
'templating' => array(
'packages' => array(
'avatars' => array(
'base_urls' => 'http://static_cdn.example.com/avatars',
),
),
),
));

Now you can use the ``avatars`` package in your templates:

.. configuration-block:: php

.. code-block:: html+jinja

<img src="{{ asset('...', 'avatars') }}">

.. code-block:: html+php

<img src="<?php echo $view['assets']->getUrl('...', 'avatars') ?>">

Each package can configure the following options:

* :ref:`base_urls <reference-templating-base-urls>`
* :ref:`version <reference-framework-assets-version>`
* :ref:`version_format <reference-templating-version-format>`

>>>>>>> Cookbook entry: Asset - Custom Version Strategy
translator
~~~~~~~~~~

Expand Down
2 changes: 2 additions & 0 deletions reference/twig_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ Returns an instance of ``ControllerReference`` to be used with functions
like :ref:`render() <reference-twig-function-render>` and
:ref:`render_esi() <reference-twig-function-render-esi>`.

.. _reference-twig-function-asset:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why did you add this here @javiereguiluz ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. It was in the original PR. I've just removed it.


asset
~~~~~

Expand Down
0