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

VILT Stack (DevTreff Amstetten)

VILT Stack (DevTreff Amstetten)

Christoph Hochstrasser

June 18, 2023
Tweet

More Decks by Christoph Hochstrasser

Other Decks in Programming

Transcript

  1. My Story Seit 2005 als Web Developer aktiv – Selbstständig

    seit 2014 – Standort: beta campus in Waidhofen a/d Ybbs – Spezialgebiet: Custom Web Apps für Firmen & Behörden – Tech: Laravel, Vue.js, Node.js, Nuxt, Electron –
  2. Agenda Challenges 1. Requirements 2. VILT Stack 3. Ge ing

    Started 4. How it works 5. Showcase 6. Summary 7.
  3. Challenge #1 “Projektgeschä ” Wir arbeiten nicht dauerha am selben

    Produkt, sondern entwickeln als Dienstleister:innen ständig verschiedenste Projekte weiter oder starten Neue.
  4. Challenge #2 Kleines Full-Stack Team An einem Projekt arbeiten 1–3

    Personen, aber meistens muss ich vieles in Frontend und Backend selbst machen.
  5. Challenge #3 “Kleine” Projekte mit großer Wirkung Projekte sind eher

    “klein”. Der Aufwand beträgt meistens “nur” 1–2 Monate pro Release.
  6. Challenge #4 API ist keine Anforderung Ein umfassendes API ist

    selten eine Anforderung in den Projekten. Warum sollen Kund:innen für etwas bezahlen, das sie nicht nutzen?
  7. Ich hab alle anderen Ansätze ausprobiert: SPA & REST API

    – SPA & GraphQL – Blade Templates & Vanilla JS/jQuery –
  8. Was wäre wenn… Und trotzdem: 1 Entwickler:in einfach ein komple

    es Feature bauen könnte – UI Framework und Backend Framework optimal integriert wären – URL Routing nur an einer Stelle passieren würde – Man mit einem bereits erlernten Framework (Laravel) arbeiten könnte inkl. ORM, Validation, DB Migrations usw. – Das Frontend komple aus reaktiven UI Components bestehen würde – Man Zugang zu einem riesigen Frontend Ecosystem hä e – Interactivity extrem einfach von der Hand gehen würde –
  9. V - Vue.js I - Inertia.js L - Laravel T

    - Tailwind (Unofficial) h ps://viltstack.dev/
  10. Vue.js Frontend & “Templating Language” – Jede Seite ist eine

    eigene Vue Component (z.B. Pages/User/Index.vue ) und erhält über Props die Daten vom Backend – Routing passiert im Backend, ohne Vue Router, in routes/web.php –
  11. Vue.js Page Component Options API: <!-- pages/Hello/Index.vue --> <script> import

    Layout from './Layout' import { Head } from '@inertiajs/vue3' export default { props: { person: Object, }, components: { Layout, Head } } </script> <template> <Layout> <Head title="Welcome" /> <h1>Welcome</h1> <p> Hello {{ person.firstname }}, welcome to your first Inertia app! </p> </Layout> </template> Composition API: <!-- pages/Hello/Index.vue --> <script setup> import Layout from './Layout' import { Head } from '@inertiajs/vue3' defineProps({ person: Object }) </script> <template> <Layout> <Head title="Welcome" /> <h1>Welcome</h1> <p> Hello {{ person.firstname }}, welcome to your first Inertia app! </p> </Layout> </template>
  12. Inertia.js Glue zwischen Frontend (Vue, React,…) & Backend (Laravel, Rails,…)

    – Backend Adapter Library – z.B. inertiajs/inertia-laravel – Frontend Adapter Library – z.B. @inertiajs/vue3 – Inertia Protocol sta API –
  13. Laravel // inertia() Helper Function Route::get('/hello/{person}', function (Person $person) {

    // -> resources/js/Pages/Hello/Index.vue return inertia('Hello/Index', [ 'person' => $person ]); }); // Alternative mit Facade use Inertia\Inertia; Route::get('/hello/{person}', function (Person $person) { return Inertia::render('Hello/Index', [ 'person' => $person ]); });
  14. Tailwind <div class="bg-gray-100 p-8 h-screen flex" > <div class="bg-white shadow-lg

    flex p-8 rounded-xl m-auto" > <h1 class="text-xl font-bold"> Hello {{name}}! </h1> </div> </div>
  15. Success!  Laravel App  Vite & HMR  Vue

    3  Inertia.js  Tailwind  Authentication Pages
  16. User Browser Backend Vue App wird initialisiert Inertia wird initialisiert

    Page Component wird erstellt App ist interaktiv Neue Component wird geladen ("Resolve") Component wird mit Props initialisiert Öffnet App GET: / HTML: <div id="app" data-page='{"component":"Index", "props": …}'></div> router.visit() GET /foo X-Inertia: true JSON: { "component": "Foo", "props": … } Form Submit POST /foo X-Inertia: true {"foo": "Bar"} JSON: { "component": "Foo", "props": … } User Browser Backend
  17. Erster Request Request: GET: http://example.com/events/80 Accept: text/html, application/xhtml+xml Response: HTTP/1.1

    200 OK Content-Type: text/html; charset=utf-8 Vary: X-Inertia <html> <head> <title>My app</title> <link href="/css/app.css" rel="stylesheet"> <script src="/js/app.js" defer></script> </head> <body> <div id="app" data-page='{"component":"Event","props":{"event":{"id":80,"title":"Birthday party","start_date":"2019-06-02","description":"Come out and celebrate Jonathan&apos;s 36th birthday party!"}},"url":"/events/80","version":"c32b8e4965f418ad16eaebba1d4e960f"}'></div> </body> </html>
  18. <script setup> import { Link, router } from '@inertiajs/vue3' const

    showEvent = (id) => { router.visit(`/events/${id}`) // or // router.get() // router.post() // router.put() // router.delete() }) </script> <template> <div> <Link href="/events/80"> Show Event </Link> <!-- Don't do this bc a11y (but it's possible): --> <button type="button" @click="showEvent(80)"> Show Event </button> </div> </template>
  19. Weitere Requests Request: GET: http://example.com/events/80 Accept: text/html, application/xhtml+xml X-Requested-With: XMLHttpRequest

    X-Inertia: true … Response: HTTP/1.1 200 OK Content-Type: application/json Vary: X-Inertia X-Inertia: true { "component": "Event", "props": { "event": { "id": 80, "title": "Birthday party", "start_date": "2019-06-02", "description": "Come out and celebrate Jonathan's 36th birthday party!" } }, "url": "/events/80", "version": "c32b8e4965f418ad16eaebba1d4e960f" }
  20. VILT ist perfekt geeignet für: “CRUD” Apps – Kleine Teams

    (ca. 1–5 Entwickler:innen) – Full-Stack Developer – Frontend & Backend sind komple gekoppelt –
  21. VILT ist weniger gut geeignet: Alles wo SEO eine Rolle

    spielt (SSR ist möglich, SSG ist nicht möglich) – Wenn ein umfassendes API ein wesentliches Feature ist – Wenn die Web App komple offline verfügbar sein soll – Wenn Frontend & Backend komple entkoppelt sein sollen – Große Teams & große Projekte, wo die Spezialisierung auf Frontend/Backend/uvm. sinnvoll ist –
  22. Pitfall Nr. 2 Model Serialization // Don't: return inertia('User/Index', ['user'

    => $user]); // Do this instead: return inertia('User/Index', [ 'user' => $user->only('id', 'firstname', 'lastname', 'email') ]);
  23. Pitfall Nr. 3 Frontend Form Initialization Forms müssen immer alle

    Properties des Models definieren, die bearbeitet werden
  24. In bestehende (Laravel) App integrieren Links: – h ps://inertiajs.com/server-side-setup –

    h ps://inertiajs.com/client-side-setup – h ps://inertiajs.com/the-protocol
  25. VILT in bestehende App integrieren Packages installieren # Frontend Adapter

    npm i -D @inertiajs/vue3 # Backend Adapter composer require inertiajs/inertia- laravel
  26. VILT in bestehende App integrieren Root Template <!DOCTYPE html> <html>

    <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> @vite('resources/js/app.js') @inertiaHead </head> <body> @inertia </body> </html>
  27. In eine bestehende Laravel App integrieren Middleware Middleware generieren: $

    php artisan inertia:middleware Middleware in Kernel registrieren: 'web' => [ // ... HandleInertiaRequests::class, ],
  28. VILT in bestehende App integrieren (mit Vite) Vue App import

    { createApp, h } from 'vue' import { createInertiaApp } from '@inertiajs/vue3' createInertiaApp({ resolve: name => { const pages = import.meta.glob('./Pages/**/*.vue', { eager: true }) return pages[`./Pages/${name}.vue`] }, setup({ el, App, props, plugin }) { createApp({ render: () => h(App, props) }) .use(plugin) .mount(el) }, }) (Webpack ist ebenfalls möglich)
  29. VILT Yay Meh Reactive Interactivity – Auth ist super einfach

    – Form Validation ist super einfach – Error Handling ist super einfach – Backend kann User Flow bestimmen – Serialization ist super einfach – Zugang zu awesome Backend Features – “Tight coupling” zwischen Backend & UI – Model serialization – Modals – SEO – SPA+API Yay Meh Reactive Interactivity – Entkoppelung zwischen Frontend & Backend – Offline Apps sind möglich – API Dogfooding – Full-Stack mühsam – Error Handling, Form Validation – API Auth ist Overkill wenn UI der einzige Client ist –