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