There are two modes of front-end routing: hash mode and History mode. The implementation modes, advantages and disadvantages of these two modes are analyzed.

To facilitate demonstration, install light-server globally: Yarn global add light-server

Hash pattern

The hash pattern is a pattern that concatenates the path of the front-end route with a hash sign (#) after the real URL. When the path after the hash sign # changes, the browser does not reissue the request, but instead fires a HashChange event.

Example:

Let’s create a new hash. HTML file that says:

<a href="#/a">A page</a>
<a href="#/b">B page</a>
<div id="app"></div>
<script>
  function render() {
    app.innerHTML = window.location.hash
  }
  window.addEventListener('hashchange', render)
  render()
</script>
Copy the code

Run in a directory:

light-server -s .  --port 3000
Copy the code

Then open the http://localhost:3000/hash.html to check the effect.

In the example above, we set up two route navigation using the A tag, using the app as the view rendering container, and triggering an update to the view container when switching routes. This is how most front-end framework hash routing works.

To summarize the advantages and disadvantages of the hash mode:

  • Advantages: Good browser compatibility, even Internet Explorer 8 support
  • disadvantages: Path in hash sign#In the back, it’s ugly

The history mode

The History API is a new feature in H5 that allows developers to change front-end routing directly, that is, to update the browser URL address without reissuing the request.

Example:

Let’s create a new history.html and say:

<a href="javascript:toA();">A page</a>
<a href="javascript:toB();">B page</a>
<div id="app"></div>
<script>
  function render() {
    app.innerHTML = window.location.pathname
  }
  function toA() {
    history.pushState({}, null.'/a')
    render()
  }
  function toB() {
    history.pushState({}, null.'/b')
    render()
  }
  window.addEventListener('popstate', render)
</script>
Copy the code

Run in a directory:

light-server -s . --historyindex '/history.html' --port 3000
Copy the code

Then open the http://localhost:3000/history.html to check the effect.

The History API provides a wealth of functions for developers to call. Let’s open the console and enter the following statement to watch the browser address bar change:

history.replaceState({}, null.'/b') // Replace the route
history.pushState({}, null.'/a') // Press the routing stack
history.back() / / return
history.forward() / / to go forward
history.go(-2) // Retreat twice
Copy the code

The above code listens for the popState event, which can be heard:

  • The user clicks the browser forward and backward
  • Call history manuallyback,forwardgomethods

Failed to listen:

  • The history ofpushStatereplaceStatemethods

This is why the above toA and toB functions internally need to manually call the render method. Also, you may have noticed that the light-server command has more –historyindex ‘/history.html’ arguments. What does that do?

When the browser refreshes, it will send the actual resource request by the path. If the path is the URL set by the history API on the front end, the resource will not exist on the server side and will return 404. The above argument means to return the content of history.html if the backend resource does not exist.

Therefore, when deploying a single page application based on the History API online, you must support the backend, otherwise you will get a lot of 404. For the most common Nginx example, simply add the following line to the location/configuration:

try_files $uri /index.html;
Copy the code

To summarize the pros and cons of the History mode:

  • advantages: path is normal, no hash sign#
  • Disadvantages: Less compatibility than hash, and needs to be supported by the server, otherwise a page refresh 404