激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - ASP.NET教程 - ASP.NET Core 集成 React SPA應用的步驟

ASP.NET Core 集成 React SPA應用的步驟

2021-12-13 19:26Agile.Zhou ASP.NET教程

這篇文章主要介紹了ASP.NET Core 集成 React SPA應用的步驟,幫助大家更好的理解和學習使用.net技術,感興趣的朋友可以了解下

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個:

  1. spa的入口path友好,比如http://localhost:5000/ui
  2. spa靜態文件存放的目錄獨立,比如存放在wwwroot/ui文件夾下,或者別的什么目錄下。

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

wwwroot\ui

wwwroot\ui

ASP.NET Core 集成 React SPA應用的步驟

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

ReactUIMiddleware

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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 request
            var filePath = "";
            if (ShouldHandleUIRequest(context))
            {
                filePath = uiDirectory + "/index.html";
            }
            //handle static files that Referer = xxx/ui
            if (ShouldHandleUIStaticFilesRequest(context))
            {
                filePath = uiDirectory + context.Request.Path;
            }
 
            if (string.IsNullOrEmpty(filePath))
            {
                await _next(context);
            }
            else
            {
                //output the file bytes
 
                if (!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不然瀏覽器無法準確識別資源。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider)
     {
         if (env.IsDevelopment())
         {
             app.UseDeveloperExceptionPage();
         }
         else
         {
             app.UseMiddleware<ExceptionHandlerMiddleware>();
         }
         app.UseMiddleware<ReactUIMiddleware>();
     
     ...
     ...
 
     }

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

運行一下

ASP.NET Core 集成 React SPA應用的步驟

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

總結

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

以上就是ASP.NET Core 集成 React SPA應用的步驟的詳細內容,更多關于ASP.NET Core 集成 React SPA的資料請關注服務器之家其它相關文章!

原文鏈接:https://www.cnblogs.com/kklldog/p/netcore-embed-react.html

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25
主站蜘蛛池模板: 欧美成人一区二区三区电影 | 99精品在线视频观看 | 福利免费视频 | 欧美一级α| 国产亚洲高清在线精品不卡 | 国产精品一区二区三区在线播放 | 成人颜色视频 | 欧美成人综合视频 | 国产成人精品免费视频大全办公室 | 福利一区二区三区视频在线观看 | 国产二区三区视频 | 国产一级毛片在线看 | 久久露脸国语精品国产91 | 深夜小视频在线观看 | 日日鲁一鲁视频 | 日韩av日韩 | 91系列在线观看 | 日本在线精品视频 | 黄网站免费观看视频 | 久久国产精品久久久久久久久久 | 日产精品一区二区三区在线观看 | 久久久国产精品电影 | 亚洲综合91 | 久久久久久久久免费 | 欧美日韩国产中文字幕 | 国产自91精品一区二区 | 污黄视频在线播放 | 草莓福利视频在线观看 | 麻豆视频在线观看 | 久久精品无码一区二区三区 | 欧美成人一区二区视频 | 午夜国内精品a一区二区桃色 | 国产精品久久久久久久久粉嫩 | 毛片视频在线免费观看 | 久久影院免费观看 | 国产精品久久久久影院老司 | 国产女同疯狂激烈互摸 | 一本色道精品久久一区二区三区 | 国产污污视频 | 成人福利视频在线观看 | 亚洲免费视 |