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

Differentiate slash-ended routes (foo and foo/) #1443

Closed
MachinisteWeb opened this issue May 20, 2017 · 9 comments
Closed

Differentiate slash-ended routes (foo and foo/) #1443

MachinisteWeb opened this issue May 20, 2017 · 9 comments

Comments

@MachinisteWeb
Copy link
Contributor

MachinisteWeb commented May 20, 2017

What problem does this feature solve?

The following url:

http://www.exemple.com/agency/

is NOT the same as the following url:

http://www.exemple.com/agency

for SEO crawler and HTTP point of vue.

This is not a big deal for a SPA without SEO requirement but in an SSR app this is critical.

If I use, for example, Express.js to serve my application with the strict mode and following routes :

app.set("strict routing", true);
app.get('/agency/', agencyPage);
app.get('/*', errorPage);

The pages (based on Vue renderer) HTTP served for following URL will be :

  • http://www.exemple.com/agency/ ==> agency
  • http://www.exemple.com/agency ==> error
  • http://www.exemple.com/foo ==> error

But, when client-side Vue will perform hydratation, the component/route will be resolved as following

  • http://www.exemple.com/agency/ ==> agency : Good
  • http://www.exemple.com/agency ==> agency : Fail
  • http://www.exemple.com/foo ==> error : Good

For http://www.exemple.com/agency, hydratation fail because the source code come currently from errorPage process (/agency/ is not the same page as /agency and HTTP returned a 404 error code) but client-side Vue Router find a route /agency for /agency/.


There is maybe a way to explain to router how the route should be match ?

What does the proposed API look like?

declare type RouteConfig = {
  ...
  strict?: boolean
  ...
}

Allows Vue Router to work in the same way as usual but allows to corretly recognise HTTP different url for SEO/SSR mode with 'strict mode'.

@MachinisteWeb
Copy link
Contributor Author

MachinisteWeb commented May 20, 2017

My current workarround is to check the following before use Vue Proccess client-side :

if (window.location.pathname.slice(-1) !== '/') {
  window.location = window.location.pathname + '/';
}

but that not allows usage of url not ended by '/' so a « strict mode » should be the true solution.

@posva posva changed the title Feature Request: Vue Router Strict Mode Differentiate slash-ended routes (foo and foo/) May 20, 2017
@posva
Copy link
Member

posva commented May 20, 2017

This will be possible once the pr #1215 gets merged by passing setting strict: true on the pathToRegexOptions property of a route
However, from a user point of view, foo/ and foo are the same, so I'd recommend you to handle the case in your server, there's probably an option for express. Out of curiosity, why do you need to make that difference?

@MachinisteWeb
Copy link
Contributor Author

MachinisteWeb commented May 20, 2017

Thx @posva !

Just because it's not the same route for crawler.

http://www.test.com/bonjour (file bonjour under directory /)
http://www.test.com/bonjour/ (file « index (for example) » under directory /bonjour/)

So for SEO, it's important when crawler pass on http://www.test.com/bonjour and http://www.test.com/bonjour/ which this two url are not « duplicated content ». So I let my server respond one not exist and other exist.

And you are right, some user don't do the difference, and ultimatly for a pure front-side user experience it's a better thing to not have different pages behind /bonjour and /bonjour/ so the most common case is just to return 404 from one of two URL OR a 301 redirect from one to other.

Vue Router actually not allows that. I wanted to force « /bonjour » to be « /bonjour/ » with redirect but without success too :/

EDIT : I will provided some full SEO/SSR website with Vue and NodeAtlas (based on Express) with isomorphisme and it's really important my front can be display error page from /bonjour and real page from /bonjour/ to allows hydratation to be performed because server serve error in one case and real page in others.

I will probably directly do a 301 for all non slash-ended route to slash-ended and let « front » part not do difference between two type of URL, maybe.

@posva
Copy link
Member

posva commented Jun 16, 2017

This got merged at #1215
You'll have to provide an option to the route definition:

pathToRegexOptions: { strict: true }

(it's not released yet though)

@posva posva closed this as completed Jun 16, 2017
@MachinisteWeb
Copy link
Contributor Author

MachinisteWeb commented Jun 16, 2017

Vue guys! You're bests!

EDIT:

(it's not released yet though)

I will wait a little more ;)

@MachinisteWeb
Copy link
Contributor Author

MachinisteWeb commented Jun 30, 2017

Re @posva

As I already said here (after cloture of point): #1215

This do not resolve my point, I wonder myself it's there is an issue...

If I set pathToRegexpOptions: { strict: true }, only page « without » trailing work. And I expected page only « with » that's work...

To resume, if I create:

/ and /test/ for exemple

/ <= OK
/test/ <= OK
/test <= NOK

and with vue-router, this is do.

/ <= OK
/test/ <= OK
/test <= OK

With usage of pathToRegexpOptions: { strict: true } I expected this following your advices

/ <= OK
/test/ <= OK
/test <= NOK

But what I have is that

/ <= OK
/test/ <= NOK
/test <= OK

So it's not normal? That is the reverse of description of strict no?

It's possible to re-open this issue and help to resolve that in anyway ?

@posva
Copy link
Member

posva commented Jun 30, 2017

@haeresis I went a bit too fast creating the issue, it works as it should: http://jsfiddle.net/0evuj9fs/

@MachinisteWeb
Copy link
Contributor Author

MachinisteWeb commented Jul 1, 2017

Thx a lot @posva for your help.

Your « simple » case work, indeed but... let me introduce this:

I have just add a new entry error with /* to match all others pages. This is the minimal for a page that doesn't exist.

I also set /home/ and not /home because it's the case I want it match, but if you kept (/home) that change nothing.

See the behavior of link, it's change in fonction of source target!

Follow this cases:

So when you start running, it is display: Error (I expected Home)

  • After, click on /home and you will see Home (OK)
  • After, click on /foo and you will see Foo (I expected Error)
  • After, click on /foo/ and you will see Foo (OK)
  • After, click on /error and you will see Error (OK)
  • After, click on /plop and you will see Error (OK)
  • After, click on /hoho and you will see Error (OK)
  • After, click on /foo/ and you will see Error (WTF ! Previously it was OK...)
  • After, click on /foo and you will see Error (Error Great ! But Previously it was Foo...)
  • After, click on /home and you will see Home (OK)
  • After, click on /foo/ and you will see Error (WTF ! Again...)
  • After, click on /foo and you will see Error (WTF ! Again...)
  • After, click on /home and you will see Home (OK)
  • After, click on /foo and you will see Foo (WTF ! Power!)
  • After, click on /foo/ and you will see Foo (My brain will exploding!!!)

Vue... Vue... What you can do to me T-T

It is the same thing I have with hydratation, after my server response the true response.

Now remove , pathToRegexpOptions: { strict: true }, and ok, /foo and /foo/ are the same page, but all work as expected. (and the default page is Home, not Error).

Where is something I don't understand ?

:D that smells like an issue then !

@giticon
Copy link

giticon commented Oct 22, 2020

I had the same problem. This is a workaround I found. With the @nuxtjs/sitemap module everything is ok.

extendRoutes: (routesIn) => {
    routesIn.forEach((r) => {
      if (r.path.includes('/blog')) {
        r.path = r.path.replace('/blog', '/blog/');
      }
    });
    return routesIn;
    }

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

No branches or pull requests

3 participants