日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

ASP.NET Core 集成 React SPA 应用

發布時間:2023/12/4 asp.net 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ASP.NET Core 集成 React SPA 应用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

AgileConfig的UI使用react重寫快完成了。上次搞定了基于jwt的登錄模式(AntDesign Pro + .NET Core 實現基于JWT的登錄認證),但是還有點問題。現在使用react重寫后,agileconfig成了個確確實實的前后端分離項目。那么其實部署的話要分2個站點部署,把前端build完的靜態內容部署在一個網站,把server端也部署在一個站點。然后修改前端的baseURL讓spa的api請求都指向server的網站。
這樣做也不是不行,但是這不符合AgileConfig的精神,那就是簡單。asp.net core程序本身其實就是一個http服務器,所以完全可以把spa網站使用它來承載。這樣只需要部署一個站點就可以同時跑spa跟后端server了。
其實最簡單的辦法就是把build完的文件全部丟wwwroot文件夾下面。然后訪問:

http://localhost:5000/index.html

但是這樣我們的入口是index.html,這樣看起來比較別扭,不夠友好。而且這些文件直接丟在wwwroot的根目錄下,會跟網站其他js、css等內容混合在一起,也很混亂。
那么下面我們就要解決這兩個文件,我們要達到的目的有2個:

  • spa的入口path友好,比如http://localhost:5000/ui

  • spa靜態文件存放的目錄獨立,比如存放在wwwroot/ui文件夾下,或者別的什么目錄下。

  • 要實現以上內容只需要一個自定義中間件就可以了。

    wwwroot\ui

    wwwroot\ui

    我們把build完的靜態文件全部復制到wwwroot\ui文件夾內,以跟其他靜態資源進行區分。當然你也可以放在任意目錄下,只要是能讀取到就可以。

    ReactUIMiddleware

    namespace AgileConfig.Server.Apisite.UIExtension {public class ReactUIMiddleware{private static Dictionary<string, string> _contentTypes = new Dictionary<string, string>{{".html", "text/html; charset=utf-8"},{".css", "text/css; charset=utf-8"},{".js", "application/javascript"},{".png", "image/png"},{".svg", "image/svg+xml"},{ ".json","application/json;charset=utf-8"},{ ".ico","image/x-icon"}};private static ConcurrentDictionary<string, byte[]> _staticFilesCache = new ConcurrentDictionary<string, byte[]>();private readonly RequestDelegate _next;private readonly ILogger _logger;public ReactUIMiddleware(RequestDelegate next,ILoggerFactory loggerFactory){_next = next;_logger = loggerFactory.CreateLogger<ReactUIMiddleware>();}private bool ShouldHandleUIRequest(HttpContext context){return context.Request.Path.HasValue && context.Request.Path.Value.Equals("/ui", StringComparison.OrdinalIgnoreCase);}private bool ShouldHandleUIStaticFilesRequest(HttpContext context){//請求的的Referer為 0.0.0.0/ui ,以此為依據判斷是否是reactui需要的靜態文件if (context.Request.Path.HasValue && context.Request.Path.Value.Contains(".")){context.Request.Headers.TryGetValue("Referer", out StringValues refererValues);if (refererValues.Any()){var refererValue = refererValues.First();if (refererValue.EndsWith("/ui", StringComparison.OrdinalIgnoreCase)){return true;}}}return false;}public async Task Invoke(HttpContext context){const string uiDirectory = "wwwroot/ui";//handle /ui requestvar filePath = "";if (ShouldHandleUIRequest(context)){filePath = uiDirectory + "/index.html";}//handle static files that Referer = xxx/uiif (ShouldHandleUIStaticFilesRequest(context)){filePath = uiDirectory + context.Request.Path;}if (string.IsNullOrEmpty(filePath)){await _next(context);}else{//output the file bytesif (!File.Exists(filePath)){context.Response.StatusCode = 404;return;}context.Response.OnStarting(() =>{var extType = Path.GetExtension(filePath);if (_contentTypes.TryGetValue(extType, out string contentType)){context.Response.ContentType = contentType;}return Task.CompletedTask;});await context.Response.StartAsync();byte[] fileData = null;if (_staticFilesCache.TryGetValue(filePath, out byte[] outfileData)){fileData = outfileData;}else{fileData = await File.ReadAllBytesAsync(filePath);_staticFilesCache.TryAdd(filePath, fileData);}await context.Response.BodyWriter.WriteAsync(fileData);return;}}} }

    大概解釋下這個中間件的思路。這個中間件的邏輯大概是分量部分。
    1.攔截請求的路徑為/ui的請求,直接從ui文件夾讀取index.html靜態文件的內容然后輸出出去,這就相當于直接訪問/index.html。但是這樣的路徑形式看起來更加友好。
    2.攔截react spa需要的靜態資源文件,比如css文件,js文件等。這里比較麻煩,因為spa拉靜態文件的時候path是直接從網站root開始的,比如http://localhost:5000/xxx.js,那么怎么區分出來這個文件是react spa需要的呢?我們判斷一下請求的Referer頭部,如果Referer的path是/ui,那么就說明是react spa需要的靜態資源,同樣從ui文件夾去讀取。
    這里還需要給每個response設置指定的contentType不然瀏覽器無法準確識別資源。

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}else{app.UseMiddleware<ExceptionHandlerMiddleware>();}app.UseMiddleware<ReactUIMiddleware>();......}

    在Startup類的Configure方法內使用這個中間件。這樣我們的改造就差不多了。

    運行一下

    訪問下http://localhost:5000/ui 可以看到spa成功加載進來了。

    總結

    為了能讓asp.net core承載react spa應用,我們使用一個中間件進行攔截。當訪問對應path的時候從本地文件夾內讀取靜態資源返回給瀏覽器,從而完成spa所需要資源的加載。這次使用react spa來演示,其實換成任何spa應用都是一樣的操作。
    代碼在這:ReactUIMiddleware

    關注我的公眾號一起玩轉技術

    創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的ASP.NET Core 集成 React SPA 应用的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。