diff --git a/frontend/custom_version_strategy.rst b/frontend/custom_version_strategy.rst new file mode 100644 index 00000000000..deaa99031c4 --- /dev/null +++ b/frontend/custom_version_strategy.rst @@ -0,0 +1,201 @@ +.. 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. + +Asset versioning is a technique that improves the performance of web +applications by adding a version identifier to the URL of the static assets +(CSS, JavaScript, images, etc.) When the content of the asset changes, its +identifier is also modified to force the browser to download it again instead of +reusing the cached asset. + +Symfony supports asset versioning thanks to the +:ref:`version ` and +:ref:`version_format ` configuration +options. If your application requires a more advanced versioning, such as +generating the version dynamically based on some external information, you can +create your own version strategy. + +Creating your Own Asset Version Strategy +---------------------------------------- + +The following example shows how to create a version strategy compatible with +`gulp-buster`_. This tool defines a configuration file called ``busters.json`` +which maps each asset file to its content hash: + +.. code-block:: json + + { + "js/script.js": "f9c7afd05729f10f55b689f36bb20172", + "css/style.css": "91cd067f79a5839536b46c494c4272d8" + } + +Implement VersionStrategyInterface +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Asset version strategies are PHP classes that implement the +:class:`Symfony\\Component\\Asset\\VersionStrategy\\VersionStrategyInterface`. +In this example, the constructor of the class takes as arguments the path to +the manifest file generated by `gulp-buster`_ and the format of the generated +version string:: + + // src/AppBundle/Asset/VersionStrategy/GulpBusterVersionStrategy.php + namespace AppBundle\Asset\VersionStrategy; + + use Symfony\Component\Asset\VersionStrategy\VersionStrategyInterface; + + class GulpBusterVersionStrategy 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) + { + return json_decode(file_get_contents($this->manifestPath), true); + } + } + +Register the Strategy Service +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +After creating the strategy PHP class, register it as a Symfony service. + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/services.yml + services: + app.assets.versioning.gulp_buster: + class: AppBundle\Asset\VersionStrategy\GulpBusterVersionStrategy + arguments: + - "%kernel.root_dir%/../busters.json" + - "%%s?version=%%s" + public: false + + .. code-block:: xml + + + + + + + %kernel.root_dir%/../busters.json + %%s?version=%%s + + + + + .. code-block:: php + + // app/config/services.php + use Symfony\Component\DependencyInjection\Definition; + + $definition = new Definition( + 'AppBundle\Asset\VersionStrategy\GulpBusterVersionStrategy', + array( + '%kernel.root_dir%/../busters.json', + '%%s?version=%%s', + ) + ); + $definition->setPublic(false); + + $container->setDefinition('app.assets.versioning.gulp_buster', $definition); + +Finally, enable the new asset versioning for all the application assets or just +for some :ref:`asset package ` thanks to +the :ref:`version_strategy ` option: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config.yml + framework: + # ... + assets: + version_strategy: 'app.assets.versioning.gulp_buster' + + .. code-block:: xml + + + + + + + + + + + .. code-block:: php + + // app/config/config.php + $container->loadFromExtension('framework', array( + // ... + 'assets' => array( + 'version_strategy' => 'app.assets.versioning.gulp_buster', + ), + )); + +.. _`gulp-buster`: https://www.npmjs.com/package/gulp-buster diff --git a/reference/configuration/framework.rst b/reference/configuration/framework.rst index 8e6dcdde3b9..72a46d16034 100644 --- a/reference/configuration/framework.rst +++ b/reference/configuration/framework.rst @@ -75,6 +75,7 @@ Configuration * `packages`_ * `version`_ * `version_format`_ + * `version_strategy`_ * `templating`_ * `hinclude_default_template`_ * :ref:`form ` @@ -945,6 +946,8 @@ collection each time it generates an asset's path: ), )); +.. _reference-framework-assets-packages: + packages ........ @@ -1013,6 +1016,7 @@ Each package can configure the following options: * :ref:`base_urls ` * :ref:`version ` * :ref:`version_format ` +* :ref:`version_strategy ` .. _reference-framework-assets-version: .. _ref-framework-assets-version: @@ -1090,6 +1094,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: @@ -1130,6 +1135,16 @@ is set to ``5``, the asset's path would be ``/images/logo.png?version=5``. any URL rewriting. The latter option is useful if you would like older asset versions to remain accessible at their original URL. +.. _reference-framework-assets-version_strategy: + +version_strategy +................ + +**type**: ``string`` **default**: null + +The service id of the :doc:`asset version strategy ` +applied to the assets. + templating ~~~~~~~~~~