Refactoring a Rails App to use Components
Early last year we wanted to overhaul the user interface of our app. I was keen to improve the structure of the app and ensure that the code became more readable and maintainable - at that point the app was about 6 years old and some of the view code had become overly complex and hard to follow.
Komponent is a rails gem that provides a way of structuring and managing your front-end code in a component-based manner. It uses Rails view_contexts and webpack configuration to allow you to create rails view components.
/frontend directory in the root of your application. So you end up with a directory structure somehting like below:
Components can have blocks passed to them, can be nested, and the ruby module can be used to define properties of the component, giving them default values or making them required as necessary. You can define methods as required within the module to have computed properties, or to extract logic out of the view partial.
There's no enforced namespacing of the css, but it is trivial to implement, keeping all the styles for the component self-contained.
We chose to pair this setup with Tailwind a utility-first css libary, which works excellently in this component based setup, meaning each component has very minimal styles defined in it's stylesheet.
Using your component in a rails view is as easy as using the
component helper method.
<%= c("button", label: "My Button") %>
Oh, and did you spot that
_examples.html.erb file in the directory tree above? Komponent can also generate a styleguide for you. So you can provide examples and usage docuemntation alongside your components.
Taken all together komponent is a great way to organise and structure your rails front-end code. It provides all the benefits of components, while keeping all the rails conventions you're used to.
If you're interested in implementing this into your app, check out my follow up posts:
- Modern Front End in Rails - A series of articles building out a setup similar to komponent from scratch. Great for understandoing what's going on behind the scenes.
- How we develop design components in rails - A post from Betterment engineering on a similar solution they built.
A while ater I had started imlpementing this in our app I watched this talk from RailsConf 2019 where Joel Hawksley from Github, demos a very similar Component based system by creating an
ActionView::Component class. This is apparently being pushed upstream, so could get incorpoarted into Rails, which would be great. It doesn't address the structuring of files, and co-locating css and js files along with the component in the same way as Komponent does, but it's still a great improvement on standard view partials.
[Update Feb 2020]
Excited to see this tweet from @dhh where he says he mentions a "new paradigm for the front-end" in Rails that basecamp have extracted from their new service hey that he's going to be talking about at RailsConf this year. 🤞 for it being some combination of what Github have been doing and Komponent!
ActionView::Component mentioned above is not being upstreamed into Rails itself, it is being renamed to
ViewComponent to reflect this. See this github issue thread for more details and discussion around these ideas of components in Rails.
Part of me wonders whether the reason
ViewComponent is not being upstreamed, is related to that tweet from dhh, and that there were similar ideas from both the basecamp and github teams. We'll have to wait and see…