《進擊吧!Blazor!》是本人與張善友老師合作的Blazor零基礎入門教程視頻,此教程能讓一個從未接觸過Blazor的程序員掌握開發Blazor應用的能力。
視頻地址:https://space.bilibili.com/483888821/channel/detail?cid=151273
Blazor WebAssembly 是單頁應用 (SPA) 框架,用於使用 .NET 生成交互式客戶端 Web 應用,采用 C# 代替 JavaScript 來編寫前端代碼
本系列文章基於《進擊吧!Blazor!》編寫,但因篇幅有限,省略了部分代碼,完整示例代碼:https://github.com/TimChen44/Blazor-ToDo
作者:陳超超
Ant Design Blazor 項目貢獻者,擁有十多年從業經驗,長期基於.Net技術棧進行架構與開發產品的工作,現就職於正泰集團。
郵箱:timchen@live.com
歡迎各位讀者有任何問題聯系我,我們共同進步。
部署是開發的最后一部,我們這次就來聊聊Blazor的部署方法。
發布
VS已經為我們預制了多個目標的發布工具,使用這些工具可以很容易的完成發布和部署。
1.首先在ToDo.Server項目上右鍵,選擇發布...功能

2.接着選擇要發布的目標,常用的環境都支持,我們就以Azure為例

3.根據目標不同填寫一些配置,VS也會幫我們保存配置信息便於下次使用。

4.配置一些依賴,比如本例中需要配置數據庫,最后點擊”發布“按鈕,接着喝杯茶等待一下。

5.經過VS后台的一頓操作,發布完成,並且會自動打開發布的站點,效果如下

到這里,這篇文章結束了,各位再見!😜
這個😅,我們本着“搞事情”的精神,"沒有困難制造困難"的理念來重構我們的發布,各位走起~~~~
首先可以確定上面VS為我們提供的發布工具確實非常方便,比較適合小團隊開發一些小規模的系統,但是通常企業中使用會遇到以下的問題
- 負責發布的運維工程師與負責編碼的開發工程師不是同一撥人,不可能讓運維工程師用VS開着源碼進行發布,代碼安全,生產環境安全雙雙無法保證。
- 自動化的IC/CD普及度的增加,生成和發布過程挪到了各DevOps平台,所以也不適合在VS中操作。
廣告時間:推薦大家嘗試一下微軟的Azure DevOps,支持本地部署,支持所有語言,預制各平台發布流程等等,配置一個項目的IC/CD過程猶如前面的操作一樣,鼠標點點就完事,懶人的福音。
綜上述,我們可以采用比較靈活的的做法,先將項目發布成文件,然后將這些文件部署到不同的環境中。這也符合自動化的IC/CD的常規流程,先集成再部署。
如果使用Docker,可以在IC時直接Build出Image,也可以在CD時Build出Image,我覺得沒有標准,適合自己就行。
發布到文件夾
那么我們繼續使用VS的發布工具將項目打包
1.選擇發布到文件夾選項,並設定輸出位置

2.點擊發布完成編譯並輸出。

3.點擊上面的”鉛筆“圖標可以進行詳細配置

目標框架 設置使用那個.net框架進行編譯
部署模式 它分為框架依賴和獨立兩個選共享
框架依賴 模式下生成的文件需要.net運行時才能運行,優點體積較小,程序本省不依賴目標運行時,方便移植
獨立 模式下編譯器會把.net運行時與程序打包在一起,運行平台無需.net運行時,缺點是體積較大,編譯的程序依賴於目標運行時
目標運行時 選擇針對那個平台編譯,可以是win、linux、osx系統,以及x64、x86、arm指令集
生成單個文件 勾選后可以把程序打包在一個文件中,運行的時候程序會自動解包並運行
裁剪未使用的程序集 將一些項目中引用但是代碼中並未使用的程序集剔除以減少程序包的體積
我們的示例程序使用配置
部署模式為依賴框架,目標運行時為可移植
如果編譯過程使用自動化工具進行打包,除了打包命令中額外增加參數外,我們也可以在.csproj文件中做以下配置來實現上面的參數
<PropertyGroup>
<PublishSingleFile>True</PublishSingleFile><!-- 生成單個文件 -->
<PublishTrimmed>True</PublishTrimmed><!-- 裁剪未使用的程序集 -->
<SelfContained>true</SelfContained><!-- 框架依賴:獨立 -->
<RuntimeIdentifier>win-x86</RuntimeIdentifier><!-- 目標運行時 -->
</PropertyGroup>
4.程序以文件形式輸出在我們給定的路徑
部署
使用 ASP.NET Core 進行托管部署
如果使用ASP.NET Core的Kestrel Web 服務器托管程序,我們只需運行我們上面發布輸出的ToDo.Server.exe文件即可

到這里有個小問題,就是我們不想使用默認的5000和5001端口,這個我們就需要人為的給定端口。
修改ToDo.Server的Program.cs文件
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder
.UseUrls("http://*:4000", "https://*:4001")
.UseStartup<Startup>();
});
我們使用.UseUrls來給定Url地址,這里*代表適配所有IP或域名,端口分別設定為4000和4001。
這里又冒出一個小問題,目前端口硬編碼在程序中,發布后無法修改,遇到這個問題,我們可以通過啟動參數、配置文件等多個方法實現發布后修改,在這里我貼上通過啟動參數修改端口的代碼。
public static IHostBuilder CreateHostBuilder(string[] args)
{
var configuration = new ConfigurationBuilder().AddCommandLine(args).Build();
return Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder
.UseUrls($"http://*:{configuration["httpport"] ?? "5000"}", $"https://*:{configuration["httpsport"] ?? "5001"}")
.UseStartup<Startup>();
});
}
啟動的時候附上對應參數實現修改端口的目的。

使用 IIS 進行托管部署
我們也可以使用IIS來托管部署我們的程序。
-
需要在部署的服務器上安裝
ASP.NET Core Hosting Bundle,這個可以讓IIS支持.Net Core應用。下載地址:https://dotnet.microsoft.com/download/dotnet/5.0 -
添加名為
ToDo的站點,選擇發布的文件所在目錄,配置端口等

-
將應用程序池
ToDo的NET CLR版本設置為無托管代碼。

-
啟動站點就能看到自己部署的程序了。

與ASP.Net Core的區別
看到這里,各位覺得Blazor和ASP.Net Core在部署上有什么區別嗎?答案是:沒區別😉。
前后端分開部署
當遇到規模不小的項目時,我們會考慮到性能、安全等因素時,可能會選擇前后端分別部署在不同的服務器上,這時我們只需要新建一個空項目,然后引用Blazor項目即可,操作如下
-
添加名為
ToDo.BlazorHost的ASP.NET Core空項目

-
引用
ToDo.Client項目 -
安裝
Microsoft.AspNetCore.Components.WebAssembly.Server包 -
修改
launchSettings.json文件,配置應用端口默認為4000
"iisExpress": {
"applicationUrl": "http://localhost:4000",
"sslPort": 0
}
- 修改
Startup.cs文件,讓項目支持Blazor應用
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseBlazorFrameworkFiles();//配置應用程序從根“/”提供Blazor框架文件
app.UseStaticFiles();//提供靜態文件支持
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapFallbackToFile("index.html");//配置默認路由地址
});
}
- 修改
ToDo.Client項目Program.cs文件,設置HttpClient默認請求地址為ToDo.Server項目的地址
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri($"http://localhost:5000") });
- 修改
ToDo.Server項目launchSettings.json文件,配置IIS Express調試端口默認為5000
"iisExpress": {
"applicationUrl": "http://localhost:5000",
"sslPort": 0
}
- 修改
Startup.cs文件,添加跨域支持,此處為了演示方便,我開啟了所有跨域設置
app.UseCors(config => config.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().AllowCredentials().WithOrigins("http://localhost:4000"));
-
刪除
ToDo.Server中ToDo.Client的引用,以及Blazor相關的設置,ToDo.Server作為一個存粹的WebAPI站點存在。 -
為了驗證前端請求的數據是那個服務返回,我們做一個反饋服務器地址的接口給前端調用。
修改AuthController.cs文件
[HttpGet]
public string GetHost()
{
return HttpContext.Request.Host.ToString();
}
修改Login.razor文件
<p>前端地址:<span>@ClientHost</span></p>
<p>API服務地址:<span>@ServerHost</span></p>
string ClientHost;
string ServerHost;
protected override async Task OnInitializedAsync()
{
ClientHost = WebAssemblyHostBuilder.CreateDefault().HostEnvironment.BaseAddress;
ServerHost = await Http.GetStringAsync($"api/Auth/GetHost");
await base.OnInitializedAsync();
}
同時啟動ToDo.Server和ToDo.BlazorHost項目的調試,看到以下效果

網關部署
當用戶多了,獲作為關鍵服務時,單點部署就有點不合時宜了,這時需要高可用,負載均衡等需求,因此我們就要拿出我們的網關,把他放在最前面,負責請求分發。
-
添加名為
ToDo.BlazorHost的ASP.NET Core空項目作為網關ToDo.Gateway -
添加
Ocelot組件,Ocelot是一個用.NET Core實現並且開源的API網關,它功能強大,包括了:路由、請求聚合、服務發現、認證、鑒權、限流熔斷、並內置了負載均衡器與Service Fabric、Butterfly Tracing集成。

- 修改
launchSettings.json文件,將訪問端口改成5500
"iisExpress": {
"applicationUrl": "http://localhost:5500",
"sslPort": 0
}
- 添加
Ocelot.json文件,配置我們網關的策略
{
"Routes": [
{
// - 上游服務配置
"UpstreamPathTemplate": "/api/{url}",
"UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ],
// - 下游服務配置
"DownstreamPathTemplate": "/api/{url}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5000
}
],
// - LoadBalancer將決定負載均衡的算法,三種取值
// RoundRobin:輪流發送
// LeastConnection:將請求發往最空閑的那個服務器
// NoLoadBalance:總是發往第一個請求或者是服務發現
"LoadBalancerOptions": {
"Type": "RoundRobin"
}
},
{
// - 上游服務配置
"UpstreamPathTemplate": "/{url}",
"UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ],
// - 下游服務配置
"DownstreamPathTemplate": "/{url}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5100
}
],
// - LoadBalancer將決定負載均衡的算法,三種取值
// RoundRobin:輪流發送
// LeastConnection:將請求發往最空閑的那個服務器
// NoLoadBalance:總是發往第一個請求或者是服務發現
"LoadBalancerOptions": {
"Type": "RoundRobin"
}
}
],
"GlobalConfiguration": {
"BaseUrl": "https://api.mybusiness.com"
}
}
上面
Ocelot.json文件中注釋只是為了介紹常用屬性,實際使用中json文件中不能包含注釋,否則會造成解析失敗,切記。
- 修改
Program.cs文件,添加載入Ocelot.json文件的代碼
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureAppConfiguration((hostContext, config) =>
{
config.AddJsonFile("Ocelot.json");
})
.UseStartup<Startup>();
});
- 修改
Startup.cs文件,添加Ocelot服務
public void ConfigureServices(IServiceCollection services)
{
services.AddOcelot();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseOcelot();
}
- 修改
ToDo.Client項目的Program.cs文件,配置HttpClient默認地址為網關地址
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri($"http://localhost:5500") });
- 修改
ToDo.Server項目的Startup.cs文件,追加跨域請求地址“http://localhost:5500”
app.UseCors(config => config.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().AllowCredentials().WithOrigins("http://localhost:4000", "http://localhost:5500"));
同時調試ToDo.BlazorHost,ToDo.Gateway,ToDo.Server三個項目,打開地址http://localhost:5500
我們看到前端地址是localhost:5500,請求的地址也是localhost:5500,但是為我們返回數據的API服務地址是localhost:5000,說明網關已經幫我做了轉發。

最后
感謝有讀者能看到這里,這是本人第一次寫專欄,文章可能會存在一些瑕疵,我會在將來盡力改進。
《進擊吧!Blazor!》系列入門教程 第一章到這里就結束了,后續我會繼續為大家帶來與.Net和Blazor有關的原創文章,文章內容爭取做到易讀、高質量。
謝謝大家!
