Pragmatic frontend for Symfony developers

Pragmatic frontend for Symfony developers

364d59ac0b4b4e5eee8aeb27a127d176?s=128

Titouan Galopin

February 28, 2020
Tweet

Transcript

  1. 7.

    Agenda 1. A bit of history 2. Modern frontend 3.

    The least complex technology possible 4. Approaches to frontend with Symfony 7
  2. 14.

    14 2016–2020 New technologies and platforms built around modern frontend

    emerge: GraphQL, Service Workers, Cordova, Electron, React Native, …
  3. 23.

    23 Ever been angered by a website you couldn’t open

    in multiple tabs without messing with the data?
  4. 25.

    25 Ever had to use a screen reader on a

    full Javascript interface?
  5. 32.

    How many times did you experience PHP failing between a

    function call and the first line of the function? 32
  6. 33.

    How many times did you experience an AJAX call failing

    between the request and the response? 33
  7. 46.

    46 Full-page app + API Has a lot of drawbacks

    but is the only option for multiple clients (web + mobile)
  8. 48.

    48 Most recent JS frameworks (React, Vue, …) can be

    used in limited parts of the page
  9. 52.

    52 {# index.html.twig #} {% extends 'base.html.twig' %} {% block

    body %} <div> Hello world <div> <input type="text" placeholder="Color in hexadecimal" /> </div> </div> {% endblock %}
  10. 53.

    53 {# index.html.twig #} {% extends 'base.html.twig' %} {% block

    body %} <div> Hello world <div> <input type="text" placeholder="Color in hexadecimal" /> </div> </div> {% endblock %} This could be a Symfony Form field
  11. 56.

    56 Webpack is a build tool It lets you manipulate

    your Javascript and CSS before using it in production (JSX, minification, …)
  12. 57.

    57 Webpack Encore wraps Webpack around a nice API to

    improve its Developer Experience
  13. 61.

    61 {# index.html.twig #} {% extends 'base.html.twig' %} {% block

    body %} <div> Hello world <div data-color-chooser> <input type="text" placeholder="Color in hexadecimal" /> </div> </div> {% endblock %} Marker to find where to inject a React component
  14. 62.

    62 // app.js import ReactDOM from 'react-dom'; import {ColorChooser} from

    './ColorChooser/ColorChooser'; $('div[data-color-chooser]').each((key, node) => { const input = $(node).find('input'); ReactDOM.render( <ColorChooser color={input.val()} onColorChange={(color) => input.attr('value', color)} />, node ); });
  15. 63.

    63

  16. 64.

    64 ✓ Allow to use great React components where it’s

    useful ✓ Do not add unnecessary complexity ✓ 100% compatible with Symfony, HTTP and default browser behaviors
  17. 66.

    66 namespace App\DataExposer; class DataExposer { private $data = [];

    public function expose(string $name, $value) { $this->data[$name] = $value; } public function getExposedData(): array { return $this->data; } }
  18. 67.

    67 namespace App\Twig; class DataExposerExtension extends AbstractExtension { private $exposer;

    public function __construct(DataExposer $exposer) { $this->exposer = $exposer; } public function getFunctions(): array { return [ new TwigFunction('expose', [$this, 'exposeData']), new TwigFunction('get_exposed_data', [$this, 'getExposedData']), ]; } // ... }
  19. 68.

    68 {# base.html.twig #} <!DOCTYPE html> <html> <head> <meta charset="UTF-8">

    <title>Welcome!</title> </head> <body> {% block body %}{% endblock %} <script type="application/json" id="exposed-data"> {{- get_exposed_data()|json_encode|raw -}} </script> {{ encore_entry_script_tags('app') }} </body> </html>
  20. 70.

    70 ✓ Easy to parse (JSON.stringify) ✓ Compatible with Content

    Security Policy ✓ Easy to use in automated testing