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.

weaverryan

June 16, 2023
Tweet

More Decks by weaverryan

Other Decks in Technology

Transcript

  1. @weaverryan
    With your friend Ryan Weaver
    Modern UIs with UX,


    a little JS & Zero Node

    View full-size slide

  2. > 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

    View full-size slide

  3. Your new Build System:


    Your browser
    Part 1
    @weaverryan

    View full-size slide

  4. export default class {


    constructor(name) {


    this.name = name;


    }


    quack() {


    console.log(`${this.name} says: Quack!`);


    }


    }
    public/duck.js

    View full-size slide

  5. import Duck from './duck.js';


    const duck = new Duck('Waddles');


    duck.quack();
    public/app.js
    This just works!

    View full-size slide

  6. All browsers now support
    import, ES6 class syntax,
    etc**
    ** Ok, not IE11, but that is less than 0.5%!

    View full-size slide

  7. So then… why do I need
    ANY tools?

    View full-size slide

  8. Two Problems
    1) Versioned Filenames
    2) Importing 3rd Party Packages

    import 'https://cdn.jsdelivr.net/npm/[email protected]/+esm';

    View full-size slide

  9. Hello AssetMapper


    (Experimental in 6.3)
    Part 2
    @weaverryan

    View full-size slide

  10. Asset Mapper Part #1 of 2:


    Exposing & Versioning Assets
    @weaverryan

    View full-size slide








  11. If my photo updates, my
    fi
    lename will update
    automatically!"

    View full-size slide

  12. 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

    View full-size slide

  13. Asset Mapper Part #2 of 2:


    Importmap
    @weaverryan

    View full-size slide

  14. How can we use 3rd party
    packages?
    @weaverryan

    View full-size slide

  15. import { Alert } from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm';


    const alert = new Alert(element);
    This works
    Yikes!

    View full-size slide

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


    import { Alert } from 'bootstrap';


    const alert = new Alert(element);

    View full-size slide

  17. return [


    'app' => [


    'path' => 'app.js',


    ],


    'bootstrap' => [


    'url' => 'https://cdn.jsdelivr.net/npm/[email protected]/+esm',


    ],


    ];


    importmap.php

    View full-size slide

  18. {% block javascripts %}


    {{ importmap() }}


    {% endblock %}
    base.html.twig
    {<br/><br/><br/>"imports": {<br/><br/><br/>"app": "/assets/app-4e986c1a2318dd050b1d47db8d856278.js",<br/><br/><br/>"bootstrap": "https://cdn.jsdelivr.net/npm/[email protected]/+esm"<br/><br/><br/>}<br/><br/><br/>}


    View full-size slide

  19. import hljs from 'highlight.js/lib/core';

    View full-size slide

  20. What about CSS?
    @weaverryan

    View full-size slide

  21. /* assets/styles/app.css */


    body {


    background: skyblue;


    }


    .quack {


    background-image: url('../images/duck.png');


    }
    {% block stylesheets %}





    {% endblock %}

    View full-size slide

  22. 3rd Party CSS?
    @weaverryan

    View full-size slide



  23. rel="stylesheet"


    href="https://cdn.jsdelivr.net/npm/bootstrap/dist/css/bootstrap.min.css"


    >
    Not as smooth, but documented
    Or download into assets/vendor/, include & commit.

    View full-size slide

  24. 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)

    View full-size slide

  25. Does it combine and
    minify the assets?

    View full-size slide

  26. No!


    By Design! Yay!

    View full-size slide

  27. 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.

    View full-size slide

  28. Part 3
    Turbo: You're Handier


    Than I Thought
    @weaverryan

    View full-size slide

  29. Create rich frontends while minimizing
    the need for custom JavaScript
    Goal
    ✅ Asset Mapper: Ciao node!
    s
    Turbo + Sprinkle of Stimulus
    square
    Live Components

    View full-size slide

  30. https://bit.ly/30-days-hotwire

    View full-size slide

  31. Need:


    Even MORE demos on ux.symfony.com
    @weaverryan

    View full-size slide

  32. @weaverryan
    Part 4
    Symfony UX:


    2.8 & 2.9

    View full-size slide

  33. Symfony UX 2.8
    @weaverryan

    View full-size slide

  34. Two New Components
    symfony/ux-translator
    symfony/ux-svelte
    import { trans, NUM_OF_APPLES } from '../translator';


    trans(NUM_OF_APPLES, {


    apples: 2


    })

    View full-size slide

  35. Live Components
    * Smart Rendering System



    * Communication between components: emit()

    * First class data serializing & invalid data handling


    * … lot's more!

    View full-size slide

  36. New Demos:


    ux.symfony.com/live-components
    @weaverryan

    View full-size slide

  37. HTML Twig Syntax
    {% component Alert {


    type: 'success',


    closeable: allowClose


    } %}


    {% block body %}Quack!{% endblock %}


    {% endcomponent %}


    View full-size slide

  38. HTML Twig Syntax


    type="success"


    :closeable="allowClose"


    >


    Quack!



    View full-size slide

  39. Symfony UX 2.9
    @weaverryan

    View full-size slide

  40. UX 2.9
    StimulusBundle
    AssetMapper Support!
    {{ stimulus_* }} functions moved out of
    WebpackEncoreBundle and into StimulusBundle.

    View full-size slide

  41. Yes, this means you can use Chart.js,
    LiveComponents, Autocomplete, etc
    entirely by writing PHP (no node!)

    View full-size slide

  42. #[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;


    }


    }

    View full-size slide




  43. How many slices?





    {{ render_chart(this.chart) }}





    View full-size slide

  44. We've come a long way…


    @weaverryan

    View full-size slide

  45. Symfony Cat Barcelona 2016

    View full-size slide

  46. That's no longer a given!
    @weaverryan

    View full-size slide

  47. Browsers
    Importmaps, import, ES6
    features
    HTTP/2 Requests download in parallel
    AssetMapper Asset versioning + Extra DX

    View full-size slide

  48. 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

    View full-size slide

  49. Hotwire: HTML over the Wire


    Alternative Path
    HTML in templates , 0 Node , low custom JS

    View full-size slide

  50. AssetMapper ❌ build system / node
    Symfonycasts tutorial coming this month!

    View full-size slide

  51. Turbo
    Remove full page


    reloads & more*
    https://bit.ly/30-days-hotwire
    SymfonyCasts.com/turbo

    View full-size slide

  52. Stimulus
    A sprinkle of


    custom JavaScript
    SymfonyCasts.com/stimulus
    🧁

    View full-size slide

  53. LiveComponents
    Swiss-Army Knife:


    Make your Twig templates
    reload live on the site.
    🗡
    Symfonycasts tutorial coming soon!

    View full-size slide

  54. Thank you!
    @weaverryan
    Symfony UX


    ux.symfony.com
    Turbo Tutorial


    symfonycasts.com/screencast/turbo
    Stimulus Tutorial


    symfonycasts.com/screencast/stimulus

    View full-size slide