digitallyinduced / ihp

🔥 The fastest way to build type safe web apps. IHP is a new batteries-included web framework optimized for longterm productivity and programmer happiness
https://ihp.digitallyinduced.com/
MIT License
4.94k stars 196 forks source link

Polishing the front-end experience #1502

Open wout opened 2 years ago

wout commented 2 years ago

Coming from Rails and Lucky, the front-end experience of IHP feels a bit dated. With talks about a v1.0 tag (#1501), I would like to propose a few changes to bring it into 2022.

jQuery (-> Stimulus?)

jQuery has been a great tool, but with modern JS, I think it is unnecessary. Vanilla JS should be sufficient, but having Stimulus as an alternative would be great. It would be a perfect match for IHP.

Build tools

I'm using the ESBuild setup (as described in the React tutorial) instead of the standard IHP setup, and I think it's pretty great. It's lean and does everything I expect it to do (CSS and JS).

I've also used Vite before in other projects, which could be an option. I know Lucky Framework is considering Vite over their original Webpack setup at the moment.

Usage of data attributes for behaviour (instead of class names)

This is again personal. Currently, class names are used for js-delete, date-time and time-ago, to name a few. It's not always clear which class names are for styling and which add behaviour.

Perhaps the data-behavior attributes (Rails community) could be used instead. for example:

Another option could be using named data attributes:

kodeFant commented 2 years ago

esbuild sounds like a good default approach.

Phoenix framework uses esbuild and I like the rationale used here. One advantage is that npm/node.js is opt-in https://fly.io/blog/phoenix-moves-to-esbuild-for-assets/ https://hexdocs.pm/phoenix/asset_management.html#removing-esbuild

I quit using Turbolinks some time ago. And I don't really feel I lost anything substantial of value by removing it. Considering the problems it also brings, I think maybe it could be opt-in. And maybe the newer Hotwire/Turbo would be a better opt-in? 🤷‍♂️

Also, DataSync library could maybe be bundled in with IHP? Currently installing it via npm is a bit confusing as it's kind of hard to know if one is using an updated version. I also had troubles installing it with Parcel, but works well in esbuild btw.

I personally always delete jquery and bootstrap. But they are also easy to remove, so if many find value in having them, I have no issue with it 🙂

wout commented 2 years ago

esbuild sounds like a good default approach.

I agree. I've been using esbuild for a few days now, and it's pretty great. I like that it can also process CSS without any additional configuration.

Chris Oliver did a great video about esbuild in Rails, which may be useful as a reference: https://gorails.com/episodes/esbuild-jsbundling-rails

And maybe the newer Hotwire/Turbo would be a better opt-in?

I think making those libraries opt-in would be the right approach. I've never had any trouble with Turbolinks, and I'll probably keep it. But it may as well be opt-in for consistency, and because front-end preferences can vary significantly between devs.

I personally always delete jquery and bootstrap.

Same here. :)

stephenbenedict commented 2 years ago

Part of the attraction of IHP to me is that tooling/configuration is minimal, so I prefer IHP’s current manner of not including JS/CSS build tools, even though esbuild looks better than most.

Regarding default JS/CSS libaries to include, I would be in favor of including just what is necessary for live reload functionality.

Everything else should, in my opinion, be opt-in. By opt-in, I mean just recommendations and links in the docs, not separate IHP builds; it’s easy to understand <script src="..."></script> but not, e.g., passing in special flags to an ihp-new command.

On that note, I found turbolinks/morphdom problematic as well, so I switched to HTMX which works well. Since it is easy to enable or disable selectively, it is easy to avoid conflicts with other libraries or custom view logic as well.

If the current JS libraries continue to be included by default, I think there needs to be more documentation about the various functions each of those JS libraries offer.

For example, you can’t remove morphdom if you want to use IHP’s live reload JS script which depends on it.

Also, what js-delete does is not explicitly explained in the docs. So I was caught off guard when I removed helpers.js and found that my logout links/forms did not work (they require a hidden field that that script adds automatically).

kodeFant commented 1 year ago

Part of the attraction of IHP to me is that tooling/configuration is minimal, so I prefer IHP’s current manner of not including JS/CSS build tools, even though esbuild looks better than most.

I agree with this.

I would like to propose esbuild under the hood (added just as a nix dependency in the ihp lib) for the bundling step to add minification for prod.js and prod.css. I think minification after the concatenation would instantly add a little value for everyone and add yet another reason for not resorting to extra tooling. It does not need to be esbuild, but it's very accessible as a nix package and works with both js and css.

On that note, I found turbolinks/morphdom problematic as well, so I switched to HTMX which works well. Since it is easy to enable or disable selectively, it is easy to avoid conflicts with other libraries or custom view logic as well.

I have myself switched from Elm to htmx/hyperscript and removed npm on Shipnix. I can attest to it being liberating. I feel confident that the js will be working if I return to the project 2 years later. I can't see myself spinning up an SPA island again unless it's the last resort.

Everything else should, in my opinion, be opt-in. By opt-in, I mean just recommendations and links in the docs, not separate IHP builds

I think I agree on this. Maybe just a basic css file, possibly a CSS reset, or some classless css starter. It would be awesome to be able to bootstrap different sets for quick-starting a project though, like the current bootstrap/turbolinks/jquery and htmx/hyperscript in an ideal world, but maybe people can just make their own Github templates.

I have also ditched Tailwind for future projects now. Starting to grow fond of classless, or almost classless css frameworks. Currently using missing.css (also maintained by the htmx people in a new project). It's one of those classless css frameworks (but with a couple of high-power css utilties and a little optional js). You can just write html and barely need to style MVP.

When you later need styling, just use regular CSS and no problem overriding things unlike in Bootstrap where you need to use SASS or override with important!

stephenbenedict commented 1 year ago

I think I agree on this. Maybe just a basic css file, possibly a CSS reset, or some classless css starter. It would be awesome to be able to bootstrap different sets for quick-starting a project though, like the current bootstrap/turbolinks/jquery and htmx/hyperscript in an ideal world, but maybe people can just make their own Github templates.

Maybe a good balance would be having 2 builds:

  1. A "plainkit" build that has no included CSS or predefined controllers or views. This would be for those who are already familiar with IHP and/or don't want any scaffolding.
  2. A "starterkit" build which includes a sample controller with views (and some simple CSS; classless or similar would be my preference as well) which includes code annotation as well. This would be for first-timers who want to get a big picture of how everything works, as well as for the people that you described (those who want to bootstrap something quickly).

Basically what Kirby CMS does: https://getkirby.com/try

I have also ditched Tailwind for future projects now. Starting to grow fond of classless, or almost classless css frameworks. Currently using missing.css (also maintained by the htmx people in a new project). It's one of those classless css frameworks (but with a couple of high-power css utilties and a little optional js). You can just write html and barely need to style MVP.

If you like missing.css, you might like Mdash (I mentioned it before on Slack so maybe you already know of it). I have been using that on all of my recent projects that need admin interfaces and have been able to avoid writing any CSS. It strikes a nice balance between classless and utility classes.

kodeFant commented 1 year ago

Had not heard of Mdash before, but yeah I really like this 👍 so little baggage and docs are simple.

You basically just need html and IHP to be productive, and a couple of utility classes that are easy to memorize. Great for beginners and all kinds MVP-ers alike!

Does Mdash play well with current IHP code generation also ?

Also, do you use htmx hx-boost in place of Turbolinks?

kodeFant commented 1 year ago

AutoRefresh triggers a turbolinks:load event btw, so you can use something like this to force htmx to re-evaluate after a refresh.

document.addEventListener("turbolinks:load", (e) => {
  // Re-evaluate htmx code
  htmx.process(document.body);
  // Re-evaluate hyperscript code
  _hyperscript.processNode(document.body);
});
stephenbenedict commented 1 year ago

The only annoyance I experience using Mdash within IHP is related to what you helped me figure out on Slack, regarding writing spread values for HTML attributes, like:

 {...[ ("data-my-attribute" :: Text, "Hello World!" :: Text) ]}

Even though most of the Mdash components don't require custom attributes to work, when you have to, this syntax is a little ungainly and I always forget how to write it.

Otherwise, I haven't run into any issues. For the formFor function, the only thing I need to change is adding <fieldset> around inputs.

And thank you for the tip regarding the AutoRefresh trigger. Good to know.

stephenbenedict commented 1 year ago

As far as the generated views, they have some styling specific to Bootstrap (like breadcrumbs), so I do have to remove or change those.

kodeFant commented 1 year ago

As far as the generated views, they have some styling specific to Bootstrap (like breadcrumbs), so I do have to remove or change those.

You can actually overwrite the underlying CSS framework so for example the breadcrumbs works the way you want. This is one I created for missing.css:

https://gist.github.com/kodeFant/279029af06ec103439712d3296bc53d7

With this you can add this config as an option in the Config.hs

module Config where

import IHP.Prelude
import IHP.Environment
import IHP.FrameworkConfig
import Web.View.CustomCSSFramework

config :: ConfigBuilder
config = do
    -- See https://ihp.digitallyinduced.com/Guide/config.html
    -- for what you can do here
    option customMissing
    pure ()
stephenbenedict commented 1 year ago

I did not realize that was possible! Thank you. I will probably put something like that together for Mdash.

geofflangenderfer commented 1 year ago

any example repos using ihp + htmx?