The Asset Component

The Asset component manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files.

Asset コンポーネントは、CSS スタイルシート、JavaScript ファイル、画像ファイルなどの Web アセットの URL 生成とバージョン管理を管理します。

In the past, it was common for web applications to hard-code the URLs of web assets. For example:

以前は、Web アプリケーションが Web アセットの URL をハードコーディングするのが一般的でした。例:
1
2
3
4
5
<link rel="stylesheet" type="text/css" href="/css/main.css">

<!-- ... -->

<a href="/"><img src="/images/logo.png" alt="logo"></a>

This practice is no longer recommended unless the web application is extremely simple. Hardcoding URLs can be a disadvantage because:

Web アプリケーションが非常に単純でない限り、この方法は推奨されなくなりました。 URL のハードコーディングは、次の理由で不利になる可能性があります。
  • Templates get verbose: you have to write the full path for each asset. When using the Asset component, you can group assets in packages to avoid repeating the common part of their path;
    テンプレートは冗長になります。各アセットのフル パスを記述する必要があります。 Asset コンポーネントを使用すると、アセットをパッケージにグループ化して、パスの共通部分の繰り返しを避けることができます。
  • Versioning is difficult: it has to be custom managed for each application. Adding a version (e.g. main.css?v=5) to the asset URLs is essential for some applications because it allows you to control how the assets are cached. The Asset component allows you to define different versioning strategies for each package;
    バージョン管理は難しく、アプリケーションごとにカスタム管理する必要があります。アセットの URL にバージョン (main.css?v=5 など) を追加することは、アセットのキャッシュ方法を制御できるため、一部のアプリケーションにとって不可欠です。 Asset コンポーネントを使用すると、パッケージごとに異なるバージョン管理戦略を定義できます。
  • Moving assets' location is cumbersome and error-prone: it requires you to carefully update the URLs of all assets included in all templates. The Asset component allows to move assets effortlessly just by changing the base path value associated with the package of assets;
    アセットの場所を移動するのは面倒で、エラーが発生しやすくなります。すべてのテンプレートに含まれるすべてのアセットの URL を慎重に更新する必要があります。 Assetcomponent を使用すると、アセットのパッケージに関連付けられたベース パス値を変更するだけで、アセットを簡単に移動できます。
  • It's nearly impossible to use multiple CDNs: this technique requires you to change the URL of the asset randomly for each request. The Asset component provides out-of-the-box support for any number of multiple CDNs, both regular (http://) and secure (https://).
    複数の CDN を使用することはほとんど不可能です。この手法では、リクエストごとにアセットの URL をランダムに変更する必要があります。 Asset コンポーネントは、標準 (http://) とセキュア (https://) の両方で、任意の数の複数の CDN をすぐにサポートします。

Installation

1
$ composer require symfony/asset

Note

ノート

If you install this component outside of a Symfony application, you must require the vendor/autoload.php file in your code to enable the class autoloading mechanism provided by Composer. Read this article for more details.

このコンポーネントを Symfony アプリケーションの外部にインストールする場合は、Composer が提供するクラス自動ロード メカニズムを有効にするために、コード内に vendor/autoload.php ファイルを必要とする必要があります。詳細については、この記事をお読みください。

Usage

Asset Packages

The Asset component manages assets through packages. A package groups all the assets which share the same properties: versioning strategy, base path, CDN hosts, etc. In the following basic example, a package is created to manage assets without any versioning:

Asset コンポーネントは、パッケージを通じてアセットを管理します。パッケージは、同じプロパティ (バージョン管理戦略、ベース パス、CDN ホストなど) を共有するすべてのアセットをグループ化します。次の基本的な例では、バージョン管理なしでアセットを管理するパッケージが作成されます。
1
2
3
4
5
6
7
8
9
10
11
12
use Symfony\Component\Asset\Package;
use Symfony\Component\Asset\VersionStrategy\EmptyVersionStrategy;

$package = new Package(new EmptyVersionStrategy());

// Absolute path
echo $package->getUrl('/image.png');
// result: /image.png

// Relative path
echo $package->getUrl('image.png');
// result: image.png

Packages implement PackageInterface, which defines the following two methods:

パッケージは、次の 2 つのメソッドを定義する PackageInterface を実装します。
getVersion()
Returns the asset version for an asset.
アセットのアセット バージョンを返します。
getUrl()
Returns an absolute or root-relative public path.
絶対またはルート相対パブリック パスを返します。

With a package, you can:

パッケージを使用すると、次のことができます。

A) version the assets; B) set a common base path (e.g. /css) for the assets; C) configure a CDN for the assets

A) アセットのバージョンを設定する;B) アセットに共通のベース パス (/css など) を設定する;C) アセットの CDN を構成する

Versioned Assets

One of the main features of the Asset component is the ability to manage the versioning of the application's assets. Asset versions are commonly used to control how these assets are cached.

アセット コンポーネントの主な機能の 1 つは、アプリケーションのアセットのバージョン管理を管理する機能です。アセット バージョンは、これらのアセットのキャッシュ方法を制御するためによく使用されます。

Instead of relying on a simple version mechanism, the Asset component allows you to define advanced versioning strategies via PHP classes. The two built-in strategies are the EmptyVersionStrategy, which doesn't add any version to the asset and StaticVersionStrategy, which allows you to set the version with a format string.

単純なバージョン メカニズムに依存する代わりに、Asset コンポーネントを使用すると、PHP クラスを介して高度なバージョン管理戦略を定義できます。 2 つの組み込み戦略は、アセットにバージョンを追加しない EmptyVersionStrategy と、フォーマット文字列でバージョンを設定できる StaticVersionStrategy です。

In this example, the StaticVersionStrategy is used to append the v1 suffix to any asset path:

この例では、StaticVersionStrategy を使用して v1suffix を任意のアセット パスに追加します。
1
2
3
4
5
6
7
8
9
10
11
12
use Symfony\Component\Asset\Package;
use Symfony\Component\Asset\VersionStrategy\StaticVersionStrategy;

$package = new Package(new StaticVersionStrategy('v1'));

// Absolute path
echo $package->getUrl('/image.png');
// result: /image.png?v1

// Relative path
echo $package->getUrl('image.png');
// result: image.png?v1

In case you want to modify the version format, pass a sprintf-compatible format string as the second argument of the StaticVersionStrategy constructor:

バージョン形式を変更する場合は、sprintf-compatibleformat 文字列を StaticVersionStrategy コンストラクターの 2 番目の引数として渡します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// puts the 'version' word before the version value
$package = new Package(new StaticVersionStrategy('v1', '%s?version=%s'));

echo $package->getUrl('/image.png');
// result: /image.png?version=v1

// puts the asset version before its path
$package = new Package(new StaticVersionStrategy('v1', '%2$s/%1$s'));

echo $package->getUrl('/image.png');
// result: /v1/image.png

echo $package->getUrl('image.png');
// result: v1/image.png

JSON File Manifest

A popular strategy to manage asset versioning, which is used by tools such as Webpack, is to generate a JSON file mapping all source file names to their corresponding output file:

Webpack などのツールで使用されるアセットのバージョン管理を管理するための一般的な戦略は、すべてのソース ファイル名を対応する出力ファイルにマッピングする JSON ファイルを生成することです。
1
2
3
4
5
{
    "css/app.css": "build/css/app.b916426ea1d10021f3f17ce8031f93c2.css",
    "js/app.js": "build/js/app.13630905267b809161e71d0f8a0c017b.js",
    "...": "..."
}

In those cases, use the JsonManifestVersionStrategy:

そのような場合は、JsonManifestVersionStrategy を使用します。
1
2
3
4
5
6
7
8
use Symfony\Component\Asset\Package;
use Symfony\Component\Asset\VersionStrategy\JsonManifestVersionStrategy;

// assumes the JSON file above is called "rev-manifest.json"
$package = new Package(new JsonManifestVersionStrategy(__DIR__.'/rev-manifest.json'));

echo $package->getUrl('css/app.css');
// result: build/css/app.b916426ea1d10021f3f17ce8031f93c2.css

If you request an asset that is not found in the rev-manifest.json file, the original - unmodified - asset path will be returned. The $strictMode argument helps debug issues because it throws an exception when the asset is not listed in the manifest:

rev-manifest.json ファイルにないアセットを要求すると、元の (変更されていない) アセット パスが返されます。 $strictMode 引数は、アセットがマニフェストにリストされていない場合に例外をスローするため、問題のデバッグに役立ちます。
1
2
3
4
5
6
7
8
9
10
use Symfony\Component\Asset\Package;
use Symfony\Component\Asset\VersionStrategy\JsonManifestVersionStrategy;

// The value of $strictMode can be specific per environment "true" for debugging and "false" for stability.
$strictMode = true;
// assumes the JSON file above is called "rev-manifest.json"
$package = new Package(new JsonManifestVersionStrategy(__DIR__.'/rev-manifest.json', null, $strictMode));

echo $package->getUrl('not-found.css');
// error:

If your JSON file is not on your local filesystem but is accessible over HTTP, use the RemoteJsonManifestVersionStrategy with the HttpClient component:

JSON ファイルがローカル ファイル システムになく、HTTP 経由でアクセスできる場合は、HttpClient コンポーネントで RemoteJsonManifestVersionStrategy を使用します。
1
2
3
4
5
6
7
use Symfony\Component\Asset\Package;
use Symfony\Component\Asset\VersionStrategy\RemoteJsonManifestVersionStrategy;
use Symfony\Component\HttpClient\HttpClient;

$httpClient = HttpClient::create();
$manifestUrl = 'https://cdn.example.com/rev-manifest.json';
$package = new Package(new RemoteJsonManifestVersionStrategy($manifestUrl, $httpClient));

Custom Version Strategies

Use the VersionStrategyInterface to define your own versioning strategy. For example, your application may need to append the current date to all its web assets in order to bust the cache every day:

VersionStrategyInterface を使用して、独自のバージョン管理戦略を定義します。たとえば、アプリケーションは、毎日キャッシュを消去するために、すべての Web アセットに現在の日付を追加する必要がある場合があります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
use Symfony\Component\Asset\VersionStrategy\VersionStrategyInterface;

class DateVersionStrategy implements VersionStrategyInterface
{
    private $version;

    public function __construct()
    {
        $this->version = date('Ymd');
    }

    public function getVersion(string $path)
    {
        return $this->version;
    }

    public function applyVersion(string $path)
    {
        return sprintf('%s?v=%s', $path, $this->getVersion($path));
    }
}

Grouped Assets

Often, many assets live under a common path (e.g. /static/images). If that's your case, replace the default Package class with PathPackage to avoid repeating that path over and over again:

多くの場合、多くのアセットが共通のパス (/static/images など) の下にあります。その場合は、デフォルトの Packageclass を PathPackage に置き換えて、そのパスを何度も繰り返さないようにします。
1
2
3
4
5
6
7
8
9
10
11
use Symfony\Component\Asset\PathPackage;
// ...

$pathPackage = new PathPackage('/static/images', new StaticVersionStrategy('v1'));

echo $pathPackage->getUrl('logo.png');
// result: /static/images/logo.png?v1

// Base path is ignored when using absolute paths
echo $pathPackage->getUrl('/logo.png');
// result: /logo.png?v1

Request Context Aware Assets

If you are also using the HttpFoundation component in your project (for instance, in a Symfony application), the PathPackage class can take into account the context of the current request:

プロジェクトで HttpFoundation コンポーネントも使用している場合 (たとえば、Symfony アプリケーションで)、PathPackage クラスは現在のリクエストのコンテキストを考慮することができます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use Symfony\Component\Asset\Context\RequestStackContext;
use Symfony\Component\Asset\PathPackage;
// ...

$pathPackage = new PathPackage(
    '/static/images',
    new StaticVersionStrategy('v1'),
    new RequestStackContext($requestStack)
);

echo $pathPackage->getUrl('logo.png');
// result: /somewhere/static/images/logo.png?v1

// Both "base path" and "base url" are ignored when using absolute path for asset
echo $pathPackage->getUrl('/logo.png');
// result: /logo.png?v1

Now that the request context is set, the PathPackage will prepend the current request base URL. So, for example, if your entire site is hosted under the /somewhere directory of your web server root directory and the configured base path is /static/images, all paths will be prefixed with /somewhere/static/images.

リクエスト コンテキストが設定されたので、PathPackage は現在のリクエスト ベース URL を追加します。したがって、たとえば、サイト全体が Web サーバーのルート ディレクトリの /somewhere ディレクトリの下にホストされていて、構成済みのベース パスが /static/images である場合、すべてのパスには /somewhere/static/images というプレフィックスが付けられます。

Absolute Assets and CDNs

Applications that host their assets on different domains and CDNs (Content Delivery Networks) should use the UrlPackage class to generate absolute URLs for their assets:

異なるドメインと CDN (ContentDelivery Networks) でアセットをホストするアプリケーションは、UrlPackage クラスを使用してアセットの絶対 URL を生成する必要があります。
1
2
3
4
5
6
7
8
9
10
use Symfony\Component\Asset\UrlPackage;
// ...

$urlPackage = new UrlPackage(
    'http://static.example.com/images/',
    new StaticVersionStrategy('v1')
);

echo $urlPackage->getUrl('/logo.png');
// result: http://static.example.com/images/logo.png?v1

You can also pass a schema-agnostic URL:

スキーマに依存しない URL を渡すこともできます。
1
2
3
4
5
6
7
8
9
10
use Symfony\Component\Asset\UrlPackage;
// ...

$urlPackage = new UrlPackage(
    '//static.example.com/images/',
    new StaticVersionStrategy('v1')
);

echo $urlPackage->getUrl('/logo.png');
// result: //static.example.com/images/logo.png?v1

This is useful because assets will automatically be requested via HTTPS if a visitor is viewing your site in https. If you want to use this, make sure that your CDN host supports HTTPS.

これは、訪問者が https でサイトを表示している場合、HTTPS 経由でアセットが自動的にリクエストされるため便利です。これを使用する場合は、CDN ホストが HTTPS をサポートしていることを確認してください。

In case you serve assets from more than one domain to improve application performance, pass an array of URLs as the first argument to the UrlPackage constructor:

アプリケーションのパフォーマンスを向上させるために複数のドメインからアセットを提供する場合は、URL の配列を最初の引数として UrlPackageconstructor に渡します。
1
2
3
4
5
6
7
8
9
10
11
12
13
use Symfony\Component\Asset\UrlPackage;
// ...

$urls = [
    '//static1.example.com/images/',
    '//static2.example.com/images/',
];
$urlPackage = new UrlPackage($urls, new StaticVersionStrategy('v1'));

echo $urlPackage->getUrl('/logo.png');
// result: http://static1.example.com/images/logo.png?v1
echo $urlPackage->getUrl('/icon.png');
// result: http://static2.example.com/images/icon.png?v1

For each asset, one of the URLs will be randomly used. But, the selection is deterministic, meaning that each asset will always be served by the same domain. This behavior simplifies the management of HTTP cache.

アセットごとに、URL の 1 つがランダムに使用されます。ただし、選択は決定論的です。つまり、各アセットは常に同じドメインによって提供されます。この動作により、HTTP キャッシュの管理が簡素化されます。

Request Context Aware Assets

Similarly to application-relative assets, absolute assets can also take into account the context of the current request. In this case, only the request scheme is considered, in order to select the appropriate base URL (HTTPs or protocol-relative URLs for HTTPs requests, any base URL for HTTP requests):

アプリケーション関連アセットと同様に、絶対アセットも現在のリクエストのコンテキストを考慮に入れることができます。この場合、適切なベース URL (HTTPs または HTTPs 要求のプロトコル相対 URL、HTTP 要求の任意のベース URL) を選択するために、requestscheme のみが考慮されます。
1
2
3
4
5
6
7
8
9
10
11
12
13
use Symfony\Component\Asset\Context\RequestStackContext;
use Symfony\Component\Asset\UrlPackage;
// ...

$urlPackage = new UrlPackage(
    ['http://example.com/', 'https://example.com/'],
    new StaticVersionStrategy('v1'),
    new RequestStackContext($requestStack)
);

echo $urlPackage->getUrl('/logo.png');
// assuming the RequestStackContext says that we are on a secure host
// result: https://example.com/logo.png?v1

Named Packages

Applications that manage lots of different assets may need to group them in packages with the same versioning strategy and base path. The Asset component includes a Packages class to simplify management of several packages.

多くの異なるアセットを管理するアプリケーションは、同じバージョン管理戦略とベース パスを使用してパッケージにグループ化する必要がある場合があります。 Asset コンポーネントには、複数のパッケージの管理を簡素化する Packages クラスが含まれています。

In the following example, all packages use the same versioning strategy, but they all have different base paths:

次の例では、すべてのパッケージが同じバージョン管理戦略を使用していますが、ベース パスはすべて異なります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use Symfony\Component\Asset\Package;
use Symfony\Component\Asset\Packages;
use Symfony\Component\Asset\PathPackage;
use Symfony\Component\Asset\UrlPackage;
// ...

$versionStrategy = new StaticVersionStrategy('v1');

$defaultPackage = new Package($versionStrategy);

$namedPackages = [
    'img' => new UrlPackage('http://img.example.com/', $versionStrategy),
    'doc' => new PathPackage('/somewhere/deep/for/documents', $versionStrategy),
];

$packages = new Packages($defaultPackage, $namedPackages);

The Packages class allows to define a default package, which will be applied to assets that don't define the name of the package to use. In addition, this application defines a package named img to serve images from an external domain and a doc package to avoid repeating long paths when linking to a document inside a template:

Packages クラスでは、使用するパッケージの名前を定義していないアセットに適用されるデフォルトのパッケージを定義できます。さらに、このアプリケーションは、外部ドメインからの画像を提供する img という名前のパッケージと、テンプレート内のドキュメントにリンクするときに長いパスの繰り返しを避けるための doc パッケージを定義します。
1
2
3
4
5
6
7
8
echo $packages->getUrl('/main.css');
// result: /main.css?v1

echo $packages->getUrl('/logo.png', 'img');
// result: http://img.example.com/logo.png?v1

echo $packages->getUrl('resume.pdf', 'doc');
// result: /somewhere/deep/for/documents/resume.pdf?v1

Local Files and Other Protocols

In addition to HTTP this component supports other protocols (such as file:// and ftp://). This allows for example to serve local files in order to improve performance:

HTTP に加えて、このコンポーネントは他のプロトコル (file:// や ftp:// など) をサポートします。これにより、たとえば、パフォーマンスを向上させるためにローカル ファイルを提供できます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use Symfony\Component\Asset\UrlPackage;
// ...

$localPackage = new UrlPackage(
    'file:///path/to/images/',
    new EmptyVersionStrategy()
);

$ftpPackage = new UrlPackage(
    'ftp://example.com/images/',
    new EmptyVersionStrategy()
);

echo $localPackage->getUrl('/logo.png');
// result: file:///path/to/images/logo.png

echo $ftpPackage->getUrl('/logo.png');
// result: ftp://example.com/images/logo.png

Learn more