Vue router uses History mode to cause page requests 404

The default hash mode of Vue router uses the hash of the URL to simulate a complete URL, so when the URL changes, the page will not be reloaded.

If we don't want ugly hash, we can use the history mode of routing, which makes full use of history Pushstate API to complete URL jump without reloading the page.

const router = new VueRouter({
  mode: 'history',
  routes: [...]
})

When you use the history mode, the url looks like a normal url, for example http://yoursite.com/user/id , also beautiful!

However, in order to play this mode well, the background configuration support is also required. Because our application is a single page client application, if the background is not configured correctly, when users access it directly in the browser http://oursite.com/user/id It will return 404, which is not good-looking.

Therefore, you need to add a candidate resource on the server that covers all situations: if the URL does not match any static resources, it should return the same index HTML page, which is the page your app depends on.

Back end configuration example

Note: the following example assumes that you are serving this application in the root directory. If you want to deploy to a subdirectory, you need to use publicPath option for Vue CLI And related router base property . You also need to adjust the root directory in the following example to a subdirectory (for example, replace RewriteBase / with RewriteBase /name of your subfolder/).

Apache

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ./index.html [L]
</IfModule>

Except mod_rewrite, you can also use FallbackResource.

nginx

location / {
  try_files $uri $uri/ /index.html;
}

Native node JS

const http = require('http')
const fs = require('fs')
const httpPort = 80

http.createServer((req, res) => {
  fs.readFile('index.htm', 'utf-8', (err, content) => {
    if (err) {
      console.log('We cannot open "index.htm" file.')
    }

    res.writeHead(200, {
      'Content-Type': 'text/html; charset=utf-8'
    })

    res.end(content)
  })
}).listen(httpPort, () => {
  console.log('Server listening on: http://localhost:%s', httpPort)
})

# Based on node JS Express

For node Js/express, please consider using Connect history API fallback Middleware.

#Internet Information Services (IIS)

  1. Installation IIS UrlRewrite
  2. Create a web Config file, as follows:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Handle History Mode and custom 404/500" stopProcessing="true">
          <match url="(.*)" />
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
          </conditions>
          <action type="Rewrite" url="/" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

#Caddy

rewrite {
    regexp .*
    to {path} /
}

# Firebase host

On your firebase JSON:

{
  "hosting": {
    "public": "dist",
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}

warning

Give me a warning, because after doing so, your server will no longer return the 404 error page, because for all paths, it will return index HTML file. To avoid this situation, you should cover all routing situations in Vue applications, and then give a 404 page.

const router = new VueRouter({
  mode: 'history',
  routes: [
    { path: '*', component: NotFoundComponent }
  ]
})

Or, if you use node JS server, you can use the server route to match the incoming URL, and return 404 when no route is matched to achieve fallback. For more details, please refer to Vue server rendering document.

Tags: Vue.js

Posted by CraigRoberts on Wed, 01 Jun 2022 02:45:05 +0530