ASP.NET Core 奇淫技巧之SPA部署

2020-08-28 10:04:33 浏览数 (1)

一.前言

咕咕咕,许久不见 hhh,晓晨的 ASP.NET Core 奇淫技巧又开新篇章了,今天给大家带来我在 ASP.NET Core 前后端分离开发中,在部署过程中的一些技巧。前后端分离的项目做过也有好几个了,有简单的,有复杂的。有一些简单的项目部署可能会比较的简便,下面给大家讲讲我所用过的部署方式。

二.Kestrel 全托法

此方法是将前端项目发布后,Copy 到后端 WebApi 项目下的 wwwroot 目录下(没有就新建),让 Kestrel 来同时提供 api 和 前端静态资源服务,适合内部使用小型项目,不建议用在中大型项目。

此方法的限制:前端必须使用基于 hash 的路由方式,基于 history 的不行;后端 WebApi 项目需要添加静态文件中间件和默认文件中间件

代码语言:javascript复制
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseDefaultFiles();
    app.UseStaticFiles();
}

这样进行发布后,即便是打包成 Docker 镜像也只需要一个,比较方便。

此方法部署没有跨域问题,后端无需配置跨域,没有额外的 HTTP OPTIONS 请求。

三.Nginx 全代理法

此方法是 nginx 根据请求路径来指向前端资源或者代理后端 api,和上面的方法一样,也只使用一个域名,没有跨域问题、

此方法的限制:后端必须设置给 api 设置统一的前缀。

api 的前缀,是自定义的,一般以 api作为前缀,例如:/api/apple/add

安利一个快速为所有 api 设置前缀方法,通过在 MVC 框架启动时给所有 api 增加一个 RouteAttribute 来实现。

定义一个类实现 IApplicationModelConvention 接口,遍历所有 Controller 来为它们加上一个前缀路由

代码语言:javascript复制
public class RouteConvention: IApplicationModelConvention
{
    private readonly RouteAttribute _apiPrefix;

    public XlRouteConvention(RouteAttribute apiPrefix)
    {
        _apiPrefix = apiPrefix;
    }
    public void Apply(ApplicationModel application)
    {
        foreach (var controller in application.Controllers)
        {
            // 已经标记了 RouteAttribute 的 Controller
            var matchedSelectors = controller.Selectors.Where(x => x.AttributeRouteModel != null).ToList();
            foreach (var selectorModel in matchedSelectors)
            {
                var attrPrefix =
                    new AttributeRouteModel(_apiPrefix);
                selectorModel.AttributeRouteModel = AttributeRouteModel.CombineAttributeRouteModel(attrPrefix, selectorModel.AttributeRouteModel);
            }

            // 没有标记 RouteAttribute 的 Controller
            var unmatchedSelectors = controller.Selectors.Where(x => x.AttributeRouteModel == null).ToList();
            foreach (var selectorModel in unmatchedSelectors)
                // 添加一个 路由前缀
                selectorModel.AttributeRouteModel = new AttributeRouteModel(_apiPrefix);
        }
    }
}

使用:

代码语言:javascript复制
services.AddControllers(op =>
{
    op.Conventions.Insert(0, new RouteConvention(new RouteAttribute("api")));
})

这样就会在所有的接口上都加一个指定的前缀,无需手动去给每个接口设置路由。

最后就是 nginx 的配置了:

代码语言:javascript复制
location /api {
	proxy_redirect     off;
	proxy_set_header   Host             $host;
	proxy_set_header   X-Real-IP        $remote_addr;
	proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
	proxy_pass http://localhost:5000;
}

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

需要自行设置 root(前端资源根目录) 和 proxy_pass(后端api地址) 的值

四.分开部署法

此方法顾名思义就是 后端API 和 前端程序分开部署,对于前后端没有任何限制。

此方法的限制:需要给前端和后端分配单独的域名,具有跨域问题需要配置跨域,因为有跨域,在调用API时还有会额外的 HTTP OPTIONS 请求。

五.结束

上面三种都是我使用的 SPA 程序部署方法,我个人比较喜欢的和经常使用的是Nginx全代理方法,如果有更好的方法欢迎大家和我讨论。

0 人点赞