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

bug: nested folders causes parent folder to use trailing slash #70

Closed
lrstanley opened this issue Sep 30, 2022 · 3 comments
Closed

bug: nested folders causes parent folder to use trailing slash #70

lrstanley opened this issue Sep 30, 2022 · 3 comments

Comments

@lrstanley
Copy link

Problem

When defining routes that have both sub-routes, and an index of the parent route, unplugin-vue-router will generate the parent route types including a trailing slash. This causes inconsistencies throughout the routes -- this is also a different behavior compared to vite-plugin-pages.

Description

I have the following src/pages/ folder structure, which is used for all routing:

$ tree src/pages/
src/pages/
├── [...catchall].vue
├── dashboard
│   ├── guild
│   │   └── [id].vue
│   └── index.vue
├── index.vue
├── info
│   ├── privacy.vue
│   ├── service-health.vue
│   └── terms.vue
└── test.vue

3 directories, 8 files

Vite config:

    VueRouter({
      routesFolder: "src/pages",
      extensions: [".vue"],
      routeBlockLang: "yaml",
      logs: true,
    }),

And this is the auto-generated typed info from vite, that is most important to this issue:

declare module 'vue-router/auto/routes' {
  export interface RouteNamedMap {
    '/': RouteRecordInfo<'/', '/', Record<never, never>, Record<never, never>>,
    '/[...catchall]': RouteRecordInfo<'/[...catchall]', '/:catchall(.*)', { catchall: ParamValue<true> }, { catchall: ParamValue<false> }>,
    '/dashboard/': RouteRecordInfo<'/dashboard/', '/dashboard/', Record<never, never>, Record<never, never>>,
    '/dashboard/guild/[id]': RouteRecordInfo<'/dashboard/guild/[id]', '/dashboard/guild/:id', { id: ParamValue<true> }, { id: ParamValue<false> }>,
    '/info/privacy': RouteRecordInfo<'/info/privacy', '/info/privacy', Record<never, never>, Record<never, never>>,
    '/info/service-health': RouteRecordInfo<'/info/service-health', '/info/service-health', Record<never, never>, Record<never, never>>,
    '/info/terms': RouteRecordInfo<'/info/terms', '/info/terms', Record<never, never>, Record<never, never>>,
    '/test': RouteRecordInfo<'/test', '/test', Record<never, never>, Record<never, never>>,
  }
}

Looking at /dashboard/, because it has /dashboard/guild/[id] as a sub-path, this causes the dashboard/index.vue page to render as /dashboard/, where I believe it should be /dashboard. This is the behavior I have previously seen with vite-plugin-pages (see their readme that includes an example of a similar routing folder structure as above).

Technically, /dashboard is still routable, however any form of typed routing will always force that route to include the trailing slash, and this leads to inconsistent trailing slashes being used throughout the frontend.

Version Info

  • vue 3.2.39
  • vite 3.1.2
  • unplugin-vue-router 0.2.1
@posva posva closed this as completed in f0cfb36 Sep 30, 2022
@posva
Copy link
Owner

posva commented Sep 30, 2022

The type for the path should indeed be /dashboard and not /dashboard/. Note this is a type only fix and that it currently doesn't force you to use the version with the trailing slash, you can remove it after autocomplete and also any string is valid (from a typing perspective). The names will keep the trailing slash to differentiate them from parent routes which can also be targeted:

 // articles.vue
 '/articles': RouteRecordInfo<'/articles', '/articles', Record<never, never>, Record<never, never>>,
 // articles/index.vue
-'/articles/': RouteRecordInfo<'/articles/', '/articles/', Record<never, never>, Record<never, never>>,
+'/articles/': RouteRecordInfo<'/articles/', '/articles', Record<never, never>, Record<never, never>>,

@lrstanley
Copy link
Author

Updated to 0.2.2, and tested it out.

The names will keep the trailing slash to differentiate them from parent routes which can also be targeted

What does this mean? How would a parent route have the same name (or path) as a child route? Even with articles.vue and articles/index.vue, that should still be one route in the tree (and just wrapping the component), no? or am I missing something?

There are still inconsistencies between trailing slashes and not. If I use RouteNamedMap to restrict a to reference, it would still require the trailing slash, which will force it to use the trailing slash when routing. Additionally, various types reference some paths without a slash, and some with a slash. Even if auto-complete works, it's not ideal.

I can use RouteLocationNormalized like so:

However it's additional stutter/duplication, just to make trailing slashes consistent.

@posva
Copy link
Owner

posva commented Oct 1, 2022

Even with articles.vue and articles/index.vue, that should still be one route in the tree (and just wrapping the component), no? or am I missing something?

That would create two named routes named /articles and /articles/ (its child) but both map to the path /articles (you can find more about this in vue router docs). Having only articles/index.vue creates only one named route, /articles/, you can find other examples in the readme as well

There are still inconsistencies between trailing slashes and not. If I use RouteNamedMap to restrict a to reference, it would still require the trailing slash

Yes, that's the name, not the path. Note you can customize the way routes are named but the point of having a named that looks like their path is to make an instant connection between both.
Regarding that code sample, I don't know where you are using the cast, but the type should work without it for the extended functions. If not, more context or a boiled down repro would help to pinpoint the bug

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

2 participants