不同的历史模式
创建路由实例时的 history
选项允许我们在不同的历史模式之间选择。
哈希模式
哈希历史模式使用 createWebHashHistory()
创建
import { createRouter, createWebHashHistory } from 'vue-router'
const router = createRouter({
history: createWebHashHistory(),
routes: [
//...
],
})
它在实际 URL 之前使用一个哈希字符 (#
) 来内部传递。由于 URL 的这一部分永远不会发送到服务器,因此它不需要服务器级别的任何特殊处理。但是,它对 SEO 影响很大。如果这是你的顾虑,请使用 HTML5 历史模式。
HTML5 模式
HTML5 模式使用 createWebHistory()
创建,是推荐的模式
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(),
routes: [
//...
],
})
使用 createWebHistory()
时,URL 将看起来“正常”,例如 https://example.com/user/id
。漂亮!
但是,这里有一个问题:由于我们的应用程序是一个单页面的客户端应用程序,如果没有适当的服务器配置,用户如果直接在浏览器中访问 https://example.com/user/id
,就会收到 404 错误。现在这很丑。
不用担心:要解决这个问题,你只需要在服务器上添加一个简单的通配符回退路由。如果 URL 与任何静态资产不匹配,它应该提供你的应用程序所在的同一个 index.html
页面。再次漂亮!
内存模式
内存历史模式不假设浏览器环境,因此不与 URL 交互也不自动触发初始导航。这使其非常适合 Node 环境和 SSR。它使用 createMemoryHistory()
创建,需要你在调用 app.use(router)
后推送初始导航。
import { createRouter, createMemoryHistory } from 'vue-router'
const router = createRouter({
history: createMemoryHistory(),
routes: [
//...
],
})
虽然不推荐,但你可以在浏览器应用程序中使用此模式,但请注意将没有历史记录,这意味着你将无法后退或前进。
示例服务器配置
注意:以下示例假设你从根文件夹提供你的应用程序。如果你部署到子文件夹,你应该使用 Vue CLI 的 publicPath
选项 和相关的 路由的 base
属性。你还需要调整以下示例以使用子文件夹而不是根文件夹(例如,将 RewriteBase /
替换为 RewriteBase /name-of-your-subfolder/
)。
Apache
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
除了 mod_rewrite
,你还可以使用 FallbackResource
。
nginx
location / {
try_files $uri $uri/ /index.html;
}
原生 Node.js
const http = require('http')
const fs = require('fs')
const httpPort = 80
http
.createServer((req, res) => {
fs.readFile('index.html', 'utf-8', (err, content) => {
if (err) {
console.log('We cannot open "index.html" file.')
}
res.writeHead(200, {
'Content-Type': 'text/html; charset=utf-8',
})
res.end(content)
})
})
.listen(httpPort, () => {
console.log('Server listening on: https://127.0.0.1:%s', httpPort)
})
Express 与 Node.js
对于 Node.js/Express,请考虑使用 connect-history-api-fallback 中间件。
Internet Information Services (IIS)
- 安装 IIS UrlRewrite
- 在你的站点根目录中创建一个
web.config
文件,内容如下
<?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 v2
try_files {path} /
Caddy v1
rewrite {
regexp .*
to {path} /
}
Firebase 托管
将此添加到你的 firebase.json
中
{
"hosting": {
"public": "dist",
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
Netlify
创建一个 _redirects
文件,该文件包含在你的部署文件中
/* /index.html 200
在 vue-cli、nuxt 和 vite 项目中,此文件通常位于名为 static
或 public
的文件夹下。
你可以在 Netlify 文档 中了解更多关于语法的知识。你也可以 创建一个 netlify.toml
来将重定向与其他 Netlify 功能结合起来。
Vercel
在你的项目的根目录下创建一个 vercel.json
文件,内容如下
{
"rewrites": [{ "source": "/:path*", "destination": "/index.html" }]
}
警告
这里有一个警告:你的服务器将不再报告 404 错误,因为所有未找到的路径现在都提供你的 index.html
文件。要解决这个问题,你应该在你的 Vue 应用程序中实现一个通配符路由来显示一个 404 页面
const router = createRouter({
history: createWebHistory(),
routes: [{ path: '/:pathMatch(.*)', component: NotFoundComponent }],
})
或者,如果你使用的是 Node.js 服务器,你可以使用服务器端的路由来实现回退,以匹配传入的 URL,如果路由不匹配,则返回 404。查看 Vue 服务器端渲染文档 以了解更多信息。