Slide 1

Slide 1 text

Pragmatic frontend for Symfony developers Titouan GALOPIN

Slide 2

Slide 2 text

2 Titouan Galopin Product Manager SymfonyInsight insight.symfony.com

Slide 3

Slide 3 text

3 The Why

Slide 4

Slide 4 text

4 Why is frontend development so complex?

Slide 5

Slide 5 text

5 Thinking about modern software architectures requires frontend choices

Slide 6

Slide 6 text

6 Let’s discuss!

Slide 7

Slide 7 text

Agenda 1. A bit of history 2. Modern frontend 3. The least complex technology possible 4. Approaches to frontend with Symfony 7

Slide 8

Slide 8 text

8 1. A bit of history

Slide 9

Slide 9 text

9 1990–1995 HTML, CSS and JavaScript are invented

Slide 10

Slide 10 text

10 1996–1999 Standardization efforts begin Browser compliance is terrible

Slide 11

Slide 11 text

2000–2004 CSS frameworks begin to emerge jQuery is born 11

Slide 12

Slide 12 text

2005–2009 W3C specification is met Responsive designs and frameworks introduced 12

Slide 13

Slide 13 text

13 2010–2015 JS frameworks are born (Backbone, Ember, Angular, React, Vue, ...) HTML5 is announced

Slide 14

Slide 14 text

14 2016–2020 New technologies and platforms built around modern frontend emerge: GraphQL, Service Workers, Cordova, Electron, React Native, …

Slide 15

Slide 15 text

15 Modern frontend development is a direct consequence of this history

Slide 16

Slide 16 text

16 What is Modern Frontend?

Slide 17

Slide 17 text

17 2. Modern frontend

Slide 18

Slide 18 text

18 Modern frontend is supposed to be about user experience

Slide 19

Slide 19 text

19 “Nowadays, users expect more from websites (performance, help, productivity, …)”

Slide 20

Slide 20 text

20 Ever wondered whether a loader was actually loading or was broken?

Slide 21

Slide 21 text

21 Ever been frustrated about a Back button click returning to the wrong page?

Slide 22

Slide 22 text

22 Ever been disappointed by a link you couldn’t open in a new tab?

Slide 23

Slide 23 text

23 Ever been angered by a website you couldn’t open in multiple tabs without messing with the data?

Slide 24

Slide 24 text

24 Ever had to disable your adblocker to make a website work?

Slide 25

Slide 25 text

25 Ever had to use a screen reader on a full Javascript interface?

Slide 26

Slide 26 text

26 Full-page apps (for instance create-react-app) is not an answer to the UX problem

Slide 27

Slide 27 text

27 It’s easy to do it really wrong and hurts UX a lot

Slide 28

Slide 28 text

28 Modern frontend != Full-page app

Slide 29

Slide 29 text

29 Full-page app is a solution to a different problem

Slide 30

Slide 30 text

30 How to build a website and a mobile application with the same backend?

Slide 31

Slide 31 text

31 3. The least complex technology possible

Slide 32

Slide 32 text

How many times did you experience PHP failing between a function call and the first line of the function? 32

Slide 33

Slide 33 text

How many times did you experience an AJAX call failing between the request and the response? 33

Slide 34

Slide 34 text

34 The network is a huge source of complexity

Slide 35

Slide 35 text

How many times did you develop your own session system in PHP? 35

Slide 36

Slide 36 text

How many times did you develop your own session history stack in PHP? 36

Slide 37

Slide 37 text

37 Not using the features of the browser is a source of complexity

Slide 38

Slide 38 text

How many developers in your team know perfectly well both React and Symfony? 38

Slide 39

Slide 39 text

39 Dealing with backend vs with interfaces are two different jobs: human complexity

Slide 40

Slide 40 text

KISS Keep It Super Simple 40

Slide 41

Slide 41 text

By default, use the simplest option available Migrate to something more complex only if necessary 41

Slide 42

Slide 42 text

The simplest option = HTML + CSS built with PHP 42

Slide 43

Slide 43 text

But it’s sometimes not enough... 43

Slide 44

Slide 44 text

44 4. Approaches to frontend with Symfony

Slide 45

Slide 45 text

45 No JS Misses the real UX gain of Javascript, but still possible

Slide 46

Slide 46 text

46 Full-page app + API Has a lot of drawbacks but is the only option for multiple clients (web + mobile)

Slide 47

Slide 47 text

47 Progressive enhancement A pragmatic in-between

Slide 48

Slide 48 text

48 Most recent JS frameworks (React, Vue, …) can be used in limited parts of the page

Slide 49

Slide 49 text

49 What about using React only where it brings actual improvements?

Slide 50

Slide 50 text

50 Using React to enhance your Symfony application

Slide 51

Slide 51 text

51 1. Develop your application as usual

Slide 52

Slide 52 text

52 {# index.html.twig #} {% extends 'base.html.twig' %} {% block body %}
Hello world
{% endblock %}

Slide 53

Slide 53 text

53 {# index.html.twig #} {% extends 'base.html.twig' %} {% block body %}
Hello world
{% endblock %} This could be a Symfony Form field

Slide 54

Slide 54 text

54 2. Add React only where it’s useful

Slide 55

Slide 55 text

55 composer req --dev webpack yarn install https://symfony.com/doc/current/frontend.html

Slide 56

Slide 56 text

56 Webpack is a build tool It lets you manipulate your Javascript and CSS before using it in production (JSX, minification, …)

Slide 57

Slide 57 text

57 Webpack Encore wraps Webpack around a nice API to improve its Developer Experience

Slide 58

Slide 58 text

58 Webpack Encore is awesome to compile React apps to normal Javascript

Slide 59

Slide 59 text

59 yarn add @babel/preset-react react react-dom prop-types

Slide 60

Slide 60 text

60 // webpack.config.js Encore.enableReactPreset()

Slide 61

Slide 61 text

61 {# index.html.twig #} {% extends 'base.html.twig' %} {% block body %}
Hello world
{% endblock %} Marker to find where to inject a React component

Slide 62

Slide 62 text

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( input.attr('value', color)} />, node ); });

Slide 63

Slide 63 text

63

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

65 3. How to transfer data?

Slide 66

Slide 66 text

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; } }

Slide 67

Slide 67 text

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']), ]; } // ... }

Slide 68

Slide 68 text

68 {# base.html.twig #} Welcome! {% block body %}{% endblock %} {{- get_exposed_data()|json_encode|raw -}} {{ encore_entry_script_tags('app') }}

Slide 69

Slide 69 text

69 const data = JSON.stringify( document.getElementById('exposed-data') );

Slide 70

Slide 70 text

70 ✓ Easy to parse (JSON.stringify) ✓ Compatible with Content Security Policy ✓ Easy to use in automated testing

Slide 71

Slide 71 text

71 Conclusion

Slide 72

Slide 72 text

Thanks! 72 For any question: ▪ @titouangalopin on Twitter ▪ titouan.galopin @symfony.com