Open serhiihiba opened 1 year ago
Nice, I like this idea! I've wanted to add it for a while now.
A few questions:
.wrapper_pvsbv6dH6Fdf4
because I personally find them hard to read. I wonder if we could prefix every class with the full constant name of the component, eg. .ui--mix--home--spacecraft-item-component > .ui--mix--home--spacecraft-item-component-wrapper > .ui--mix--home--spacecraft-item-component-avatar
. That's obviously a lot more verbose, but easier to understand when you see one of those names in the Chrome inspector, for example.Let me know your thoughts!
@camertron So cool you like my proposal! Hmm, i using Birdel to automate my assets sync before bundling. But it doesn't matter if you uses Birdel or writing that manually, result entrypoint file may looks something like this:
//app/assets/stylesheets/ui/entries/home/index.css
@import url("../../united/colors.css");
@import url("../../united/images.css");
@import url("../../../../../components/ui/mix/home/space_home_component/space_home_component.css");
@import url("../../../../../components/ui/mix/home/spacecraft_list_component/spacecraft_list_component.css");
@import url("../../../../../components/ui/mix/home/spacecraft_item_component/spacecraft_item_component.css");
Next, esbuild makes bundling for each entrypoint by config which may looks like this:
//package.json
"build:css": "esbuild app/assets/stylesheets/ui/entries/**/index.css --bundle --minify --outdir=app/assets/builds --outbase=app/assets/stylesheets --loader:.woff2=file --loader:.svg=file --external:app/assets/fonts/ui/* --external:app/assets/images/ui/*",
Or sometimes i can bundle some components styles too, it may help if you for example uses rails-turbo (which i personally don't like and uses Birdel instead) So last step is Propshaft uses that bundled entries (or/and bundled components css files) for assets delivery, that's why i can't answear about dart-sass, sprockets etc
About another gem - personally I more like including a module based on some config in project like .config.vcss = true
And about hashes - you are right, it may 100% better to see normally named css classes like .ui--mix--home--spacecraft-item-component_wrapper
while you develops app. But what about production? In rails is really problem is big bundle file, so if I could choose - I would definitely choose .wrapper_hb34JHG34
classes looking style for minimise my bundle
result entrypoint file may looks something like this:
Ah ok so you add them manually for each component. I wonder if there's a way to automate that? It would also be really cool if the page only requested the CSS it actually needed based on the components that have been rendered.
With regard to esbuild, propshaft, etc... it feels like automatic discovery of .css files might be hard to implement consistently for all these build systems. If the page only requests the component CSS it actually needs, maybe Sprockets would be the right build system to use.
About another gem - personally I more like including a module based on some config in project like
.config.vcss = true
I'm not sure what you mean, can you explain in more detail?
And about hashes ... But what about production? In rails is really problem is big bundle file, so if I could choose - I would definitely choose
.wrapper_hb34JHG34
classes looking style for minimise my bundle
That's a good point... although as I said above, I think it makes more sense for the page to request individual CSS files per component rather than bundle all of them up into one giant CSS file. With HTTP/2, gzip, etc, I think per-component CSS files could be pretty small and wouldn't impact load times dramatically.
Quick answear about .config.vcss = true
means insert this css transpile feature inside rux gem to not create another one, and user can enable or disable this css transpile feature by config flag .config.vcss = true
for example
Great next: i think it doesn't matter which tool user uses to create a bundle file or asset delivery, not?
The essence of VCSS is to take a classes from a my_component.vcss
file based on @styles
instance and transpile each class to .avatar_3hkb87HFy
or nested version .ui--mix--home--spacecraft-item-component > .ui--mix--home--spacecraft-item -component-wrapper > .ui--mix--home--spacecraft-item-component-avatar
and after that rewrite my_component.css
component file with that classes and also keep it in inside html like:
<div class="ui--mix--home--spacecraft-item-component" data-controller="ui--mix--home--spacecraft-item-component">
<div class="ui--mix--home--spacecraft-item-component-wrapper" data-action="click->ui--mix--home--spacecraft-item-component#handleClick">
<div class="ui--mix--home--spacecraft-item-component-avatar">
</div>
<div class="ui--mix--home--spacecraft-item-component-name">
Bla Bla
</div>
</div>
</div>
<!--OR Hashed version-->
<div class="ui--mix--home--spacecraft-item-component" data-controller="ui--mix--home--spacecraft-item-component">
<div class="wrapper_jhb45" data-action="click->ui--mix--home--spacecraft-item-component#handleClick">
<div class="avatar_6fjGFD6">
</div>
<div class="name_kj5fHG0">
Bla Bla
</div>
</div>
</div>
You can see we changed only classes which was inside @styles
instance and didn't changed classes which user wrote manually by another way without @styles
instance
Maybe will be nice also set a config flag which version of transpiled classes you need .avatar_3hkb87HFy
or .ui--mix--home--spacecraft-item-component > .ui--mix--home--spacecraft-item -component-wrapper > .ui--mix--home--spacecraft-item-component-avatar
for example config.vcss_hashed = true
As you can see it doesn't matter for this feature how user bundles styles, by each component or by one big entry bundle, that's not our trouble haha๐
@camertron Have you think about that? Otherwise it would be fine to have some transpile callback, so users can realize this or anything else by himself
Like before_transpile
, after_transpile
etc
@camertron bump๐
Quick answear about
.config.vcss = true
means insert this css transpile feature inside rux gem to not create another one
Hmm I'm not sure I understand. Where does this config value get set? In application.rb maybe?
class Application < Rails::Application
config.rux.vcss = true # is this correct?
end
I think it doesn't matter which tool user uses to create a bundle file or asset delivery, not?
I'm not sure, I don't have much experience with all the new asset options in Rails these days. We just need to make it easy to configure whatever tool to process CSS files. If you think that doesn't require any magic on rux's part, then cool ๐
You can see we changed only classes which was inside
@styles
instance and didn't changed classes which user wrote manually by another way without@styles
instance.
Right yeah that's great ๐ Would rux look for an @styles
instance variable? It might be nicer to do something like this:
class Component < ViewComponent::Base
styles do
Styles.new(
wrapper: "wrapper",
avatar: "avatar",
name: "name"
)
end
end
What do you think?
Maybe will be nice also set a config flag which version of transpiled classes you need
Ahh yes I like that! Make it easy to switch between them in case you want one style or the other ๐
Ohh @camertron i totally agree with you. I think this way is cool:
styles do
Styles.new(
wrapper: "wrapper",
avatar: "avatar",
name: "name"
)
end
And about configuration: i think it can be in development.rb
file
Rails.application.configure do
config.rux.vcss = true
...
Do you think that's possible?๐ I really need that and i'm sure that's a revolutionize feature
I think this way is cool
Awesome!
And about configuration: i think it can be in
development.rb
file
Right ok that makes sense. I still think this functionality should eventually live in a separate gem, but we can always extract it later.
Do you think that's possible?๐ I really need that and i'm sure that's a revolutionize feature
Yes, I definitely think it's possible! Are you volunteering to work on it?
@camertron I don't think i have time for that, but if i can help somehow a little - let me know๐
Hey @camertron can i help somehow to make this feature?๐
Hey @serhiijun, sure, feel free to dive in and submit a PR ๐ Maybe a good place to start is adding the styles
method?
Same to css-in-js it would be fine to have bundled css from my rux component too. Let's say, we have this folder structure:
And my_component.rux looks like this
And
my_component.rcss
like this:And while Rux transpiles .rux component - it also transpiles .rcss file from this component to .css file, which may looks like this after:
As you can see - now our css selectors is uniq. Why we need that - well, this is super simple example, but let's imagine we have 50 components. Each of them may have .wrapper or .avatar or anything same classes. Now solving that will looks like nesting css selectors:
By this way our bundle will have ton of KB lol Or another way same to:
This way so fast will make our code super ugly. So, my proposal is realise transpiling rcss to css which will have uniq version of selectors so our code will be clean and our bundle will be super light weight.