vuejs/router

Introduce `createSearchParamsHistory`

Closed this issue · 1 comments

What problem is this solving

As the documentation says, both createWebHistory and createWebHashHistory have disadvantages.

createWebHistory can not be used if the underlying server can't handle the required paths in some specific way.

Since, by default, when a server sees pathname like this /users/123 it tries to return a file with name 123 from the users directory even while only the index.html is in the working directory. Trying opening such URL will fail with the 404 error.

❌ So, createWebHistory can not be used when there is no ability to configure the server behaviour. In particular, in web extensions.

On the other hand, using of createWebHashHistory don't allow to use the hash for common things as scrolling to an element with id same as in the hash, and/or styling the element with :target CSS selector, also for other things like using hash for storing local data, for example:

  • a code in online code editors (https://play.vuejs.org/ )
  • a decryption key in a file hosting like Mega (https://mega.nz/)

❌ Thus, using createWebHashHistory limits the use of the hash to only store the route and nothing else. It's bad.

Proposed solution

The very simple alternative is just to store the route path as a key's value of searchParams.

This:

  • ✅ works everywhere, no need to perform a server configuration which may be not available,
  • ✅ you can use hash for your own purposes,
  • ✅ no SEO problems like with using of createWebHashHistory

(using of seachParams for navigation is the older thing than "REST API-like" URLs of createWebHistory).

It should look like this:

createRouter({
    history: createSearchParamsHistory(),
    routes: [
        { path: "/users/:id", component: UserComp, name: "User" },
        { path: "/admin", component: AdminComp, name: "Admin" },
    ]
});

And the URLs will look so:

  • /index.html?route=/users/123
  • /index.html?route=/admin

For both URLs /index.html and /index.html?route=/users/123 any server will return the same "index.html" file with no problem.
Then the router will parse the input URL and do the things.

Also, it makes sense to allow to specify the searchParam's key name (if the default route is already used for another purpose):

createSearchParamsHistory({
    name: "vueRoute"
})
  • /index.html?vueRoute=/admin

I sure it's easy to implement.
You just only need to parse/write the route path from/to the specific searchParams' key instead of pathname, or hash.
That's all.


createSearchParamsHistory will be definitely better than createWebHashHistory.

Describe alternatives you've considered

No response

posva commented

Interesting idea! It does sound like you could use the hash history. Note that you can still store other data with a virtual hash property. You do lose the CSS :target property as a tradeoff.
You mention 3 other advantages, but the first two apply to the hash history as well, and the last one isn't a concern in a web extension.

In any case, this can be built as a standalone library outside of vue-router (that was one of the advantages of extracting the histories 😄). I don't think this kind of history should be included in vue router because I wouldn't recommend it over the other histories (for the reasons mentioned above), but I would love to see it as a standalone open-source library! It shouldn't be too hard by copying an existing history and replacing the way it handles the path, so you should definitely give it a try. FYI: I offer consultancy for anybody needing help with their products