Skip to content
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

Added the documentation for the new Asset component #4987

Closed
wants to merge 9 commits into from
249 changes: 249 additions & 0 deletions components/asset.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
.. index::
single: Asset
single: Components; Asset

The Asset Component
===================

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

Choose a reason for hiding this comment

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

typo ("stylsheets")

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed. Thank you!


Installation
------------

You can install the component in two different ways:

* :doc:`Install it via Composer </components/using_components>` (``symfony/asset`` on `Packagist`_);
Copy link
Member

Choose a reason for hiding this comment

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

The packagist URL is missing at the bottom of the file.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed thanks.

* Use the official Git repository (https://github.com/symfony/Asset).

Usage
-----

Asset Packages
Copy link
Member

Choose a reason for hiding this comment

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

Hmm, I believe we're starting to quick with this more complex terminology. On IRC, we have lots of people that are often very confused with the term "asset" itself. Maybe we should first talk about that and show a very basic Asset component usage.

Btw, I would also propose to make the Package component default to the EmptyVersionStrategy. I don't think many people need versioning at their first encounter. Then the example can be very simple:

$package = new Package();

echo $package->getUrl('/image.png'); // /image.php

Copy link
Member Author

Choose a reason for hiding this comment

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

In my opinion, the real problem was the lack of an introduction for the asset. In ac58089 I briefly explain the benefits that the Asset component provides comparing it with no using any asset management.

~~~~~~~~~~~~~~

The Asset component manages its assets through packages. A package groups all
the assets which use the same versioning strategy. In the following basic
example, a package is created to manage assets without any versioning:

.. code-block:: php
Copy link
Member

Choose a reason for hiding this comment

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

use the :: shorthand


use Symfony\Component\Asset\Package;
use Symfony\Component\Asset\VersionStrategy\EmptyVersionStrategy;

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

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

Packages implement the ``PackageInterface``, which defines the following two
methods::
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we have to show the interface here, just a defintion list of the 2 methods and their usage.


namespace Symfony\Component\Asset;

interface PackageInterface
{
/**
* Returns the asset version for an asset.
*/
public function getVersion($path);

/**
* Returns an absolute or root-relative public path.
*/
public function getUrl($path);
}

Versioned Assets
~~~~~~~~~~~~~~~~

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

Instead of relying on a simple version mechanism, the Asset component allows to
define advanced versioning strategies via PHP classes. The two built-in strategies
provided by the component are ``EmptyVersionStrategy``, which doesn't add any
Copy link
Member

Choose a reason for hiding this comment

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

I would love to use API links here

version to the asset, and ``StaticVersionStrategy``, which allows to set the
Copy link
Member

Choose a reason for hiding this comment

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

I think we should remove the serial comma here

version with a format string.

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

use Symfony\Component\Asset\Package;
use Symfony\Component\Asset\VersionStrategy\StaticVersionStrategy;

$package = new Package(new StaticVersionStrategy('v1'));
Copy link
Contributor

Choose a reason for hiding this comment

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

this should be rather a constant imo, self::VERSION_1 or self::V1, actually nevermind, it is fine, read too much from the example 👶

Copy link
Member

Choose a reason for hiding this comment

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

let's not make examples complex :)


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::

// put 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

// put 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

Custom Version Strategies
.........................

Use the ``VersionStrategyInterface`` to define your own version strategy. For
example, you could define a versioning where the current date is appended to
bust the cache every day::

use Symfony\Component\Asset\VersionStrategy\VersionStrategyInterface;

class DateVersionStrategy implements VersionStrategyInterface
{
private $version;

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

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

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

Grouped Assets
~~~~~~~~~~~~~~

It's common for applications to store their assets in a common path. If that's
your case, replace the default ``Package`` class by ``PathPackage`` to avoid
Copy link
Member

Choose a reason for hiding this comment

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

api link for PathPackage here as well

repeating the same path time and again::

use Symfony\Component\Asset\PathPackage;

Copy link
Member

Choose a reason for hiding this comment

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

missing some // ... comment (in other examples too) to indicate that not all use statements or boilerplate code is shown

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

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

Request Context Aware Assets
............................

If you are also using the HttpFoundation component in your project, for example
in a Symfony application, the ``PathPackage`` class can take into account the
Copy link
Member

Choose a reason for hiding this comment

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

I would remove the notion of the Symfony application here, as you should use the configuration provided by the framework bundle and not do this stuff by hand.

context of the current request::

use Symfony\Component\Asset\PathPackage;
use Symfony\Component\Asset\Context\RequestStackContext;

$package = new PathPackage('/static/images', new StaticVersionStrategy('v1'));
$package->setContext(new RequestStackContext($requestStack));

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

When the request context is set, in addition to the configured base path,
``PathPackage`` also prepends the current request base URL (``/somewhere/`` in
this example) to assets. This allows your website to be hosted anywhere under
the web server root directory.

Absolute Assets and CDNs
~~~~~~~~~~~~~~~~~~~~~~~~

Applications that host their assets on different domains and CDNs (*Content
Delivery Networks*) should use instead the ``UrlPackage`` class to generate
Copy link
Member

Choose a reason for hiding this comment

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

"should use instead the UrlPackage class" -> "should use the UrlPackage class instead"

Copy link
Member

Choose a reason for hiding this comment

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

I may even prefer to remove "instead" completely

absolute URLs for their assets::

use Symfony\Component\Asset\UrlPackage;

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

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

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

use Symfony\Component\Asset\UrlPackage;

$urls = array(
'http://static1.example.com/images/',
'http://static2.example.com/images/',
);
$package = new UrlPackage($urls, new StaticVersionStrategy('v1'));

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

The selection of the domain which will serve the asset is deterministic, meaning
that each asset will be always served by the same domain. This behavior simplifies
the management of HTTP cache.

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)::

use Symfony\Component\Asset\UrlPackage;
use Symfony\Component\Asset\Context\RequestStackContext;

$package = new UrlPackage(array('http://example.com/', 'https://example.com/'), new StaticVersionStrategy('v1'));
Copy link
Member

Choose a reason for hiding this comment

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

please wrap this line like this:

$package = new UrlPackage(
    array('http://example.com/', 'https://example.com/'),
    new StaticVersionStrategy('v1')
);

$package->setContext(new RequestStackContext($requestStack));
Copy link
Member

Choose a reason for hiding this comment

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

this is wrong. there is no setContext method anymore (it was removed during the review of the component, making the package immutable). The context is actually the last constructor argument.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for reporting this error. Fixed now.


echo $package->getUrl('/logo.png');
// 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 the management of several packages.
Copy link
Member

Choose a reason for hiding this comment

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

please use an api link here too


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

use Symfony\Component\Asset\Package;
use Symfony\Component\Asset\PathPackage;
use Symfony\Component\Asset\UrlPackage;
use Symfony\Component\Asset\Packages;

$versionStrategy = new StaticVersionStrategy('v1');

$defaultPackage = new Package($versionStrategy);

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

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

The ``Packages`` class requires to define a default package which will be applied
Copy link
Member

Choose a reason for hiding this comment

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

it doesn't require it. It's only requried as soon as you don't always use named packages

to all assets except those which indicate 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::

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
1 change: 1 addition & 0 deletions components/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ The Components
:hidden:

using_components
asset
Copy link
Member

Choose a reason for hiding this comment

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

should be asset/index

class_loader/index
config/index
console/index
Expand Down
4 changes: 4 additions & 0 deletions components/map.rst.inc
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
* :doc:`/components/using_components`

* **Asset**

* :doc:`/components/asset`

* :doc:`/components/class_loader/index`

* :doc:`/components/class_loader/introduction`
Expand Down