Как использовать стратегию пользовательских версий для ресурсов

Как использовать стратегию пользовательских версий для ресурсов

Вресионирование ресурсов - это техника, которая улучшает производительность веб-приложений, добавляя идентификатор версии к URL статических ресурсов (CSS, JavaScript, images, и др.). Когда содержимое ресурса изменяется, его идентификатор также изменяется, чтобы заставить браузер скачать его заново, вместо повторного использоваия кешрованного ресаурса.

Если вашему приложению требуется продвинутое версионирование, вроде генерирования версии динамически, основываясь на некоторой внешней информации, вы можете создать собственную стратегию версий.

Note

Symfony предоставляет различные реализации, отключающие кеширование, с помощью опций конфигурации version, version_format, и json_manifest_path.

Создание собственной стратегии версии

Следующий пример показывает, как создать стратегию версии, совместимую с gulp-buster. Этот инструмент определяет файл конфигурации, под названием busters.json, который соединяет каждый файл ресурса с его хешем контента:

1
2
3
4
{
    "js/script.js": "f9c7afd05729f10f55b689f36bb20172",
    "css/style.css": "91cd067f79a5839536b46c494c4272d8"
}

Реализация VersionStrategyInterface

Стратегии версий ресурсов - это PHP-классы, которые реализуют VersionStrategyInterface. В этом примере, конструктор класса берёт в качестве аргументов путь к файлу манифеста, сгенерированного gulp-buster и формат сгенерированной строки версии:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// src/Asset/VersionStrategy/GulpBusterVersionStrategy.php
namespace App\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()
    {
        return json_decode(file_get_contents($this->manifestPath), true);
    }
}

Регистрация сервиса стратегии

После создания стратегии PHP-класса, зарегистрируйте его в качестве сервиса Symfony.

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
# config/services.yaml
services:
    App\Asset\VersionStrategy\GulpBusterVersionStrategy:
        arguments:
            - "%kernel.project_dir%/busters.json"
            - "%%s?version=%%s"
        public: false

Наконец, подключите новое версионирование ресурсов для всех ресурсов приложения или только для некоторых пакетов ресурсовм, благодаря version_strategy option:

  • YAML
  • XML
  • PHP
1
2
3
4
5
# config/packages/framework.yaml
framework:
    # ...
    assets:
        version_strategy: 'App\Asset\VersionStrategy\GulpBusterVersionStrategy'