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

Modern UIs with UX, a little JS & Zero Node

Modern UIs with UX, a little JS & Zero Node

Ready to build a highly-interactive, modern UI? Me too! But hold up, do we really need to install Node & Webpack to pull this off? Not anymore! With PHP, Twig, and just a pinch of JavaScript magic, we can create something truly special.

In this talk, we'll embark on a journey using the new Symfony UX experience, one *without* Node and Webpack. We'll conquer common UI challenges like modals, notifications, and filterable tables, wielding the power of Turbo & Stimulus while writing minimal JavaScript.

For the grand finale, we'll tackle the most interactive situations using only PHP & Twig, thanks to the LiveComponents. With *huge* changes over the past few months, this is finally ready for the big leagues.


June 16, 2023

More Decks by weaverryan

Other Decks in Technology


  1. > Member of the Symfony docs team > Husband of

    the talented and beloved @leannapelham symfonycasts.com twitter.com/weaverryan Howdy there!! I’m Ryan! > Author person at SymfonyCasts.com
  2. export default class { constructor(name) { this.name = name; }

    quack() { console.log(`${this.name} says: Quack!`); } } public/duck.js
  3. All browsers now support import, ES6 class syntax, etc** **

    Ok, not IE11, but that is less than 0.5%!
  4. Two Problems 1) Versioned Filenames 2) Importing 3rd Party Packages

    <link href="/assets/app.1234.css"> import 'https://cdn.jsdelivr.net/npm/[email protected]/+esm';
  5. How… did that work? /assets/* is served by an internal

    Symfony listener dev: prod: Run php bin/console asset-map:compile to physically write all fi les into the public/assets/ directory /assets/images/duck-3c16d9220694.png
  6. ???

  7. Now this works ✅ import { Alert } from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm';

    import { Alert } from 'bootstrap'; const alert = new Alert(element);
  8. return [ 'app' => [ 'path' => 'app.js', ], 'bootstrap'

    => [ 'url' => 'https://cdn.jsdelivr.net/npm/[email protected]/+esm', ], ]; importmap.php
  9. {% block javascripts %} {{ importmap() }} {% endblock %}

    base.html.twig <script type="importmap">{ "imports": { "app": "/assets/app-4e986c1a2318dd050b1d47db8d856278.js", "bootstrap": "https://cdn.jsdelivr.net/npm/[email protected]/+esm" } }</script>
  10. /* assets/styles/app.css */ body { background: skyblue; } .quack {

    background-image: url('../images/duck.png'); } {% block stylesheets %} <link rel="stylesheet" href="{{ asset('styles/app.css') }}"> {% endblock %}
  11. Sass? Tailwind? ✅ (see docs about building) JSX, Vue, TypeScript?

    ❌ (actually, yes, but a build system may be better) Production Ready? ✅ (and performant) Works on all browsers? ✅ (except for ancient browsers, like IE 11)
  12. gzip/compress Assets Do it on your web server / Cloud

    fl are Combining Assets Not needed** Use an HTTP/2 powered web server / Cloud fl are ** not combining can even *help* performance: if a single fi le is changed, users will only need to download that one fi le.
  13. Create rich frontends while minimizing the need for custom JavaScript

    Goal ✅ Asset Mapper: Ciao node! s Turbo + Sprinkle of Stimulus square Live Components
  14. Two New Components symfony/ux-translator symfony/ux-svelte import { trans, NUM_OF_APPLES }

    from '../translator'; trans(NUM_OF_APPLES, { apples: 2 })
  15. Live Components * Smart Rendering System 
 * Communication between

    components: emit() 
 * First class data serializing & invalid data handling 
 * … lot's more!
  16. HTML Twig Syntax {% component Alert { type: 'success', closeable:

    allowClose } %} {% block body %}Quack!{% endblock %} {% endcomponent %}
  17. UX 2.9 StimulusBundle AssetMapper Support! {{ stimulus_* }} functions moved

    out of WebpackEncoreBundle and into StimulusBundle.
  18. #[AsLiveComponent()] class DonutChart { use DefaultActionTrait; #[LiveProp(writable: true)] public int

    $slices = 5; public function __construct( private ChartBuilderInterface $chartBuilder, ) { } public function getChart(): Chart { $chart = $this->chartBuilder->createChart('doughnut'); $chart->setData(...); return $chart; } }
  19. RIP Build Systems? React, Vue, Next.js, etc Tailwind / Sass

    TypeScript use their tools to build use its tools to build best served using their build system / a build system
  20. LiveComponents Swiss-Army Knife: Make your Twig templates reload live on

    the site. 🗡 Symfonycasts tutorial coming soon!