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

From Vue to Alpine: How & Why

From Vue to Alpine: How & Why

Every time we approach a new project at Tighten, we ask ourselves the question: Understanding the needs of this project, what’s the best frontend stack? Vue, React, Alpine? Livewire? SPA? Inertia?

However, we seldom change the tech stack on existing projects. In this talk I’ll cover how and why I’ve started converting some of our Vue sites to Alpine—and why you should consider it, too!

60187fe0ab07ea5a46572a3ab05f61dd?s=128

Matt Stauffer

June 10, 2021
Tweet

Transcript

  1. From VUE to ALPINE: HOW & WHY

  2. Back Story: THE JAVASCRIPT FRAMEWORKS FRAMEWORK

  3. TIGHTEN'S JAVASCRIPT DECISION MATRIX FRAMEWORK WHEN TO USE IT jQuery

    Never Vanilla JS Rudiments (simple toggles, hamburgers) Vue Single components, widgets, etc. Full page components & SPAs React SPAs, full page components
  4. WHY WE BASICALLY NEVER CONVERT FRAMEWORKS ON AN EXISTING PROJECT

  5. CAVEAT We'll always convert jQuery to something more modern if

    possible
  6. Where does Alpine fit for new builds?

  7. Where does Alpine fit for new builds? Story time!

  8. The CORE WEB VITALS

  9. None
  10. LARGEST CONTENTFUL PAINT

  11. FIRST INPUT DELAY

  12. CUMULATIVE LAYOUT SHIFT

  13. A QUICK INTRO to LIGHTHOUSE

  14. STORY TIME TIGHTEN.CO and the CORE WEB VITALS

  15. !

  16. SOURCES OF TROUBLE? ▸ Web Fonts ▸ Some old jQuery-based

    plugins ▸ A bit of other crap
  17. None
  18. None
  19. None
  20. Alpine to the rescue!

  21. ALPINE ❤ CORE WEB VITALS

  22. DOWNLOAD SIZE Vue1 33.7kB Alpine2 8.9kB 2 https://cdn.jsdelivr.net/npm/alpinejs@2.8.2/dist/alpine.min.js 1 https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js

  23. PROCESSING TIME, NO ACTUAL CODE ON PAGE:

  24. PROCESSING TIME, NO ACTUAL CODE ON PAGE:

  25. PROCESSING TIME, SIMPLE HAMBURGER

  26. NEW MATRIX Not just “what can each framework do” but

    “what can each do with the smallest payload”
  27. EXAMPLES

  28. CONVERTING A HAMBURGER MENU

  29. HAMBURGER MENU IN VUE

  30. <template> <button @click="toggle"> ! </button> <div v-show="show"> <ul><li>...</li></ul> </div> </template>

    <script> export default { data: { show: false }, methods: { toggle() { this.show ? this.close() : this.open(); }, open() { window.addEventListener('keydown', this.handleEscape); this.show = true; }, close() { window.removeEventListener('keydown', this.handleEscape); this.show = false; }, handleEscape(event) { if (event.code === 'Escape') this.close(); }, }, }; </script>
  31. HAMBURGER MENU IN ALPINE

  32. <div x-data="{ open: false }" x-on:keydown.escape.window="open = false"> <button @click="open

    = !open"> ! </button> <div x-show="open"> <ul><li>...</li></ul> </div> </div>
  33. CONVERTING A CONTACT MODAL

  34. CONTACT MODAL IN VUE

  35. <!-- Modal component --> <template> <div class="full-screen show" v-if="show"> <span

    class="full-screen__close" @click="close">&times;</span> <slot :close="close"></slot> </div> </template> <script> export default { props: { show: {} }, methods: { open() { window.addEventListener('keydown', this.handleEscape); }, close() { window.removeEventListener('keydown', this.handleEscape); }, handleEscape(event) { if (event.code === 'Escape') this.close(); }, }, // A watch handler for "show" }; </script>
  36. <!-- Contact Modal component--> <template> <modal> <template slot-scope="modal"> <label>Name</label><input v-model="form.name"

    name="name"> <label>Email</label><input v-model="form.email" name="email" type="email"> <button @click.prevent="submitForm">Submit</button> </template> </modal> </template> <script> import Modal from "./modal.vue"; export default { components: { Modal }, data() { return { form: { name: null, email: null } }; }, methods: { formIsValid() { /* Validate */ }, submitForm() { if (this.formIsValid()) axios(/* Post the form */); } } }; </script>
  37. CONTACT MODAL IN ALPINE

  38. Basic modal <div x-data="{ showModal: false }" @keydown.escape.window="showModal = false"

    > <button @click="showModal = true">Open Modal</button> <div x-show="showModal"> <div @click.away="showModal = false"> <button @click="showModal = false">X</button> <p>Content goes here</p> </div> </div> </div>
  39. Extract... <div x-data="modal()" @keydown.escape.window="showModal = false" > ... </div> <script>

    function modal() { return { showModal: false, } } </script>
  40. Extract further... <div x-data="modal()" x-spread="modalSpread"> ... </div> <script> function modal()

    { return { showModal: false, modalSpread: { ['x-on:keydown.escape.window']() { this.showModal = false; }, }, } } </script>
  41. Contact modal script <script> function contact_modal() { return { form:

    { name: null, email: null, }, formIsValid() { /* Validate */ }, submitForm() { if (this.formIsValid()) axios(/* Post the form */); }, } }
  42. Apply both modal and contact modal <div x-data="{...modal(), ...contact_modal()}" x-spread="{...modalSpread,

    ...contactModalSpread}" > <label>Name</label><input x-model="form.name" name="name"> <label>Email</label><input x-model="form.email" name="email" type="email"> <button @click.prevent="submitForm">Submit</button> </div>
  43. CONCLUSION

  44. WHEN I WOULD RECOMMEND MOVING FROM VUE to ALPINE ▸

    Hamburgers and toggles ▸ Modals and accordions ▸ Widgets ▸ Simple AJAX/Axios calls & forms ▸ “We’re using Vue because this is too complex for vanilla JS”
  45. WHEN I WOULDN'T RECOMMEND MOVING FROM VUE to ALPINE CAVEAT:

    YOU CAN USE ALPINE FOR MOST OF THESE, I JUST WOULDN’T RECOMMEND REWRITING ▸ Full page components ▸ Significant component nesting ▸ SPAs ▸ Most major dashboards
  46. YOUR NEXT STEPS Using Vue for minor JS because at

    least it's better than jQuery? Run Lighthouse. Then try Alpine.