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

The Rails 6 Front End: Building with Webpacker and Stimulus

The Rails 6 Front End: Building with Webpacker and Stimulus

Sometimes you need to have something happen in the browser. You don’t need a Single Page App, but you do want some client-side interactions. Rails 6 has great tools for simplifying the complex JavaScript ecosystem. We’ve got Webpacker, the default asset pipeline for JavaScript tooling, and Stimulus, a small library from Basecamp that brings Rails convention over configuration to JavaScript tools. As a result, it’s easier than ever to build user interactions with Rails-friendly tools. In this hands-on workshop, you’ll take a simple Rails app, and use Webpacker and Stimulus to add some front-end flair. No prior knowledge of Webpack or Stimulus is required.

Noel Rappin

April 29, 2019
Tweet

More Decks by Noel Rappin

Other Decks in Technology

Transcript

  1. Let's make sure everybody is on board 1. https://github.com/noelrappin/rails_conf_north_by 2.

    bundle install 3. yarn install 4. rails server -> http://localhost:3000/schedule 5. The toggle buttons should not work 6. http://bit.ly/workshop_snippets Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  2. Rails 6, Webpacker, and Stimulus Noel Rappin (@noelrap) http://www.tablexi.com http://techdoneright.io

    http://www.noelrappin.com Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  3. We are going to • Walk-through adding a stimulus feature

    • talk about webpack and webpacker • see where we are on time • work together to add more stimulus code Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  4. Some ground rules: Noel Rappin | Rails 6, Webpacker, and

    Stimulus | RailsConf 2019 | @noelrap
  5. Feel free to ask questions Noel Rappin | Rails 6,

    Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  6. Pair... if you are comfortable doing so Noel Rappin |

    Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  7. Everybody knows that the best way to learn is under

    intense, life- threatening pressure! Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  8. We have a Rails app Noel Rappin | Rails 6,

    Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  9. We want to improve the user experience Noel Rappin |

    Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  10. But we don't need a single page app Noel Rappin

    | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  11. There are a lot of Questions Noel Rappin | Rails

    6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  12. Logistics: How to convert our code into something nice that

    we can send to the browser Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  13. Structure: What's a good structure for non- SPA JavaScript interactions

    Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  14. "A Modest JavaScript Framework for the HTML you already have"

    Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  15. Stimulus has four basic concepts Noel Rappin | Rails 6,

    Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  16. Controllers Actions Targets Data Maps Noel Rappin | Rails 6,

    Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  17. A controller is where Stimulus code is executed Noel Rappin

    | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  18. A controller is associated with an HTML Element Noel Rappin

    | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  19. The controller is active across that element and its children

    Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  20. Let's create a controller! Noel Rappin | Rails 6, Webpacker,

    and Stimulus | RailsConf 2019 | @noelrap
  21. All the stuff to enter in this section is in

    http://bit.ly/ workshop_snippets Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  22. The code for the controller exists in app/javascript/ controllers/ toggle_controller.js

    Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  23. import { Controller } from "stimulus" export default class extends

    Controller { connect() { console.log("The Controller is Connected") } } Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  24. Reload the page Noel Rappin | Rails 6, Webpacker, and

    Stimulus | RailsConf 2019 | @noelrap
  25. You'll see in the log [Webpacker] Compiling… Noel Rappin |

    Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  26. And the message in the console Noel Rappin | Rails

    6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  27. An element can have multiple controllers Noel Rappin | Rails

    6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  28. A controller can be instantiated multiple times Noel Rappin |

    Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  29. Actions are associated with an HTML element Noel Rappin |

    Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  30. An action associates an arbitrary event to a controller method

    event->controller#method Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  31. When the event happens, Stimulus dispatches to the controller method

    Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  32. The HTML element must be within the controller being referenced

    Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  33. A Target is an HTML element of interest to a

    controller Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  34. Targets are associated with an HTML element Noel Rappin |

    Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  35. And then are registered with the controller: static targets =

    ["thingToHide"] Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  36. Targets make it easy to look up elements of interest

    You get: • this.thingToHideTarget • this.thingToHideTargets • this.hasThingToHideTarget Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  37. Let's update our action Noel Rappin | Rails 6, Webpacker,

    and Stimulus | RailsConf 2019 | @noelrap
  38. A Data Map allows you to associate data with a

    controller Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  39. Data maps belong to the controller data-controllername-key • get(key) •

    has(key) • set(key, stringValue) • delete(key) Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  40. If we add another target: <span data-target="toggle.text">Hide</span> Noel Rappin |

    Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  41. We can glue it all together Noel Rappin | Rails

    6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  42. import { Controller } from "stimulus" export default class extends

    Controller { static targets = ["text", "thingToHide"] hidden() { return this.data.get("hidden") === "true" } flip() { this.data.set("hidden", this.hidden() ? "false" : "true") } toggle() { this.flip() this.thingToHideTarget.classList.toggle("is-hidden", this.isHidden()) this.textTarget.innerText = this.isHidden() ? "Show" : "Hide" } } Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  43. Stimulus Cheatsheet Item Attribute Value Naming Controller data-controller controller-name Action

    data-action event->controller- name#methodName Target data-target controller- name.targetName Data Map data-controller-name- attribute value as string Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  44. How does this all work? Noel Rappin | Rails 6,

    Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  45. At compile, webpack loads all controllers import { Application }

    from "stimulus" import { definitionsFromContext } from "stimulus/webpack-helpers" const application = Application.start() const context = require.context("controllers", true, /_controller\.js$/) application.load(definitionsFromContext(context)) Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  46. On page load, Stimulus detects the data-controller attributes and instantiates

    new controller instances. Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  47. Stimulus also finds all the actions and sets up event

    listeners Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  48. When the event is triggered, the stimulus listener sends control

    to the method. Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  49. In the method, Stimulus generates the data and target properties

    Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  50. Low Overhead Easy to follow Noel Rappin | Rails 6,

    Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  51. Removes a lot of boilerplate event listeners Noel Rappin |

    Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  52. Makes it easy to write small modular effects Noel Rappin

    | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  53. Great at handling dynamic changes to the page. Noel Rappin

    | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  54. Why not Stimulus? Noel Rappin | Rails 6, Webpacker, and

    Stimulus | RailsConf 2019 | @noelrap
  55. No support for router/ SPA Noel Rappin | Rails 6,

    Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  56. Not super-helpful if there's a lot of state, or controlled

    access to state. Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  57. Let's talk about: Webpack and Webpacker Noel Rappin | Rails

    6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  58. When executing our code: Noel Rappin | Rails 6, Webpacker,

    and Stimulus | RailsConf 2019 | @noelrap
  59. Our code knew how to find other modules via include

    Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  60. The browser got all of our individual files in one

    pack Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  61. Our changes were automatically compiled on page reload. Noel Rappin

    | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  62. Webpack's mission in life: Noel Rappin | Rails 6, Webpacker,

    and Stimulus | RailsConf 2019 | @noelrap
  63. "At its core, webpack is a static module bundler for

    modern JavaScript applications. Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  64. Entry Output Loaders / Plugins Noel Rappin | Rails 6,

    Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  65. Entry: A file. Often JavaScript. Usually referencing other files in

    use. Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  66. Webpack uses entry points to build a "dependency graph" Noel

    Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  67. Output: where the bundle ends up Often the code is

    turned into a single file. Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  68. Loaders: transform files add them the graph Noel Rappin |

    Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  69. For Example: TypeScript compiler CSS Loader File loader Noel Rappin

    | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  70. Webpacker's mission in life Noel Rappin | Rails 6, Webpacker,

    and Stimulus | RailsConf 2019 | @noelrap
  71. Webpacker provides Useful defaults Makes some behavior easier to override

    Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  72. Webpacker is the default for new Rails 6 apps Noel

    Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  73. It has default configs for • Angular • Coffeescript •

    Elm • Erb Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  74. It has default configs for • React • Stimulus •

    TypeScript • Vue Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  75. What are the defaults? Noel Rappin | Rails 6, Webpacker,

    and Stimulus | RailsConf 2019 | @noelrap
  76. Any file in application/ javascript/packs is considered an entry point

    for a pack Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  77. Using javascript_pack_tag or stylesheet_pack_tag adds the pack to a page

    Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  78. Program note: If you have both JS and CSS in

    the same pack, import them both in the same .js file, and use both javascript_pack_tag and stylesheet_pack_tag to load them Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  79. Rails automatically compiles when you hit a page in development

    Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  80. Or you can use webpack-dev-server Noel Rappin | Rails 6,

    Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  81. Which compiles on change Noel Rappin | Rails 6, Webpacker,

    and Stimulus | RailsConf 2019 | @noelrap
  82. And live reloads Noel Rappin | Rails 6, Webpacker, and

    Stimulus | RailsConf 2019 | @noelrap
  83. Let's build a different date filter Noel Rappin | Rails

    6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  84. If no dates have been clicked, all dates show If

    any dates have been clicked, only clicked dates show Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  85. What do we need? Noel Rappin | Rails 6, Webpacker,

    and Stimulus | RailsConf 2019 | @noelrap
  86. • Controller • Action for each date • Action for

    show all • Targets for each date body • Data for current state Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  87. put the controller in the HTML Noel Rappin | Rails

    6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  88. Add the targets and starting data Noel Rappin | Rails

    6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  89. Add the action Noel Rappin | Rails 6, Webpacker, and

    Stimulus | RailsConf 2019 | @noelrap
  90. Add the show all action Noel Rappin | Rails 6,

    Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  91. Webpack and Webpacker are there to help you write your

    code the way you want... Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  92. And deliver it to the browser as needed Noel Rappin

    | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap
  93. Stimulus is great for small JS interactions that aren't SPA

    worthy Noel Rappin | Rails 6, Webpacker, and Stimulus | RailsConf 2019 | @noelrap