honojs / honox

HonoX - Hono based meta framework
https://hono.dev
MIT License
1.4k stars 38 forks source link

Directory based router #45

Open akku1139 opened 7 months ago

akku1139 commented 7 months ago

What is the feature you are proposing?

I would like to do directory-based routing like SvelteKit and Next.js App Router. Either in a way like (+)page.ts or separate files for each HTTP method and route them like +get.ts and +post.ts.

EdamAme-x commented 7 months ago

I agree with this idea. I think it is a great way to solve the complexity of routing.

yusukebe commented 7 months ago

Hi @akku1139 !

Thanks for your proposal.

I'm not 100% sure I understand the directory routing for SvelteKit and Next.js App Router, but what is the difference between using index.tsx as a base as shown below?

app/routes/about/index.tsx

Of course, it would be interesting to be able to separate files for each request, such as GET and POST. In that case, I think it would be nice to have a rule for file names such as index.get.tsx or index.post.tsx, and the results they default export to correspond to GET or POST.

babie commented 7 months ago

Personally, I think that pros of directory-based-router equals pros of pakcage by feature. (cf. package by feature のススメ (ja))

I don't mind using index.tsx instead of page.tsx, but I would like a filename convention(e.g. prefix rule) that the router will ignore. This way, we can freely place related files (e.g. foo.module.css) without getting caught in routing.

akku1139 commented 7 months ago

If you use index.get.tsx etc., there is a possibility that a route of /index.get will be created.

If it can create rules in the package, the problem will be solved, but setting different rules depending on the project may make it difficult to understand.

If you decide on a fixed root file in HonoX, it will be the same for all projects, so it is easy to understand, when creating a very small application, it may be easier to make if the file name corresponds to the root. ↓ This is an explanation about SvelteKit's routing. https://zenn.dev/qwerty/articles/ed1283408bef01

yusukebe commented 7 months ago

@babie @akku1139

Thanks! Could understand. But I want to have a little bit of time to learn about it and consider it!

yoshikouki commented 6 months ago

I agree with the pros/cons discussed so far.

On a personal note, I like the current filename rules because they are as clear as the Controller in Ruby on Rails. (I guess the directory structure under app/routes in honox plays a role similar to routes.rb in Ruby on Rails. I like it because it's more convention-oriented and intuitive.)


Here are some suggestions for a related, but slightly different, client-side component (islands)

Currently, even page-specific client-side components must be placed in app/islands/*.

For example, consider a simple chat application,

.
├── app
│   ├── islands
│   │   ├── chat.tsx # URL `/chats/:id` specific component
│   │   └── online-status.tsx # Global component placed in each routes
│   ├── routes
│   │   ├── chats
│   │   │   ├── [id].tsx
│   │   │   └── index.tsx
│   │   └── index.tsx

I would like to place the client component chat.tsx in the same directory as the server-side component routes/chats/[id].tsx which is closer in purpose (e.g. chat.island.tsx)

.
├── app
│   ├── islands
│   │   └── online-status.tsx
│   ├── routes
│   │   ├── chats
│   │   │   ├── [id]
│   │   │   │   ├── chat.island.tsx
│   │   │   │   └── index.tsx
│   │   │   └── index.tsx
│   │   └── index.tsx

However, we feel that it would be better to manage global common components used on each page in app/islands/* as before.

For your reference

babie commented 6 months ago

I think it is a good idea. However, there is the problem of what to do if you want to create a page called /chats/[id]/chat.island.

I think it is a good idea to prefix it with some special character to prevent it from being included in the routing. For example, ! or something like that.

.
└── app
    ├── islands
    │   └── online-status.tsx
    └── routes
        ├── chats
        │   ├── [id]
        │   │   ├── !chat.island.tsx
        │   │   ├── !chat.module.css
        │   │   └── index.tsx
        │   └── index.tsx
        └── index.tsx
yusukebe commented 6 months ago

Hi @yoshikouki @babie

I would like to place the client component chat.tsx in the same directory as the server-side component routes/chats/[id].tsx which is closer in purpose (e.g. chat.island.tsx)

+1

I think it is a good idea to prefix it with some special character to prevent it from being included in the routing. For example, ! or something like that.

+1

I think both ideas are great. This means that...

These would be simple to implement and easy for users to understand.

yusukebe commented 5 months ago

Hey!

I've made PR #140, enabling putting an island component, not only in the /app/islands directory. I think this is a good change. So, this will be merged. But if you have any thoughts, please share them!

yusukebe commented 5 months ago

Hi you all.

I've released v0.1.12. This release includes the new feature which enables placing islands on the same directory of pages instead of /app/islands/*:

./app
├── client.ts
├── global.d.ts
├── routes
│   ├── _renderer.tsx
│   ├── articles
│   │   ├── [id].tsx
│   │   ├── _preview.island.tsx // <=== the prefix should be `_` and the suffix is `.island.tsx`
│   │   └── create.tsx
│   └── index.tsx
├── server.ts
├── style.css
└── utils.ts

This enables directory-based routing. Please try it.