Skip to content

URL路由历史模式

TIP

系统默认使用 Hash 历史模式,这种模式URL内会带有 # 号,当你有 SEO 需求或认为它不美观时,可以参考以下文档隐藏 # 号。

我们提供了 Nuxt 工程,该工程URL不含 # 号,推荐管理员后台无需隐藏 # 号,而用户端使用 Nuxt工程 即可。

第一步:修改代码

找到 web\src\router\index.ts 文件,将 createWebHashHistory 修改为 createWebHistory

原来的:

ts
import { createRouter, createWebHashHistory } from 'vue-router'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { staticRoutes } from '/@/router/static'
import { loading } from '/@/utils/loading'

const router = createRouter({
    history: createWebHashHistory(),
    routes: staticRoutes,
})

修改为:

ts
import { createRouter, createWebHistory } from 'vue-router'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { staticRoutes } from '/@/router/static'
import { loading } from '/@/utils/loading'

const router = createRouter({
    history: createWebHistory(),
    routes: staticRoutes,
})

此时,开发环境已经可以使用不带 # 号的 URL 进行访问了,但是在线上环境中,直接访问 domain.com/user/login 会提示 404,这是因为没有适当的服务器配置,请继续参考下文进行配置。

第二步:配置服务器

以下服务器配置,已经包含 ThinkPHP 的伪静态规则,所以请注意,一旦配置就不再需要配置 ThinkPHP 的伪静态规则了。

[ Nginx ] 配置

ini
# Nginx站点配置文件
server {
    listen        80;
    server_name   ba.com;
    root   "D:/WWW/ba.com/public";

    # 找到 "/" 的代码块,没有则定义
    location / {

        # 将 index.html 放在第一位可以实现隐藏 index.html
        index index.html index.php error/index.html;

        # 这一段为 URL重写规则 请确保存在
        set $server 0;
        if ($request_uri ~* "server=1") {
            set $server 1;
        }
        if ($http_server) {
            set $server 1;
        }
        if ($server = 1) {
            rewrite  ^(.*)$  /index.php?s=/$1  last;
            break;
        }
        try_files $uri $uri/ /index.html;
        # 结束
    }

    # 已省略余下代码
}

[ Apache ] 配置

  1. httpd.conf 配置文件中加载了 mod_rewrite.so 模块
  2. 站点对应的 conf 文件中 AllowOverride NoneNone 改为 All
  3. 把下面的内容保存为 .htaccess 文件放到应用入口文件的同级目录下(public目录
ini
<IfModule mod_rewrite.c>
    Options +FollowSymlinks -Multiviews
    RewriteEngine On
    RewriteBase /

    RewriteRule ^index\.html$ - [L]
    RewriteRule ^index\.php$ - [L]

    RewriteCond %{QUERY_STRING} server=1 [OR,NC]
    RewriteCond %{HTTP:server} true
    RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L]

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.html [L]
</IfModule>

[ IIS ] 配置

  1. 安装 url-rewrite
  2. 站点根目录(public目录)建立 web.Config 文件,写入以下内容:
xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <!-- 服务端请检测 -->
                <rule name="BuildAdmin" stopProcessing="true">
                    <match url="^(.*)$" ignoreCase="false" />
                    <conditions logicalGrouping="MatchAny">
                        <add input="{QUERY_STRING}" pattern="server=1" ignoreCase="true" />
                        <add input="{HTTP_SERVER}" pattern="true" ignoreCase="true" />
                    </conditions>
                    <action type="Rewrite" url="index.php/{R:1}" appendQueryString="true" />
                </rule>
                <!-- 服务端请求检测结束 -->

                <!-- 前端请求检测-转到index.html -->
                <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>
        <!-- 默认文档配置,index.html排第一 -->
        <defaultDocument>
            <files>
                <clear />
                <add value="index.html" />
                <add value="index.php" />
                <add value="Default.htm" />
                <add value="Default.asp" />
                <add value="index.htm" />
                <add value="iisstart.htm" />
            </files>
        </defaultDocument>
    </system.webServer>
</configuration>

常见问题

我曾对外分发带有#的链接

如何保证,以往带有 # 的链接在短时间内,依旧有效? 在 web/src/App.vue 文件内,获取当前 url,如果带有 hash 进行跳转即可

ts
onMounted(() => {
    iconfontInit()
    terminal.init()

    // 添加的检测 hash 代码
    if (window.location.hash) {
        window.location.href = window.location.hash.replace('#', '')
    }
    // 结束

    // Modules onMounted mark, Please do not remove.
})

允许跨域(如果有跨域需求)

通过以上的配置,OPTIONS 请求不能再正常的被程序放行,可以额外增加允许 OPTIONS 请求的代码`

[ Nginx ] 配置

ini
# 放行 OPTIONS(如果有跨域需求)
# 请将 if 代码块,合入到之前的 location / 代码块
location / {
    # ...
    if ($request_method ~* OPTIONS) {
        add_header Access-Control-Max-Age '86400';
        add_header Access-Control-Allow-Origin '*';
        add_header Access-Control-Allow-Headers '*';
        add_header Access-Control-Allow-Credentials 'true';
        add_header Access-Control-Allow-Methods 'GET, POST, PATCH, PUT, DELETE, OPTIONS';
        return 204;
    }
    # ...
}