aspnetcore前后端分离开发(什么是aspnetcore)
用过Vue单页面应用开发的,一定都知道Vue-router这个路由组件,它支持hash和history两种模式。
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的静态资源进行托管,而不是直接放到根目录下。 后端首先要添加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)
- 安装 IIS UrlRewrite(opens new window)
- 在你的网站根目录中创建一个 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.不存在,什么也不干(这里其实可以做个友好提示页面)。 重新发布,测试,不管如何刷新,都能正常显示了。
源码
Github上获取:https://github.com/SpringHgui/TestHistory
下一章:Halo 开源项目(halo是什么意思)
项目简介Halo 是一个优秀的开源博客发布应用,在 GitHub 上广受好评,正好最近在练习写博客,借此记录一下学习 Halo 的过程。项目下载从 GitHub 上拉取项目源码,Halo 从 1.4 ...