Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[SymfonyLive Paris 2020] Pragmatic frontend for Symfony developers

[SymfonyLive Paris 2020] Pragmatic frontend for Symfony developers

Titouan Galopin

September 24, 2020
Tweet

More Decks by Titouan Galopin

Other Decks in Programming

Transcript

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

    The least complex technology possible 4. Approaches to frontend with Symfony 7
  2. 14 2016–2020 New technologies and platforms built around modern frontend

    emerge: GraphQL, Service Workers, Cordova, Electron, React Native, …
  3. 23 Ever been angered by a website you couldn’t open

    in multiple tabs without messing with the data?
  4. 25 Ever had to use a screen reader on a

    fully Javascript interface?
  5. How many times did you experience PHP failing between a

    function call and the first line of the function? 32
  6. How many times did you experience an AJAX call failing

    between the request and the response? 33
  7. 46 Full-page app + API Has a lot of drawbacks

    but is the only option for multiple clients (web + mobile)
  8. 49 Most recent JS frameworks (React, Vue, …) can be

    used in limited parts of the page
  9. 53 {# index.html.twig #} {% extends 'base.html.twig' %} {% block

    body %} <div> Hello world <div> <input type="text" placeholder="Color in hexadecimal" /> </div> </div> {% endblock %}
  10. 54 {# 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. 57 Webpack is a build tool It lets you manipulate

    your Javascript and CSS before using it in production (JSX, minification, …)
  12. 58 Webpack Encore wraps Webpack around a nice API to

    improve its Developer Experience
  13. 62 {# 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. 63 // 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. 64 // 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 ); }); Using a selector library to find the node
  16. 65 // 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 ); }); Replacing the content of the node by the React tree
  17. 66

  18. 67 ✓ Allow to use great React components where it’s

    useful ✓ Do not add unnecessary complexity ✓ 100% compatible with Symfony Forms, HTTP, default browser behaviors, ...
  19. 70 ✓ HTML5 is scoped: data concerning a node is

    stored as attributes of the node ✓ HTML5 is semantic: many use cases are already considered in the standard ✓ HTML5 is flexible: you can add your own attributes
  20. 71 {# index.html.twig #} {% extends 'base.html.twig' %} {% block

    body %} <div> Hello world <div data-color-chooser data-color-chooser-type="circles"> <input type="text" placeholder="Color in hexadecimal" /> </div> </div> {% endblock %} Option which could be coming from a Twig variable
  21. 72 // app.js // ... $('div[data-color-chooser]').each((key, node) => { const

    input = $(node).find('input'); ReactDOM.render( <ColorChooser type={node.getAttribute('data-color-chooser-type')} color={input.val()} onColorChange={(color) => input.attr('value', color)} />, node ); }); Using the option from the data attribute is easy because it’s scoped to the node
  22. 73

  23. 74 ✓ Easy to use (scoped and accessible in the

    appropriate Javascript context) ✓ Compatible with Content Security Policy ✓ Easy automatic testing
  24. 78 Do not develop an API if you don’t need

    it! Keep things as simple as possible
  25. 81 HTML contains data, in a structured way, and is

    already made to be displayed by the browser
  26. 83 Turbolinks A tiny library which replace links in your

    application with AJAX calls to switch the HTML on the fly
  27. 86 ✓ Same “no-refresh” effect as SPA ✓ Fully compatible

    with browser history, sessions, cache, … ✓ Better SEO (HTML rendered on the server) ✓ No added complexity over traditional Symfony apps