Skip to content

Commit 178821e

Browse files
committed
refactor
1 parent 9f4ae9b commit 178821e

File tree

2 files changed

+285
-268
lines changed

2 files changed

+285
-268
lines changed

components/weblink.rst

Lines changed: 11 additions & 265 deletions
Original file line numberDiff line numberDiff line change
@@ -11,259 +11,21 @@ The WebLink Component
1111
.. versionadded:: 3.3
1212
The WebLink component was introduced in Symfony 3.3.
1313

14-
By implementing cutting edge web standards, namely `HTTP/2 Server Push`_ and
15-
W3C's `Resource Hints`_, the WebLink component
16-
brings great opportunities to boost webapp's performance.
17-
18-
Thanks to WebLink, HTTP/2 (**h2**) servers are able to push resources to clients
19-
before they even know that they need them (think to CSS or JavaScript
20-
files, or relations of an API resource). WebLink also enables other very
21-
efficient optimisations that work with HTTP 1:
22-
23-
- telling the browser to fetch or to render another webpage in the
24-
background ;
25-
- init early DNS lookups, TCP handshakes or TLS negotiations
26-
27-
Let's discover how easy it is to use it and the real life benefits you
28-
can expect.
29-
30-
To benefit from HTTP/2 Server Pushes, a HTTP/2 server and a HTTPS connection
31-
are mandatory (even in local).
32-
Both Apache, Nginx and Caddy support these protocols.
33-
Be sure they are properly configured before reading.
34-
35-
Alternatively, you can use the `Docker installer and runtime for
36-
Symfony`_ provided by Kévin Dunglas (community supported).
37-
38-
It includes everything you need to run Symfony
39-
(PHP :doc:`configured properly for Symfony </performance>`, and Composer)
40-
as well as a development reverse proxy (Apache) supporting HTTP/2 Server Push
41-
and HTTPS (most clients only support HTTP/2 over TLS).
42-
43-
Unzip the downloaded archive, open a shell in the resulting directory and run
44-
the following command:
14+
Installation
15+
------------
4516

4617
.. code-block:: terminal
4718
48-
# Install Symfony and start the project
49-
$ docker-compose up
50-
51-
Open ``https://localhost``, if this nice page appears, you
52-
successfully created your first Symfony 4 project and are browsing it in
53-
HTTP/2!
54-
55-
.. image:: /_images/components/weblink/symfony4-http2.png
56-
57-
Let's create a very simple homepage using
58-
the `Twig`_ templating engine.
59-
60-
The first step is to install the library itself:
61-
62-
.. code-block:: terminal
63-
64-
composer req twig
65-
66-
Symfony is smart enough to download Twig, to automatically register it,
67-
and to enable Symfony features requiring the library.
68-
It also generates a base HTML5 layout in the ``templates/`` directory.
69-
70-
Now, download `Boostrap`_, extract the archive and copy the file
71-
``dist/css/bootstrap.min.css`` in the ``public/`` directory of our
72-
project.
73-
74-
Symfony comes with a `nice integration with of the most popular CSS framework`_.
75-
76-
.. note::
77-
78-
In a real project, you should use Yarn or NPM with
79-
:doc:`Symfony Encore </frontend/encore/bootstrap>`_
80-
to install Bootstrap.
81-
82-
Now, it's time to create the template of our homepage:
83-
84-
.. code-block:: html
85-
86-
<!DOCTYPE html>
87-
<html>
88-
<head>
89-
<meta charset="UTF-8">
90-
<title>Welcome!</title>
91-
<link rel="stylesheet" href="/bootstrap.min.css">
92-
</head>
93-
<body>
94-
<main role="main" class="container">
95-
<h1>Hello World</h1>
96-
<p class="lead">That's a lot of highly dynamic content, right?</p>
97-
</main>
98-
</body>
99-
</html>
100-
101-
And finally, register our new template as the homepage using the builtin
102-
:doc:`TemplateController </templating/render_without_controller>`_:
103-
104-
.. code-block:: yaml
105-
106-
# config/routes.yaml
107-
index:
108-
path: /
109-
defaults:
110-
_controller: 'Symfony\Bundle\FrameworkBundle\Controller\TemplateController::templateAction'
111-
template: 'homepage.html.twig'
112-
113-
Refresh your browser, this nice homepage should appear:
114-
115-
.. image:: /_images/components/weblink/homepage-requests.png
116-
117-
HTTP requests are issued by the browser, one for the homepage, and
118-
another one for Bootstrap. But we know from the very beginning that the
119-
browser **will** need Bootstrap. Instead of waiting that the browser
120-
downloads the homepage, parses the HTML (notice "Initiator: Parser" in
121-
Chrome DevTools), encounters the reference to ``bootstrap.min.css`` and
122-
finally sends a new HTTP request, we could take benefit of the HTTP/2
123-
Push feature to directly send both resources to the browser.
124-
125-
Let's do it! Install the WebLink component:
126-
127-
.. code-block:: terminal
128-
129-
composer req weblink
130-
131-
As for Twig, Symfony will automatically download and register this component into our app.
132-
Now, update the template to use the ``preload`` Twig helper that
133-
leverages the WebLink component:
134-
135-
.. code:: html+twig
136-
137-
{# ... #}
138-
<link rel="stylesheet" href="{{ preload('/bootstrap.min.css') }}">
139-
{# ... #}
140-
141-
Reload the page:
142-
143-
.. image:: /_images/components/weblink/http2-server-push.png
144-
145-
As you can see (Initiator: Push), both
146-
responses have been sent directly by the server.
147-
``bootstrap.min.css`` has started to be received before the browser even requested it!
148-
149-
.. note::
150-
151-
Google Chrome provides a nice interface to debug HTTP/2 connections.
152-
Open ``chrome://net-internals/#http2`` to start the tool.
153-
154-
How does it works?
155-
~~~~~~~~~~~~~~~~~~
156-
157-
The WebLink component tracks Link HTTP headers to add to the response.
158-
When using the ``preload()`` helper, a ``Link`` header
159-
with a `preload`_
160-
``rel`` attribute is added to the response:
161-
162-
.. image:: /_images/components/weblink/response-headers.png
163-
164-
According to `the Preload specification`_,
165-
when a HTTP/2 server detects that the original (HTTP 1) response
166-
contains this HTTP header, it will automatically trigger a push for the
167-
related file in the same HTTP/2 connection.
168-
The Apache server provided in the Docker setup supports this feature.
169-
It's why Bootstrap is pushed
170-
to the client!
171-
172-
Popular proxy services and CDN including
173-
`Cloudflare`_, `Fastly`_ and `Akamai`_ also leverage this feature.
174-
It means that you can push resources to
175-
clients and improve performance of your apps in production right now!
176-
All you need is Symfony 3.3+ and a compatible web server or CDN service.
177-
178-
If you want to prevent the push but let the browser preload the resource by
179-
issuing an early separate HTTP request, use the ``nopush`` attribute:
180-
181-
.. code-block:: html+twig
182-
183-
{# ... #}
184-
<link rel="stylesheet" href="{{ preload('/bootstrap.min.css', {nopush: true}) }}">
185-
{# ... #}
186-
187-
Before using HTTP/2 Push, be sure to read `this great article`_ about
188-
known issues, cache implications and the state of the support in popular
189-
browsers.
190-
191-
In addition to HTTP/2 Push and preloading, the WebLink component also
192-
provide some helpers to send `Resource
193-
Hints <https://www.w3.org/TR/resource-hints/#resource-hints>`__ to
194-
clients, the following helpers are available:
195-
196-
- ``dns_prefetch``: "indicate an origin that will be used to fetch
197-
required resources, and that the user agent should resolve as early
198-
as possible"
199-
- ``preconnect``: "indicate an origin that will be used to fetch
200-
required resources. Initiating an early connection, which includes
201-
the DNS lookup, TCP handshake, and optional TLS negotiation, allows
202-
the user agent to mask the high latency costs of establishing a
203-
connection"
204-
- ``prefetch``: "identify a resource that might be required by the next
205-
navigation, and that the user agent *should* fetch, such that the
206-
user agent can deliver a faster response once the resource is
207-
requested in the future"
208-
- ``prerender``: "identify a resource that might be required by the
209-
next navigation, and that the user agent *should* fetch and
210-
execute, such that the user agent can deliver a faster response once
211-
the resource is requested in the future"
212-
213-
The component can also be used to send HTTP link not related to
214-
performance. For instance, any `link defined in the HTML specification`_:
215-
216-
.. code:: html+twig
217-
218-
{# ... #}
219-
<link rel="alternate" href="{{ link('/index.jsonld', 'alternate') }}">
220-
<link rel="stylesheet" href="{{ preload('/bootstrap.min.css', {nopush: true}) }}">
221-
{# ... #}
222-
223-
The previous snippet will result in this HTTP header being sent to the
224-
client:
225-
``Link: </index.jsonld>; rel="alternate",</bootstrap.min.css>; rel="preload"; nopush``
226-
227-
You can also add links to the HTTP response directly from a controller
228-
or any service:
229-
230-
.. code:: php
231-
232-
// src/Controller/BlogPostAction.php
233-
namespace App\Controller;
234-
235-
use Fig\Link\GenericLinkProvider;
236-
use Fig\Link\Link;
237-
use Symfony\Component\HttpFoundation\Request;
238-
use Symfony\Component\HttpFoundation\Response;
239-
240-
final class BlogPostAction
241-
{
242-
public function __invoke(Request $request): Response
243-
{
244-
$linkProvider = $request->attributes->get('_links', new GenericLinkProvider());
245-
$request->attributes->set('_links', $linkProvider->withLink(new Link('preload', '/bootstrap.min.css')));
246-
247-
return new Response('Hello');
248-
}
249-
}
250-
251-
.. code-block:: yaml
252-
253-
# app/config/routes.yaml
254-
blog_post:
255-
path: /post
256-
defaults:
257-
_controller: 'App\Controller\BlogPostAction'
19+
$ composer require symfony/weblink
25820
259-
Last but not least, as all Symfony components, WebLink can be used as a
260-
standalone PHP library:
21+
Alternatively, you can clone the `<https://github.com/symfony/weblink>`_ repository.
26122

262-
.. code-block:: php
23+
.. include:: /components/require_autoload.rst.inc
26324

264-
<?php
25+
Usage
26+
-----
26527

266-
require __DIR__.'/../vendor/autoload.php';
28+
Basic usage::
26729

26830
use Fig\Link\GenericLinkProvider;
26931
use Fig\Link\Link;
@@ -276,28 +38,12 @@ standalone PHP library:
27638

27739
echo 'Hello';
27840

279-
To see how WebLink is used in the wild, take a look to the `Bolt`_
280-
and `Sulu`_ CMS, they both use WebLink to trigger HTTP/2 pushes.
28141

282-
While we're speaking about interoperability, WebLink can deal with any link implementing
283-
`PSR-13`_.
42+
.. seealso::
28443

285-
Thanks to Symfony WebLink, there is no excuses to not to switch to HTTP/2!
44+
Read the :doc:`WebLink documentation </weblink>`_ to learn how
45+
to use the features implemented by this component.
28646

28747
.. _`Web Links`: https://tools.ietf.org/html/rfc5988
28848
.. _`HTTP/2 Server Push`: https://tools.ietf.org/html/rfc7540#section-8.2
28949
.. _`Resource Hints`: https://www.w3.org/TR/resource-hints/
290-
.. _`Twig`: https://twig.symfony.com/
291-
.. _`Docker installer and runtime for Symfony`: https://github.com/dunglas/symfony-docker
292-
.. _`Bootstrap`: https://getbootstrap.com/
293-
.. _`nice integration with of the most popular CSS framework`: https://symfony.com/blog/new-in-symfony-3-4-bootstrap-4-form-theme
294-
.. _`preload`: https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content
295-
.. _`the Preload specification`: https://www.w3.org/TR/preload/#server-push-(http/2)
296-
.. _`Cloudflare`: https://blog.cloudflare.com/announcing-support-for-http-2-server-push-2/
297-
.. _`Fastly`: https://docs.fastly.com/guides/performance-tuning/http2-server-push
298-
.. _`Akamai`: https://blogs.akamai.com/2017/03/http2-server-push-the-what-how-and-why.html
299-
.. _`this great article`: https://www.shimmercat.com/en/blog/articles/whats-push/
300-
.. _`link defined in the HTML specification`: https://html.spec.whatwg.org/dev/links.html#linkTypes
301-
.. _`Bolt`: https://bolt.cm/
302-
.. _`Sulu`: https://sulu.io/
303-
.. _`PSR-13`: http://www.php-fig.org/psr/psr-13/

0 commit comments

Comments
 (0)