nginx configuration for vue-router in history mode

本文介绍如何使用Vue Router的History模式来实现美观的URL,并解决直接访问这些URL时出现的404问题。通过配置不同的服务器(如Apache、Nginx、Node.js等),可以实现即使在直接访问的情况下也不会出现错误页面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Here's how I did it according to the official document

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

You can refer to vue-router's official document for more details.

First, introduction of HTML 5 history mode

HTML5 History Mode

The default mode for vue-router is hash mode - it uses the URL hash to simulate a full URL so that the page won't be reloaded when the URL changes.

To get rid of the hash, we can use the router's history mode, which leverages the history.pushState API to achieve URL navigation without a page reload:

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

When using history mode, the URL will look "normal," e.g. http://oursite.com/user/id. Beautiful!

Here comes a problem, though: Since our app is a single page client side app, without a proper server configuration, the users will get a 404 error if they access http://oursite.com/user/id directly in their browser. Now that's ugly.

Not to worry: To fix the issue, all you need to do is add a simple catch-all fallback route to your server. If the URL doesn't match any static assets, it should serve the same index.html page that your app lives in. Beautiful, again!

Then, the configurations for all kinds of servers.

Example Server Configurations

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>

Instead of mod_rewrite, you could 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)
})
Express with Node.js

For Node.js/Express, consider using connect-history-api-fallback middleware.

Internet Information Services (IIS)
  1. Install IIS UrlRewrite

  2. Create a web.config file in the root directory of your site with the following:

<?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 hosting

Add this to your firebase.json:

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

Caveat

There is a caveat to this: Your server will no longer report 404 errors as all not-found paths now serve up your index.html file. To get around the issue, you should implement a catch-all route within your Vue app to show a 404 page:

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

Alternatively, if you are using a Node.js server, you can implement the fallback by using the router on the server side to match the incoming URL and respond with 404 if no route is matched. Check out the Vue server side rendering documentation for more information.

转载于:https://my.oschina.net/fqzhang/blog/1811268

### Vue3 History Mode Deep Nested Resources Access Solution In a Vue3 project, when using the history mode of vue-router, accessing deeper nested resources can lead to issues where refreshing or directly navigating to these routes results in 404 errors. This problem arises because web servers do not recognize client-side routing and attempt to serve static files that don't exist on the server. To resolve this issue, configuring the server correctly is essential so it always serves the `index.html` file for any route while allowing HTML5 history pushstate API fallbacks[^1]. For development environments like Vite or Webpack dev servers, configuration adjustments are usually unnecessary as they handle SPA (Single Page Application) routing automatically. For production deployments, depending on the hosting platform used, different configurations apply: #### Apache Server Configuration Add an `.htaccess` file at your root directory with the following content: ```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> ``` #### Nginx Server Configuration Modify the nginx.conf or site-specific config within `/etc/nginx/sites-available/your-site-name`, adding location block inside http/server context: ```nginx location / { try_files $uri $uri/ /index.html; } ``` By ensuring proper server setup, users will be able to navigate through deeply nested paths without encountering resource loading failures even upon page refreshes or direct URL accesses. --related questions-- 1. How does one configure IIS for supporting Vue Router's history mode? 2. What modifications should be made in Firebase Hosting settings for Vue applications using history mode? 3. Can you provide examples of how to set up Express.js middleware for handling Vue Router’s history mode properly? 4. Is there a way to test if my server has been configured correctly for Vue Router history mode before deployment?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值