posva / unplugin-vue-router

Next Generation file based typed routing for Vue Router
https://uvr.esm.is
MIT License
1.47k stars 67 forks source link

Catch-all rules [...param] should end with a star * #412

Open jods4 opened 1 month ago

jods4 commented 1 month ago

Naming your file [...path].vue generates the router path :path(.*). This is documented here: https://uvr.esm.is/guide/file-based-routing.html#catch-all-404-not-found-route

Vue Router documentation recommends using a repeated regex for catch-all routes, i.e. :path(.*)* (note extra star at the end). See: https://router.vuejs.org/guide/essentials/dynamic-matching#Catch-all-404-Not-found-Route

There difference is subtle but observable.

First: the path parameter is a string "/a/b/c" with unplugin, and a parsed array ["a", "b", "c"] with router syntax.

Second: I would like to navigate to a catch-all route with a specific URL. It's impossible to do with unplugin, consider this:

// Unplugin :path(.*)
router.push({ name: "catch-all", params: { path: "a/b/c" } })
// Location is escaped into: /a%2fb%2fc

// Vue Router : path(.*)*
router.push({ name: "catch-all", params: { path: ["a", "b", "c"] })
// Location is /a/b/c
posva commented 1 month ago

This could be documented and it’s possible with [[...path]]+

jods4 commented 1 month ago

Thanks for the tip! Only difference with * is that empty route is not accepted, something that doesn't matter in my case. I'm gonna use that.

jods4 commented 1 month ago

@posva I tried to use [[..path]]+ and found two issues:

  1. The params types generated by unplugin-vue-router are incorrect, path should be an array.
  2. Looks like (on Windows at least) plus signs in paths cannot be fetched (using Vite).

Failed to fetch dynamically imported module: http://localhost:6357/Modules/[...path]+.page.vue

My guess is this is an escaping issue. + in URL are an escape for a space `. As it's part of the real filename I suppose it should have been escaped as%2B`.

posva commented 1 month ago

Wouldn’t 2 be a vite bug? I can’t test it

jods4 commented 1 month ago

I'm not sure, I would need to debug.

The message quoted above is found in browser console. That doesn't look like the right URL for the browser to fetch a file named [...path]+.vue because that URL would decode into [...path] .vue (with a space).

So my guess at the moment is that unplugin-vue-router should generate a route with component: import('./[..path]%2B.vue')... but that's just a guess at this point.

How are other escapes handled, for example if I name my file %&/.vue? I suppose that falls in the same category. Sorry I do not have time to dig into this further right now, will try to come back to this later.

posva commented 1 month ago

No worries, the help is already appreciated! This plugin doesn’t do anything in terms on encoding, it expects the other tools to handle IIRC + is decoded as space in the query (not in the path) but not by everything 😅