Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC]: New file organization scheme for components used by only a single parent #10263

Open
1 task
cannikin opened this issue Mar 18, 2024 · 9 comments
Open
1 task

Comments

@cannikin
Copy link
Member

cannikin commented Mar 18, 2024

Summary

After five years of building Redwood apps, patterns have emerged when it comes to organizing the components that make it up. One is that we'll often have components that are only used by a single parent, not shared with others. We've found that co-locating those components with the parent is a great way to stay organized. What does the community think about making this a standard going forward?

Motivation

To keep our apps better organized for long term maintenance.

Detailed proposal

The top level /components directory would be used for components that are shared by two or more parents, otherwise they would go next to their parent layout/pages in the /layouts and /pages directory.

Imagine an application which has a page listing products, a Cell which actually fetches and displays those products, a component for adding a product to the cart, and the actual button the user clicks. The button would be shared across the app, but the <ProductsCell> is only used by the <ProductsPage>, and <AddToCart> is only used in <ProductsCell>:

Before

.
├── components
│   ├── AddToCart
│   │   └── AddToCart.jsx
│   ├── Button
│   │   └── Button.jsx
│   └── ProductsCell
│       └── ProductsCell.jsx
├── layouts
└── pages
    └── ProductsPage
        └── ProductsPage.jsx

After

.
├── components
│   └── Button
│       └── Button.jsx
├── layouts
└── pages
    └── ProductsPage
        ├── ProductsCell
        │   ├── AddToCart
        │   │   └── AddToCart.jsx
        │   └── ProductsCell.jsx
        └── ProductsPage.jsx

Are you interested in working on this?

  • I'm interested in working on this
@dustinsgoodman
Copy link
Contributor

Let's say you have a UserCell that's shared on different pages, would that still go in components? If so, I think this is a wonderful pattern to consider. We use this in other project structures for the same reason and I use it on all my Redwood projects.

@cannikin
Copy link
Member Author

Yep, as soon as it's shared with another parent, it would go in web/src/components instead of the parent's directory!

@ValentinH
Copy link

Colocation FTW!

@simoncrypta
Copy link
Collaborator

simoncrypta commented Mar 29, 2024

I use this file organization scheme for years, it is a great way to keep organizing when the project and team scale. At LeftLane we also have domain directories focused by type of end user, think about front-desk/back-office kind of separation. Again, everything works, just need to add the directory name into the Route page import. I'm curious, what's the plan by going with this new file organization scheme by default in RW? One request I hope for is to be able to select the page I want my component to be generated with the CLI.

@cannikin
Copy link
Member Author

cannikin commented Mar 29, 2024

One request I hope for is to be able to select the page I want my component to be generated with the CLI.

Yep we'll have to re-think the generators and maybe some new args that can be passed to them letting them know you want to generate them next to some existing pages, instead of always in their root directory like /components.

My first instinct was that you include the path where you want it generated, otherwise it'll go in the default location:

yarn rw g component Button
# web/src/components/Button/Button.jsx

yarn rw g component Button AdminPage
# web/src/pages/AdminPage/Button/Button.jsx

yarn rw g component Button AdminPage/UsersCell/UserRow
# web/src/pages/AdminPage/UsersCell/UserRow/Button/Button.jsx

@simoncrypta
Copy link
Collaborator

My first instinct was that you include the path where you want it generated, otherwise it'll go in the default location:

yarn rw g component Button
# web/src/components/Button/Button.jsx

yarn rw g component Button AdminPage
# web/src/pages/AdminPage/Button/Button.jsx

yarn rw g component Button AdminPage/UsersCell/UserRow
# web/src/pages/AdminPage/UsersCell/UserRow/Button/Button.jsx

I would prefer to start from ../src for more flexibility, for example, we would like to do things like that :

yarn rw g component Button pages/dealership/components
# web/src/pages/dealership/components/Button/Button.jsx

yarn rw g component Button pages/admin/User/EditUserPage
# web/src/pages/admin/User/EditUserPage/Button/Button.jsx

@Tobbe
Copy link
Member

Tobbe commented Apr 1, 2024

yarn rw g component Button AdminPage/UsersCell/UserRow

I really like how this gives more flexibility to our users! But I'm a little concerned about DX

Because there's no auto-complete when writing the path here there's a lot of room for typos and/or just not remembering exactly what you named things. Discoverability is also not great.

Anyone have any thoughts on how to mitigate those concerns?

@cannikin
Copy link
Member Author

cannikin commented Apr 1, 2024

If we just start the path from the current directory, you would get the standard shell autocomplete:

yarn rw g component Button web/src/pages/AdminPage/UsersCell/UserRow

@colbywhite
Copy link
Contributor

this is typically the same comp structure i personally use. and thus i like this for standard selfish reasons

but i'd vote to default to this but then provide the tools for ppl to swap back and forth, which is a little bit different than generating a comp in one style or the other. inevitably my comps start out for a specific page then i realize i need it to be shared 2 months later. and vice versa. maybe something like yarn rw g comp mv MySharedComp ProductPage and it fixes the imports and maybe even renames the comp (both in the filename and the file itself).

a linter that lets me know that my shared comp isn't actually shared would also be cool. maybe even more valuable. especially if it can autofix itself by moving the comp itself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants