Hash mode and History mode

13.1 The difference between Hash mode and History mode
In front-end routing, no matter what the implementation mode is, it is an implementation method of the client. That is, when the path changes, no request will be sent to the server.

If you need to send a request to the server, you need to use ajax.

The difference between the two modes

The first is the difference in expression

Hash mode

https://www.baidu.com/#/showlist?id=22256
1
The path in the hash mode contains #, and the content after # is used as the routing address. Parameters can be carried via question marks.

Of course, this pattern is relatively ugly. The path contains symbols that have nothing to do with the data, such as # and ?

History mode

https://www.baidu.com/showlist/22256
1
History mode is a normal path mode. If you want to implement this mode, you need corresponding support from the server.

Let’s take a look at the principle differences between the two.

Hash mode is based on anchor points and onhashchange events.

The value of the anchor point is used as the routing address, and the onhashchange event is triggered when the address changes.

History mode is based on the History API in HTML5

That is, the following two methods

history.pushState( ) is only supported after IE10

history.replaceState()

Because when the browser refreshes the page, it will send a GET request to the server, but at this time the server does not configure the corresponding resources to match this request, so a 404 error is returned.

2. Solution
In order to solve this problem, we need to perform relevant configuration on the server side so that all routes point to the same entry file (such as index.html), and the front-end route handles the URL request and returns the corresponding page content.

The specific configuration method depends on the server environment used by the corresponding project. Common ones include Apache, Nginx, etc.

Taking Nginx as an example, you need to add the following configuration in the server configuration file (usually nginx.conf.js) to proxy all requests to the entry file of the Vue application:

try_file $uri$uri/ index.html

This code will direct all requests to the index.html file in the root directory, allowing the front-end router to handle URL requests.

At the same time, it should be noted that when using History mode, you need to ensure that the access paths of all routes point to index.html, otherwise a 404 error will still occur.

These configurations will ensure that when using history mode in a Vue application, the server correctly handles all routing requests and returns the correct page.

13.2 Use of History mode

History mode requires server support. Why?

Because in a single-page application, there is only one page, which is the page index.html, and there is no address such as http://www.test.com/login on the server side. In other words, if you refresh the browser,

When requesting the server, the /login page cannot be found, so a 404 error will occur. (In the traditional development mode, entering the above address will return the login page, while in a single-page application, there is only one page called index.html)

Therefore, in addition to static resources, the server should return the index.html of the single-page application.

Let’s start the history mode to demonstrate the corresponding problems.

First add a handler for the 404 component

First add a link to the menu bar:

 <div class="content left">
        <ul>
          <li><router-link to="/users"> User management</router-link></li>
          <li><router-link to="/rights"> Rights management</router-link></li>
          <li><router-link to="/goods"> Goods Management</router-link></li>
          <li><router-link to="/orders"> Order Management</router-link></li>
          <li><router-link to="/settings"> System settings</router-link></li>
          <li><router-link to="/about"> About</router-link></li>
        </ul>
      </div>

Here we have added an “About” link, but we have not defined a corresponding component for it, so we need to handle the 404 situation here.

const NotFound = {
template:

The page you visited does not exist!!

,
};

Added a component for 404 in the program.

const router = new VueRouter({
mode: “history”,
const router = new VueRouter({
mode: “history”,
routes: [
{ path: “/login”, component: Login },
{ path: “*”, component: NotFound },
{
path: “/”,
component:App,
redirect: “/users”,
children: [
{
path: “/users”,
component: Users,
meta: {
auth: true,
},
// beforeEnter(to, from, next) {
// if (window.isLogin) {
// next();
// } else {
// next(“/login?redirect=” + to.fullPath);
// }
// },
},
{ path: “/userinfo/:id”, component: UserInfo, props: true },
{ path: “/rights”, component: Rights },
{ path: “/goods”, component: Goods },
{ path: “/orders”, component: Orders },
{ path: “/settings”, component: Settings },
],
},
],
});

In the above code, the routing rules for handling 404 are specified, and the routing mode is changed to history mode. At the same time, enabling the routing rule configuration of other components is enabled here, that is, the addRoutes method is not used in the login method to dynamically add routing rules.

The login method is modified as follows:

login() {
// window.isLogin = true;
window.sessionStorage.setItem(“isLogin”, true);
if (this.KaTeX parse error: Expected ‘}’, got ‘EOF’ at end of input: … // this.router.addRoutes([
// {
// path: “/”,
// component: App,
// redirect: “/users”,
// children: [
// {
// path: “/users”,
// component: Users,
// meta: {
// auth: true,
// },
// // beforeEnter(to, from, next) {
// // if (window.isLogin) {
// // next();
// // } else {
// // next(“/login?redirect=” + to.fullPath);
// // }
// // },
// },
// { path: “/userinfo/:id”, component: UserInfo, props: true },
// { path: “/rights”, component: Rights },
// { path: “/goods”, component: Goods },
// { path: “/orders”, component: Orders },
// { path: “/settings”, component: Settings },
// ],
// },
// ]);
this.

r

o

u

t

e

r

.

p

u

s

h

(

t

h

i

s

.

router.push(this.

router.push(this.route.query.redirect);
} else {
this.$router.push(“/”);
}
}

Now that the code in the front-end vue has been modified, we will deploy the content of the page to the node.js server.

And in the above code, we use sessionStorage to save the logged in user information, instead of using isLogin under window

The code under the corresponding data content also needs to be modified:

const Login = {
data() {
return {
isLogin: window.sessionStorage.getItem(“isLogin”),
};
},

The code in the routing guard is modified as follows:

jsrouter.beforeEach((to, from, next) => {
//to: which page to go to, which page from comes from, next to continue execution.
if (window.sessionStorage.getItem(“isLogin”)) {
//The user has logged in
if (to.path === “/login”) {
// The user has already logged in, but visits the login page again. Here he jumps directly to the user list page.
next(“/”);
} else {
//The user has logged in and accessed other pages, then run the access

 next();
      }
    } else {
      //The user is not logged in and is accessing the login page, then run to access the login page.
      if (to.path === "/login") {
        next();
      } else {
        //The user is not logged in and jumps to the login page when accessing other pages.
        next("/login?redirect=" + to.fullPath);
      }
    }
  });

In the above code, we also obtain login information through sessionStorage.

The complete code of index.html is as follows:

Case based on vue-router

Of course, the directory structure of the project has been adjusted to some extent, as shown in the figure below:

Under the web directory, index.html is stored, and under the webserver directory, the node code is stored.

Let’s take a look at the specific node code implementation.

The code in the app.js file is as follows:

const path = require(“path”);
//Import the module that handles history mode
const history = require(“connect-history-api-fallback”);
const express = require(“express”);
const app = express();
//Register middleware to handle history mode
// app.use(history())
//Middleware that processes static resources and processes index.html in the web directory
app.use(express.static(path.join(__dirname, “…/web”)));
app.listen(3000, () => {
console.log(“Server started”);
});

The connect-history-api-fallback module is installed as follows (note that this module has not been used in the above code)

npm install –save connect-history-api-fallback
1
You also need to install express below

npm install express
1
Start service

node app.js
1
Now enter: http://localhost:3000 in the address bar to access the website.

And when we click the menu on the left, we can switch pages. When we click “About” at the same time, the content in the NotFound component will appear.

After testing, it seems that there is no problem, so what is the reason? Think about it, how routing works when we click on the left menu?

Because now we have turned on the history mode of routing, and this mode completes the routing operation through the api in the history in HTML5, that is, when we click the menu, we modify the address through the history.pushState() method. The address in the column realizes the switching of components, and also saves the address in the history record (that is, you can click the back button in the browser to perform operations such as going back), but it does not send a request to the server.

So now the entire operation is completed on the client side.

But what happens when I refresh the browser?

The meaning of the above picture is that when you click the refresh button in the browser, a request will be sent to the server, asking the node server to process this address, but the server does not process the address, so the server will return 404

The above is the problem that occurs if vue-router turns on the history mode.

To solve this problem, just enable the connect-history-api-fallback module on the server side, as shown in the following code:

const path = require(“path”);
//Import the module that handles history mode
const history = require(“connect-history-api-fallback”);
const express = require(“express”);
const app = express();
//Register middleware to handle history mode
app.use(history());
//Middleware for processing static resources
app.use(express.static(path.join(__dirname, “…/web”)));
app.listen(3000, () => {
console.log(“Server started”);
});

After the server code is modified, the server must restart node app.js

Then after testing it was found that there was no problem.

So now you think about it, what is the specific way of working?

When we enable support for history mode on the server side, we refresh the browser and send a request to the server, for example: http://localhost:3000/orders

When the server receives the request, it will enable the history mode for the server. Then the server will check that the page accessed according to the request does not exist, so the index.html of the single-page application will be returned to the browser. After the browser receives the index.html page, it will determine the routing address and find that the address is orders, so it will load the component content corresponding to the address.