solas-wyrd/yii2-static-assets-publisher

Automatically discovers and publishes Yii2 AssetBundle resources for production builds

Maintainers

Package info

github.com/SolasWyrd/yii2-static-assets-publisher

pkg:composer/solas-wyrd/yii2-static-assets-publisher

Statistics

Installs: 10

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.1.0 2026-06-22 05:23 UTC

This package is auto-updated.

Last update: 2026-06-22 05:26:16 UTC


README

Пакет автоматически находит классы yii\web\AssetBundle, публикует их ресурсы во время production-сборки и создаёт manifest с контентными хешами.

Latest Stable Version Total Downloads Build status Code Coverage Static analysis

Требования

  • PHP 8.2 или выше;
  • Yii2 2.0.49 или выше;

Установка

composer require solas-wyrd/yii2-static-assets-publisher

Конфигурация

Создайте файл, например config/static-assets.php:

<?php

declare(strict_types=1);

use SolasWyrd\Yii2StaticAssets\Configuration\StaticAssetsConfiguration;

$applicationPath = dirname(__DIR__);
$vendorPath = $applicationPath . '/vendor';

return new StaticAssetsConfiguration(
    targetPath: $applicationPath . '/web/assets/builds',
    allowedBuildRoot: $applicationPath . '/web/assets',
    baseUrl: '/assets/builds',
    scanPaths: [
        $applicationPath,
        $vendorPath,
    ],
    hashRoots: [
        'app' => $applicationPath,
        'vendor' => $vendorPath,
    ],
    manifestFileName: 'static-assets-manifest.json',
);

Параметры

targetPath — каталог опубликованных ассетов. Перед публикацией он полностью пересоздаётся.

allowedBuildRoot — безопасный родительский каталог. targetPath обязан находиться внутри него. Это защищает от удаления произвольного пути и выхода через symlink.

baseUrl — публичный URL build-директории.

scanPaths — каталоги поиска PHP-классов

hashRoots — соответствие логических имён абсолютным корням. Абсолютный путь /var/www/app/assets может быть записан в manifest как app/assets.

Yii DI definitions

<?php

declare(strict_types=1);

use SolasWyrd\Yii2StaticAssets\Configuration\StaticAssetsConfiguration;
use SolasWyrd\Yii2StaticAssets\Contract\AssetBundleFinderInterface;
use SolasWyrd\Yii2StaticAssets\Contract\AssetBundlePublisherInterface;
use SolasWyrd\Yii2StaticAssets\Contract\AssetManifestReaderInterface;
use SolasWyrd\Yii2StaticAssets\Contract\AssetManifestWriterInterface;
use SolasWyrd\Yii2StaticAssets\Contract\AssetSourceHasherInterface;
use SolasWyrd\Yii2StaticAssets\Contract\ProgressReporterInterface;
use SolasWyrd\Yii2StaticAssets\Discovery\AstAssetBundleFinder;
use SolasWyrd\Yii2StaticAssets\Hash\ContentAssetSourceHasher;
use SolasWyrd\Yii2StaticAssets\Manifest\JsonFileAssetManifestReader;
use SolasWyrd\Yii2StaticAssets\Manifest\JsonFileAssetManifestWriter;
use SolasWyrd\Yii2StaticAssets\Publication\YiiAssetBundlePublisher;
use SolasWyrd\Yii2StaticAssets\Reporting\ConsoleProgressReporter;

/** @var StaticAssetsConfiguration $configuration */
$configuration = require __DIR__ . '/static-assets.php';

return [
    StaticAssetsConfiguration::class =>
        static fn (): StaticAssetsConfiguration => $configuration,

    AssetBundleFinderInterface::class => AstAssetBundleFinder::class,
    AssetBundlePublisherInterface::class => YiiAssetBundlePublisher::class,
    AssetSourceHasherInterface::class => ContentAssetSourceHasher::class,
    AssetManifestReaderInterface::class => JsonFileAssetManifestReader::class,
    AssetManifestWriterInterface::class => JsonFileAssetManifestWriter::class,
    ProgressReporterInterface::class => ConsoleProgressReporter::class,
];

Console controller

Добавьте контроллер пакета в console-конфигурацию:

<?php

declare(strict_types=1);

use SolasWyrd\Yii2StaticAssets\Yii\AssetBuildController;

return [
    'controllerMap' => [
        'asset-build' => [
            'class' => AssetBuildController::class,
        ],
    ],
];

Публикация:

php yii asset-build/publish

Runtime AssetManager

В web-конфигурации используйте manifest вместо повторного вычисления хешей:

<?php

declare(strict_types=1);

use SolasWyrd\Yii2StaticAssets\Configuration\StaticAssetsConfiguration;
use SolasWyrd\Yii2StaticAssets\Hash\ContentAssetSourceHasher;
use SolasWyrd\Yii2StaticAssets\Hash\ManifestAssetPathHasher;
use SolasWyrd\Yii2StaticAssets\Manifest\JsonFileAssetManifestReader;
use yii\web\AssetManager;

/** @var StaticAssetsConfiguration $configuration */
$configuration = require __DIR__ . '/static-assets.php';

$manifestHasher = new ManifestAssetPathHasher(
    new JsonFileAssetManifestReader($configuration),
    new ContentAssetSourceHasher($configuration),
);

return [
    'components' => [
        'assetManager' => [
            'class' => AssetManager::class,
            'basePath' => $configuration->targetPath,
            'baseUrl' => $configuration->baseUrl,
            'appendTimestamp' => false,
            'linkAssets' => false,
            'forceCopy' => false,
            'hashCallback' => $manifestHasher(...),
        ],
    ],
];

Если manifest отсутствует или не содержит source-путь, runtime завершится с исключением. Для production это правильное fail-fast поведение: неполная сборка не маскируется пересчётом файлов.

Замена реализаций

Собственный поиск AssetBundle

use SolasWyrd\Yii2StaticAssets\Contract\AssetBundleFinderInterface;

return [
    AssetBundleFinderInterface::class => ProjectAssetBundleFinder::class,
];

Это полезно, если проект использует собственный registry, ограниченные namespaces или предварительно сформированный classmap.

Собственная публикация

use SolasWyrd\Yii2StaticAssets\Contract\AssetBundlePublisherInterface;

return [
    AssetBundlePublisherInterface::class => CdnAssetBundlePublisher::class,
];

Реализация может публиковать в shared volume, объектное хранилище или применять дополнительные права и post-processing.

Другое хранилище manifest

use SolasWyrd\Yii2StaticAssets\Contract\AssetManifestReaderInterface;
use SolasWyrd\Yii2StaticAssets\Contract\AssetManifestWriterInterface;

return [
    AssetManifestReaderInterface::class => RedisAssetManifestReader::class,
    AssetManifestWriterInterface::class => RedisAssetManifestWriter::class,
];

Запуск без консольного прогресса

use SolasWyrd\Yii2StaticAssets\Contract\ProgressReporterInterface;
use SolasWyrd\Yii2StaticAssets\Reporting\NullProgressReporter;

return [
    ProgressReporterInterface::class => NullProgressReporter::class,
];

Manifest

Пример static-assets-manifest.json:

{
    "app/assets": "f4d7c8a1b2e39d10",
    "vendor/yiisoft/yii2/assets": "91f8a4bb6c2280e1"
}

Изменение содержимого или имени файла меняет хеш и URL опубликованного ресурса. Неизменённый контент сохраняет прежний URL.

Docker

Публикуйте ассеты после установки зависимостей и копирования исходников:

WORKDIR /var/www/html

COPY composer.json composer.lock ./

RUN composer install \
    --no-dev \
    --prefer-dist \
    --no-interaction \
    --no-progress

COPY . .

RUN composer dump-autoload \
        --optimize \
        --classmap-authoritative \
    && php yii asset-build/publish

Разработка пакета

composer install
composer validate --strict
composer test
composer analyse
composer cs-check

Автоматическое исправление code style:

composer cs-fix

Лицензия

MIT.