书接上文,昨天我们快速的走了一遍wasm的开发流程(我的『MVP.Blazor』快速创建与部署),总体来说还是很不错的,无论是从技术上,还是从开发上,重点是用C#来开启前端时代,可以开发SPA单页面应用,这个本身就是很奇妙的一件事,因为我有一定的VUE.JS基础,所以入手Blazor.Wasm的话,还是特别快的,可以说是很对脾气的,无论是双向绑定、组件开发、页面模板、生命周期、父子通讯等等等等上,都很契合。
所以说:只要你会ASP.NETCore和Vue(当然其他的也可以)技术,入门Blazor也就一两天的事儿。不过在最后一步——托管和部署的时候,出现了一个小问题,当然,也不是问题,是我没有考虑到的,下边说一下这个小问题。
1、为什么要选择Blazor.Server?
上边我已经说过了,Blazor.Wasm开发起来还是很舒服的,而且也是SPA单页面应用程序,这里先说下两者的区别:
Blazor 技术又分两种:
- Blazor WebAssembly
- Blazor Server
Blazor WebAssembly 是真正的SPA,页面的渲染在前端实现,可以实现真正的前后端分离设计。而Blazor.Server可以认为是前者的服务端渲染版本,它使用SignalR实现了客户端的实时通讯,它的计算跟渲染都在服务端处理。
你可以看明白了吧,其实wasm就像是vue那种单页面程序,而Blazor.Server更像是基于前者的一种服务端渲染(注意:和MVC不是一回事),第一次刷新是HTTP请求,平时点击是SignalR处理。
虽然看似wasm有友好,但是部署的时候出现了一个问题,就是它是可以直接在浏览器中执行,就是WebAssembly在浏览器里实现了一个.NET Runtime,所以每次刷新的时候,都会加载全部的资源程序集文件dll:
所以时间会特别慢,尽管做了一些处理:比如官方推荐的PWA技术(可以在客户端缓存部分dll),也做了竞速,然后还有压缩,当然,还有人说可以使用CDN,额,好像开发一个SPA程序做了这么多步骤,显然不是很美味,可能我道行不够吧。
最后,纠结了纠结,还是选择了Blazor.Server,同时也看到上篇文章中,有小伙伴留言,更加速了我转型Server的劲头:
貌似目前blazor wasm的项目加载都非常慢,我还是优先选择blazor server,微软吹在2c4g的服务器上部署blazor server能承载十几万个session,学过Angular用blazor server特别有亲切感,service,component,DI,理念都很一致
是不是看着很心动,那果断用起来,其实我主要是想解决这个刷新很慢的问题。
好啦,正式开始将项目从wasm迁移到blazor.server中。
2、代码迁移
因为昨天已经说过了wasm的创建过程,而且代码也都写好了,特别是.razor页面,几乎都不用做处理,直接copy就行,那我就说说注意点。
1、创建server项目
还是昨天的那个页面,只不过是第一个选项了:
创建完成后,可以看到默认的项目结构,和ASP.NETCore的web项目很像:
简单解释一下:
1、wwwroot:静态资源文件; 2、Data:数据文件(M),定义Model和Service,可以从数据库里获取数据; 3、Pages:视图(V)和逻辑(VM),和wasm一样; 4、Shared:共享组件; 5、_Imports.rzor:命名空间导入; 6、App.razor:项目文件; 7、appsettings.json:配置文件; 8、Program.cs:程序总运行入口; 9、Startup.cs:启动类,做注入和中间件配置;
是不是感觉和ASP.NETCore项目很像,本来就是,看Framworks框架就知道了,反正只要是你玩儿过netcore,昨天对wasm也有一定的了解的话,对项目结构还是比较熟络的,接下来就是开发了。
2、默认示例解析
这次官方给的还是三个例子:事件绑定计数器、数据获取、首页加载。
除了这三个外,有一个需要注意的是,之前我们使用wasm的时候,是一个SPA,需要提供一个index.html文件,作为整个项目的项目承载页面,现在我们使用了server服务端渲染后,就不需要了,转而使用了一个_Host.cshtml的页面,从后缀名可以看出来,其实也和html很像的一个cshtml页面,而不是.razor。
那下边简单说下获取数据FetchData:
之前我们使用wasm的时候,因为是前后端分离,所以使用的是HttpClient来远程获取资源服务器的资源数据,但是现在我们使用了服务端以后,可以自己写业务逻辑了:
比如增删改查,持久化等等逻辑:
正如示例的,定义了一个WeatherForecastService.cs服务,然后注入到页面
代码语言:javascript复制@inject WeatherForecastService ForecastService
接着就可以直接使用了:
代码语言:javascript复制@code {
private WeatherForecast[] forecasts;
protected override async Task OnInitializedAsync()
{
forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
}
}
但是我今天不打算用这个逻辑,因为我还是想要使用Blog.Core的数据,所以,还是打算使用HttpClient来获取远程数据,而不是自写逻辑。
那下边就开始迁移:
3、代码COPY
为了让大家能看到两个项目,所以我直接在之前的解决方案中,创建一个新项目:
代码语言:javascript复制Blog.MVP.Blazor.SSR
将wwwroot资源文件,Common公共类,Models模型,Pages页面,Shared组件等全部拷贝到新项目:
4、修改Data获取方式
因为默认的server采用的是service的方式,我们要使用httpclient的方式,所以需要简单做下修改:
添加nuget包
代码语言:javascript复制<PackageReference Include="System.Net.Http.Json" Version="3.2.0" />
命名空间引入_import
代码语言:javascript复制@using System.Net.Http.Json
服务注册到容器startup.cs
代码语言:javascript复制services.AddSingleton<HttpClient>();
用绝对路径发起api请求
代码语言:javascript复制 await Http.GetFromJsonAsync<MessageModel<PageModel<BlogArticle>>>
("http://apk.neters.club/api/Blog?page=1&bcategory=MVP_azure_2020&intPageSize=20");
因为现在是服务端的请求,所以不用配置跨域。
5、调试
之前wasm调试的时候,我们通过console.write(),会把结果打印到浏览器的控制台,
但是现在我们可以直接输出到程序的控制台dos窗口。
两个都很方便。
好啦,到这里我们就迁移完成了,接下来我们就托管部署下吧。
3、新的托管与部署
还记得昨天我们是怎么部署的么?
因为wasm是SPA,所以我们发布后,直接wwwroot部署到nginx,作为一个静态站点即可,就像是部署build后的vue那样。
代码发布
但是Blazor.Server不一样了,毕竟是SSR渲染。我们把项目进行发布,可以看到发布后的文件和之前的ASP.NETCore真的一样,还有.exe可执行文件:
那既然都这么熟悉了,就不用我多说了吧,Linux PM2 Nginx跨平台流程走起!
Linux部署
我直接写了要给.sh文件,这样在服务器里部署,不用FTP,浪费带宽
代码语言:javascript复制git pull;
rm -rf .PublishFiles;
dotnet build;
cd Blog.MVP.Blazor.SSR
dotnet publish -o /home/Blog.MVP.Blazor/Blog.MVP.Blazor.SSR/bin/Debug/netcoreapp3.1/publish;
cp -r /home/Blog.MVP.Blazor/Blog.MVP.Blazor.SSR/bin/Debug/netcoreapp3.1/publish /home/Blog.MVP.Blazor/.PublishFiles;
echo "Successfully!!!! ^ please see the file .PublishFiles";
然后检查无误后,通过pm2守护进程
代码语言:javascript复制pm2 start "dotnet Blog.MVP.Blazor.SSR.dll" --name mvp.dll
最后nginx代理
代码语言:javascript复制 server {
listen 80;
server_name mvp.neters.club;
rewrite ^(.*)$ https://$host$1 permanent;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
}
server {
listen 443 ssl;
server_name mvp.neters.club;
ssl_certificate /etc/nginx/conf.d/1_mvp.neters.club_bundle.crt;
ssl_certificate_key /etc/nginx/conf.d/2_mvp.neters.club.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://localhost:5050;
index index.php index.html index.htm;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
检查nginx是否正常
代码语言:javascript复制nginx -t
重启nginx服务
代码语言:javascript复制nginx -s reload
搞定,可以在线查看效果。
5、总结
https://mvp.neters.club/
通过查看重新发布的项目,可以看到速度已经基本能接受了。
总体来说,Blazor.Server简直就是Blazor.Wasm和ASP.NetCore的结合体,当然,说白了就是服务端渲染。
我更喜欢的,还是它的组件开发,
双向绑定、组件开发、组件继承、页面模板、生命周期、父子通讯 很有前端开发那味,当然还有很多其他的亮点知识,等待一起发掘。
打完收工。