使用aspnetcore前后端分离开发,你一定要知道这个

用过Vue单页面应用开发的,一定都知道Vue-router这个路由组件,它支持hashhistory两种模式。

HTML5 History 模式

vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。

如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。

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

当你使用 history 模式时,URL 就像正常的 url,例如 http://yoursite.com/user/id,也好看!
不过这种模式要玩好,还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id 就会返回 404,这就不好看了。

所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。

aspnetcore使用Vuerouter history模式如何生产部署

今天我们的目的就是如何使用history模式,让url地址更加简洁美观,为了更完整的演示,从头手把手演示一遍。

创建vue项目

首先安装nodejs,然后执行下面的npm命令创建vue3项目,跟着提示选择是或否即可完成项目的创建。本次创建的项目名称为vue-project

npm init vue@3

创建aspnetcore的webapi项目

如下图选择ASP.Net Core WebApi项目,项目名称为TestHistory,目录选择和上面Vue项目同属一个文件夹下。

配置History模式

配置前端

vscode打开前端项目,找到router配置


由于这里创建的是Vue3项目模板,模板自动配置好的vuerouter4,
其实下面这种是一样的。详情参考,

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

如果要使用hash模式,则使用createWebHashHistory函数创建。

配置后端

如果我们的前端和后端用的是同一个域名,也就是部署在同一个目录下,则应该将前端编译后的Html页面使用aspnetcore的静态资源进行托管,而不是直接放到根目录下。

https://www.bilibili.com/read/cv16007583
https://www.bilibili.com/read/cv16022187
https://www.bilibili.com/read/cv16022610
https://www.bilibili.com/read/cv16022558
https://www.bilibili.com/read/cv16022525
https://www.bilibili.com/read/cv16022490
https://www.bilibili.com/read/cv16022187
https://www.bilibili.com/read/cv16094753
http://baijiahao.baidu.com/builder/preview/s?id=1729956495361951696
https://www.bilibili.com/read/cv16120620
https://zhuanlan.zhihu.com/p/498377792
http://baijiahao.baidu.com/builder/preview/s?id=1729992337950025166
http://baijiahao.baidu.com/builder/preview/s?id=1730067684555668223
https://zhuanlan.zhihu.com/p/498493644
https://www.bilibili.com/read/cv16133002
https://zhuanlan.zhihu.com/p/498580777
http://baijiahao.baidu.com/builder/preview/s?id=1730070464688039792
http://baijiahao.baidu.com/builder/preview/s?id=1730076425820965522
https://www.bilibili.com/read/cv16135957
https://www.bilibili.com/read/cv16135985
http://baijiahao.baidu.com/builder/preview/s?id=1730145120153966761


http://baijiahao.baidu.com/builder/preview/s?id=1730146708498458051
https://www.bilibili.com/read/cv16145218
http://baijiahao.baidu.com/builder/preview/s?id=1730416170972889395
https://www.bilibili.com/read/cv16190443
https://zhuanlan.zhihu.com/p/500443737
http://baijiahao.baidu.com/builder/preview/s?id=1730418646803373527
https://www.bilibili.com/read/cv16192158
https://zhuanlan.zhihu.com/p/500469866
http://baijiahao.baidu.com/builder/preview/s?id=1730427767581251359
https://zhuanlan.zhihu.com/p/500553747
http://baijiahao.baidu.com/builder/preview/s?id=1730530756613653139
http://baijiahao.baidu.com/builder/preview/s?id=1730531925272766956
https://zhuanlan.zhihu.com/p/501356164
https://zhuanlan.zhihu.com/p/501363814
https://www.bilibili.com/read/cv16214431
https://www.bilibili.com/read/cv16214021
http://baijiahao.baidu.com/builder/preview/s?id=1730611465234814121
http://baijiahao.baidu.com/builder/preview/s?id=1730612525906973029
http://baijiahao.baidu.com/builder/preview/s?id=1730612896521091369
http://baijiahao.baidu.com/builder/preview/s?id=1730613350304325881
https://zhuanlan.zhihu.com/p/501944415
https://zhuanlan.zhihu.com/p/501958666
https://zhuanlan.zhihu.com/p/501967687
https://zhuanlan.zhihu.com/p/501976988
https://www.bilibili.com/read/cv16230570
https://www.bilibili.com/read/cv16230293
https://www.bilibili.com/read/cv16230040
https://www.bilibili.com/read/cv16229697

后端首先要添加app.UseStaticFiles();以支持静态资源托管,然后创建该中间件默认的静态资源文件目录wwwroot

部署

将webapi项目发布到本地


vue项目执行npm run build编译前端代码,将dist目录下的文件拷贝到到webapi发布后的wwwroot目录下,

IIS新建一个站点,这里使用8080端口


别忘记安装Hosting Bundle

如果一切顺利,打开http://localhost:8080你应该会看到这个页面。


点击about还会显示下面这个页面,而且地址是http://localhost:8080/about,这不就是history模式的效果吗!

什么都没做,效果就达到了?

别急的得意,在http://localhost:8080/about这个地址下,刷新下网页试试。


卧槽,404了。

先解释下为什么会这样,当你访问http://localhost:8080时由于iis默认是设置了默认文档


当找不到你请求的资源时,它会尝试检查目录下的默认文档是否存在,按先后顺序检查,发现存在index.html所以就返回浏览器了,所以能够正常显示;当你点击about时,其实只是触发了页面的一个事件,页面有变化,url也变化了,但浏览器压根刷新。当你手动刷新http://localhost:8080/about时,就向后端发起这个地址的Get请求,很明显,我们没有写任何Controller来匹配这个路由,wwwroot目录下也不存在about/index.html当然返回404了。

如何配置history模式,而不导致404

Vuerouter官方文档给出了部分后端服务器的配置方式 后端配置例子
这里只展示aspnetcore常用的服务器

nginx

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

Internet Information Services (IIS)

  1. 安装 IIS UrlRewrite(opens new window)
  2. 在你的网站根目录中创建一个 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>

nginx的由于没有环境,没有测试,应该没问题,配置也比较简单。
iis的根据文档做一遍,UrlRewrite可以理解为是一个中间件,会对请求拦截,对符合规则的url进行路径重写,可行。

当然我要做的不是上面的任何一种,因为我们的站点可能会部署到各种各样的服务器,每次换服务器都需要不同的配置来实现,很繁琐,既然我们aspnetcore拥有强大的中间件系统,为什么不让aspnetcore来做这件事呢,不再依赖不同服务器的配置方案,实现一次编码,到处运行,在之前的文章中有介绍过如何处理404 《ASP.NETCore统一处理404错误都有哪些方式?》
那我们就在404的处理逻辑里实现其实就好了。

直接上代码

app.MapFallback(async (context) =>
{
    var phpath = Path.Join(app.Environment.WebRootPath, context.Request.Path);
    var name = Path.Combine(Path.GetDirectoryName(phpath)!, "index.html");
    if (File.Exists(name))
    {
        context.Response.StatusCode = 200;
        await context.Response.SendFileAsync(name);
    }
});

1.当进入404处理逻辑时,首先拼接访问路径
2.检查访问的路径所属的文件夹下是否存在index.html文件
3.当文件存在,则修改响应码,返回该文件。
4.不存在,什么也不干(这里其实可以做个友好提示页面)。
重新发布,测试,不管如何刷新,都能正常显示了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值