Skip to content

Allow using base option with hash under history mode #1349

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

Merged
merged 2 commits into from
Jun 16, 2017

Conversation

fnlctrl
Copy link
Member

@fnlctrl fnlctrl commented Apr 18, 2017

What kind of change does this PR introduce? (check at least one)

  • Bugfix
  • Feature
  • Code style update
  • Refactor
  • Build-related changes
  • Other, please describe:

Does this PR introduce a breaking change? (check one)

  • Yes
  • No

If yes, please describe the impact and migration path for existing applications:

The PR fulfills these requirements:

If adding a new feature, the PR's description includes:

  • A convincing reason for adding this feature (to avoid wasting your time, it's best to open a suggestion issue first and wait for approval before working on it)

Other information:

I'm not sure if using '#' inside base is a valid usage, though it currently works (in history mode, with an issue fixed by this PR), so I don't know whether it's a fix or a feature...

So the use case is:

  1. Using vue-router in a hybrid app, where it's loaded as under file:// scheme.
  2. I want to keep using history mode so scrollBehavior can be used. (to deliver a native-like experience without manually adding code to track/restore scroll position)

It may seem crazy, but let me explain:

  • Normally history mode won't work under file:// scheme

    e.g. file://path/to/index.html + history mode + route '/foo' = file://path/to/index.html/foo, 404!

  • But if we add a hash inside base, almost everything works (history API, popstate, etc).

    e.g. file://path/to/index.html, we use base: 'file://path/to/index.html#' (location.pathname + '#') and trick the browser into thinking it's a hash route.

  • The only issue is: when using router.back(), the route gets parsed as hash, resulting in a non-matched route. (due to the current way vue-router parses location inside getLocation using location.hash)

    e.g. file://path/to/index.html#/foo => file://path/to/index.html#/bar , then use router.back()(or history.go(-1)), the router now parses the location as {path: '/path/to/index.html', hash: '#/foo'}

This can be considered some kind of a semi-hash mode that utilizes history API while using a hash route.
This way we allow hybrid apps using file:// scheme to enjoy history mode without being limited to hash mode.

//
Side notes:

  • It's actually been used in my production app for months, with this little flaw worked-around with a catch-all redirect. Tested under iOS 9/10, Chrome(Crosswalk)
  • popstate and hashchange are both fired when navigating.

@yyx990803
Copy link
Member

I'm a bit confused - what is the use case for this? Why would someone use a base with #?

@posva
Copy link
Member

posva commented Apr 24, 2017

@fnlctrl Isn't it better to make the electron/nw app start a local server and visit that instead? I remember there was a way of setting up a dynamic port for that

@fnlctrl
Copy link
Member Author

fnlctrl commented Apr 25, 2017

@yyx990803 Sorry I didn't make my use case clear 😅 Let me try again..

1. Why base with hash?

To make history mode work under file:// scheme

1.1. Why doesn't history mode work under file:// scheme?

History API does work. So under

file://path/to/index.html

when navigating to /foo with vue-router, the url becomes

file://path/to/index.html/foo

and the browser tries to load this non-existent file. (foo under folder index.html)

1.2 Why adding a hash work?

Just as hash mode is already working under file:// scheme

2. Why file:// scheme?

To make the hybrid app work offline (by loading a bundled html file)

@posva A local server on iOS/Android seems an unnecessary complexity to us - after all everything worked very well using file:// scheme.. and we want to spend as little time on native code as possible.

@yyx990803 yyx990803 merged commit f5db5b8 into vuejs:dev Jun 16, 2017
yyx990803 added a commit that referenced this pull request Jun 16, 2017
@yyx990803
Copy link
Member

I merged it but afterwards I don't think I fully understood the patch, so I reverted it for now. Does this feature require the base to be hard-coded to the file path?

@fnlctrl
Copy link
Member Author

fnlctrl commented Jun 17, 2017

Yes, this is only meaningful if base is hard-coded to the file path (base: location.pathname + '#/')..
Should I put it somewhere in the doc? This seemed too much of an edge use case to me..so I wasn't sure where to put it.

@yyx990803
Copy link
Member

yyx990803 commented Jun 17, 2017

What's the primary reason for not just using hash mode? For scrollBehavior?

@fnlctrl
Copy link
Member Author

fnlctrl commented Jun 17, 2017

Yes, the primary reason was "scrollBehavior", with other benefits of being able to use history api (e.g. using history.go).

@yyx990803
Copy link
Member

I think it's a valid use case, but using base with hash sounds like a hack. Technically I think we should improve HashHistory to support scrollBehavior when pushState is supported.

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

Successfully merging this pull request may close these issues.

3 participants