Blazor WebAssembly加载优化方案

对于Blazor WebAssembly加载方案的优化是针对于WebAssembly首次加载,由于BlazorWebAssembly是在首次加载的时候会将.NET Core的所有程序集都会加载到浏览器中,并且在使用的时候可能引用了很多第三方的dll,导致加载缓慢;

优化方案 :

1. 压缩

​ 发布 Blazor WebAssembly 应用时,将在发布过程中对输出内容进行静态压缩,从而减小应用的大小,并免去运行时压缩的开销。 使用以下压缩算法:

从 google/brotli GitHub repository 中获取 JavaScript Brotli 解码器。 缩小的解码器文件被命名为 decode.min.js,并且位于存储库的 js 文件夹中。

​ 修改wwwroot/index.html 文件代码 ,添加autostart="false" ,阻住默认启动加载程序集

<script src="_framework/blazor.webassembly.js" autostart="false"></script>

在 Blazor 的 <script> 标记之后和结束 </body> 标记之前,添加以下 JavaScript 代码 <script> 块:

<script type="module">
import { BrotliDecode } from './decode.min.js';
Blazor.start({
loadBootResource: function (type, name, defaultUri, integrity) {
// 注意:这里使用localhost的时候不会启动压缩
if (type !== 'dotnetjs' && location.hostname !== 'localhost') {
return (async function () {
const response = await fetch(defaultUri + '.br', { cache: 'no-cache' });
if (!response.ok) {
throw new Error(response.statusText);
}
const originalResponseBuffer = await response.arrayBuffer();
const originalResponseArray = new Int8Array(originalResponseBuffer);
const decompressedResponseArray = BrotliDecode(originalResponseArray);
const contentType = type ===
'dotnetwasm' ? 'application/wasm' : 'application/octet-stream';
return new Response(decompressedResponseArray,
{ headers: { 'content-type': contentType } });
})();
}
}
});
</script>

压缩方案将减少加载时间,大概是压缩dll的三分之一大小,效果如图

在使用autostart="false"标记以后不会启动就加载,加载程序集将在上面的代码块中执行,默认是加载br;

2. 延迟加载程序集

通过等待应用程序集直到需要时才加载,提高 Blazor WebAssembly 应用启动性能,这种方式称为“延迟加载”。

将BlazorWebAssembly项目拆分细致,通过延迟加载程序集提升BlazorWebAssembly首次加载时间,我们将通过一个案例来讲解延迟加载程序集

创建一个空的Blazor WebAssembly项目: 项目名称Demand

取消HTTPS 使用渐进式Web应用程序

在创建Razor类库,项目名称:Demand.Components,然后默认选项创建项目

创建Components.razor文件,并且删除多余文件,效果如图:



在Components.razor添加以下代码:

@inject NavigationManager NavigationManager

@page "/components"

<div>
<h1>
Components
</h1> </div>
<button @onclick="Goto">跳转到首页</button>
@code
{
private void Goto()
{
NavigationManager.NavigateTo("/");
}
}

在Demand项目中引用Demand.Components项目

修改App.razor文件 ,代码如下:

@using System.Reflection
@using Microsoft.AspNetCore.Components.WebAssembly.Services @*
这里需要注意,WebAssembly是默认注入的但是Server并没有注入
在Server中手动注入
builder.Services.AddScoped<LazyAssemblyLoader>();
*@
@inject LazyAssemblyLoader AssemblyLoader <Router AppAssembly="@typeof(App).Assembly"
AdditionalAssemblies="@lazyLoadedAssemblies"
OnNavigateAsync="@OnNavigateAsync">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound> </Router> @code {
private List<Assembly> lazyLoadedAssemblies = new(); private async Task OnNavigateAsync(NavigationContext args)
{
try
{
if (args.Path == "components")
{
// 这里自定义Demand.Components依赖的程序集,
var assemblies = await AssemblyLoader.LoadAssembliesAsync(new[] { "Demand.Components.dll" });
// 添加到路由程序集扫描中
lazyLoadedAssemblies.AddRange(assemblies);
}
}
catch (Exception ex)
{
}
}
}

处理指定路由组件需要加载的程序集

打开Demand项目文件

如果在Debug模式下可以使用添加以下忽略列表:

<ItemGroup>
<BlazorWebAssemblyLazyLoad Include="System.Xml.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Xml.XmlSerializer.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Xml.XmlDocument.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Xml.XPath.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Xml.XPath.XDocument.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Xml.XDocument.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Xml.Serialization.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Xml.ReaderWriter.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Xml.Linq.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Windows.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Net.Quic.dll" />
<BlazorWebAssemblyLazyLoad Include="System.IO.Compression.ZipFile.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Runtime.Numerics.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Collections.Immutable.dll" />
<BlazorWebAssemblyLazyLoad Include="Microsoft.Win32.Registry.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Web.HttpUtility.dll" />
<BlazorWebAssemblyLazyLoad Include="System.ValueTuple.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Security.AccessControl.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Net.Mail.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Net.NameResolution.dll" />
<BlazorWebAssemblyLazyLoad Include="System.IO.dll" />
<BlazorWebAssemblyLazyLoad Include="System.IO.UnmanagedMemoryStream.dll" />
<BlazorWebAssemblyLazyLoad Include="System.IO.Pipes.dll" />
<BlazorWebAssemblyLazyLoad Include="System.IO.Pipes.AccessControl.dll" />
<BlazorWebAssemblyLazyLoad Include="System.IO.Pipelines.dll" />
<BlazorWebAssemblyLazyLoad Include="System.IO.FileSystem.dll" />
<BlazorWebAssemblyLazyLoad Include="System.IO.FileSystem.Watcher.dll" />
<BlazorWebAssemblyLazyLoad Include="System.IO.FileSystem.Primitives.dll" />
<BlazorWebAssemblyLazyLoad Include="System.IO.FileSystem.DriveInfo.dll" />
<BlazorWebAssemblyLazyLoad Include="System.IO.FileSystem.AccessControl.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Data.Common.dll" />
<BlazorWebAssemblyLazyLoad Include="Microsoft.CSharp.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Console.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Core.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Data.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Data.DataSetExtensions.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Drawing.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Drawing.Primitives.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Diagnostics.TraceSource.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Diagnostics.Tools.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Diagnostics.TextWriterTraceListener.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Diagnostics.StackTrace.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Diagnostics.Process.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Diagnostics.FileVersionInfo.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Diagnostics.DiagnosticSource.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Diagnostics.Debug.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Diagnostics.Contracts.dll" />
<BlazorWebAssemblyLazyLoad Include="Microsoft.AspNetCore.Authorization.dll" />
<BlazorWebAssemblyLazyLoad Include="Microsoft.AspNetCore.Components.Forms.dll" />
<BlazorWebAssemblyLazyLoad Include="Microsoft.AspNetCore.Metadata.dll" />
<BlazorWebAssemblyLazyLoad Include="Microsoft.Extensions.Configuration.Binder.dll" />
<BlazorWebAssemblyLazyLoad Include="Microsoft.Extensions.FileProviders.Abstractions.dll" />
<BlazorWebAssemblyLazyLoad Include="Microsoft.Extensions.FileProviders.Physical.dll" />
<BlazorWebAssemblyLazyLoad Include="Microsoft.Extensions.Configuration.FileExtensions.dll" />
<BlazorWebAssemblyLazyLoad Include="Microsoft.Extensions.FileSystemGlobbing.dll" />
<BlazorWebAssemblyLazyLoad Include="System.IO.MemoryMappedFiles.dll" />
<BlazorWebAssemblyLazyLoad Include="System.IO.IsolatedStorage.dll" />
<BlazorWebAssemblyLazyLoad Include="System.IO.Compression.dll" />
<BlazorWebAssemblyLazyLoad Include="System.IO.Compression.FileSystem.dll" />
<BlazorWebAssemblyLazyLoad Include="System.IO.Compression.Brotli.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Formats.Tar.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Formats.Asn1.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Net.WebSockets.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Private.DataContractSerialization.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Private.Xml.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Security.Cryptography.dll" />
<BlazorWebAssemblyLazyLoad Include="Microsoft.VisualBasic.dll" />
<BlazorWebAssemblyLazyLoad Include="Microsoft.VisualBasic.Core.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Threading.Tasks.Dataflow.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Text.Encoding.CodePages.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Net.WebSockets.Client.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Private.Xml.Linq.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Text.RegularExpressions.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Net.Sockets.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Net.WebClient.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Net.WebProxy.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Net.Ping.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Security.Cryptography.X509Certificates.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Net.WebHeaderCollection.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Security.Cryptography.OpenSsl.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Security.Cryptography.Encoding.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Security.Cryptography.Csp.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Security.Cryptography.Cng.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Security.Claims.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Security.Cryptography.Algorithms.dll" />
<BlazorWebAssemblyLazyLoad Include="Microsoft.Win32.Primitives.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Net.HttpListener.dll" />
<BlazorWebAssemblyLazyLoad Include="System.AppContext.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Net.NetworkInformation.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Net.Requests.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Net.Primitives.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Net.Security.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Net.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Net.ServicePoint.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Net.Http.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Globalization.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Globalization.Calendars.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Globalization.Extensions.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Net.Http.Json.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Web.dll" />
<BlazorWebAssemblyLazyLoad Include="WindowsBase.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Resources.Writer.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Resources.ResourceManager.dll" />
<BlazorWebAssemblyLazyLoad Include="System.Resources.Reader.dll" />
</ItemGroup>

这些是不常用的一些程序集,如果出现以下错误,请将找不到的程序集删除按需加载配置,

但是如果使用了上面的按需加载配置,在发布的时候会出现异常比如下面这个图这样;错误原因是Blazor WebAssembly在发布的时候默认使用裁剪,由于以下程序集刚刚好是没有使用的,在裁剪以后会配置按需加载,但是它已经被裁剪了,所以导致无法找到按需加载的程序集;只要删除报错的程序集即可;这个只有在发布的时候才会出现,DeBug还是可以继续使用上面的按需加载的配置,可以在调试的时候响应更快

然后下一步

添加指定项目的按需加载配置,我们将Demand.Components项目配置上去,

	<ItemGroup>
<BlazorWebAssemblyLazyLoad Include="Demand.Components.dll" />
</ItemGroup>

修改Pages/Index.razor文件代码

@page "/"
@inject NavigationManager NavigationManager
<h1>Hello, world!</h1> <button @onclick="Goto">跳转到components</button>
@code
{
private void Goto()
{
NavigationManager.NavigateTo("/components");
}
}

然后启动项目,打开F12开发者调试工具,点击应用程序,找到存储,点击清除网站数据(第一次加载以后程序集会缓存起来):

点击网络,然后刷新界面,我们看到这里并不会加载Demand.Components.dll,但是这里的程序集:



然后点击界面的按钮:

这个时候在来到调试工具的网络,我们看到Demand.Components.dll已经被加载了,当我们使用的时候这个程序集才会加载,并且第二次加入界面的时候不会重复加载程序集



然后我们将项目发布(发布的时候记得上面提到的裁剪导致程序集丢失无法使用按需加载的问题,只要在按需加载的配置中清理掉被裁剪的程序集即可):

然后使用docker compose部署一个nginx代理查看效果:

创建docker-compose.yml文件,并且添加以下代码,在docker-compose.yml的当前目录下创建 conf.d和wwwroot俩个文件夹:

services:
nginx:
image: nginx:stable-alpine
container_name: nginx
volumes:
- ./conf.d:/etc/nginx/conf.d
- ./wwwroot:/wwwroot
ports:
- 811:80

在conf.d中创建webassembly.conf,并且添加以下代码:

server {
listen 80;
server_name http://localhost; location / {
root /wwwroot;
index index.html;
} }

然后在docker-compose.yml所属目录中使用docker-compose up -d启动nginx服务

打开浏览器访问http://127.0.0.1:811/ (不要使用localhost访问,默认不会启动压缩的)然后打开f12调试工具,并且在应用程序中清理掉存储,在打开网络选项,刷新浏览器,加载完成,优化到了2.3MB,启动压缩,并且在发布的时候裁剪了未使用的程序集:

结尾

如果您有更好的优化方案可以联系我

来着token的分享

demo地址

GitHub

Gitee

blazor交流群:452761192

如何将WebAssembly优化到2MB?的更多相关文章

  1. 一起学Blazor WebAssembly 开发(1)

    最近blazor的WebAssembly 正式版出来了,正好手头有一个项目采用的前后端分离模式做的,后端用的abp vnext(.net core 的一个很著名的框架)框架开发的,其实前端之前考虑的使 ...

  2. Blazor WebAssembly 渐进式 Web 应用程序 (PWA) 使用 LocalStorage 离线处理数据

    原文链接:https://www.cnblogs.com/densen2014/p/16133343.html Window.localStorage 只读的localStorage 属性允许你访问一 ...

  3. .NET in Browser - Blazor

    什么是Blazor Blazor 是一个实验性的. NET web 框架, 使用 C# 和 HTML 在任何浏览器中不需要插件即可运行 WebAssembly 程序集. 什么是WebAssembly ...

  4. 我的MYSQL学习心得(十六) 优化

    我的MYSQL学习心得(十六) 优化 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

  5. MYSQL数据库的优化

    我们究竟应该如何对MySQL数据库进行优化?下面我就从MySQL对硬件的选择.MySQL的安装.my.cnf的优化.MySQL如何进行架构设计及数据切分等方面来说明这个问题. 服务器物理硬件的优化 在 ...

  6. 优化MySchool数据库设计之【巅峰对决】

    优化MySchool数据库设计 之独孤九剑 船舶停靠在港湾是很安全的,但这不是造船的目的 By:北大青鸟五道口原玉明老师 1.学习方法: 01.找一本好书 初始阶段不适合,可以放到第二个阶段,看到知识 ...

  7. [MySQL Reference Manual] 8 优化

    8.优化 8.优化 8.1 优化概述 8.2 优化SQL语句 8.2.1 优化SELECT语句 8.2.1.1 SELECT语句的速度 8.2.1.2 WHERE子句优化 8.2.1.3 Range优 ...

  8. 【转载】PHP性能优化干货

    PHP优化对于PHP的优化主要是对php.ini中的相关主要参数进行合理调整和设置,以下我们就来看看php.ini中的一些对性能影响较大的参数应该如何设置. # vi /etc/php.ini (1) ...

  9. 一些PHP性能优化汇总

    PHP优化对于PHP的优化主要是对php.ini中的相关主要参数进行合理调整和设置,以下我们就来看看php.ini中的一些对性能影响较大的参数应该如何设置. # vi /etc/php.ini (1) ...

  10. PHP干货技巧文,一些PHP性能的优化

    PHP优化对于PHP的优化主要是对php.ini中的相关主要参数进行合理调整和设置,以下我们就来看看php.ini中的一些对性能影响较大的参数应该如何设置. # vi /etc/php.ini (1) ...

随机推荐

  1. 五、kubernetes节点与令牌管理

    Kubernetes节点与令牌管理 一.令牌管理 查看令牌 [root@master ~]# kubeadm token list 删除令牌 [root@master ~]# kubeadm toke ...

  2. 5 why 分析法,一种用于归纳抽象出解决方案的好方法

    最近在看了<微信背后的产品观 - 张小龙手抄版>,其中有段话如下: 用户需求是零散的,解决方案是归纳抽象的过程 那如何归纳抽象呢?是否有一定的实践方法论呢?经过一轮探讨和学习,有这些答案: ...

  3. Excel中的VLOOKUP函数

    VLOOKUP函数是Excel中的一个纵向查找函数,功能是按列查找,最终返回该列所需查询序列所对应的值. 该函数的语法规则如下: VLOOKUP(lookup_value,table_array,co ...

  4. SpringCloudAlibaba 微服务组件 Nacos 之配置中心源码深度解析

    大家好,这篇文章跟大家聊下 SpringCloudAlibaba 中的微服务组件 Nacos.Nacos 既能做注册中心,又能做配置中心,这篇文章主要来聊下做配置中心时 client 端的一些设计,主 ...

  5. 定制ASP.NET Core的身份认证

    大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享学习心得,希望我的文章能成为你成长路上的垫脚石,让我们一起精进. 在本章,我们将学习如何定制ASP.NET Core认证机制.微软把安全认证当做AS ...

  6. Window使用PowerShell改文件时间戳

    We cross infinity with every step; we meet eternity in every second. 我们每一步都跨过无穷,每一秒都遇见永恒. Window使用Po ...

  7. 1759E(方案枚举)

    题目链接 题目大意: 给你n个数(n个宇航员对应的能量值) 一个h ,h表示机器人当前的能量值.机器人拥有2中绿色的药剂,一瓶蓝色的药剂.其中绿色的药剂可以使机器人的能量值变为现在的2倍(2-> ...

  8. 5 STL-string

    ​ 重新系统学习c++语言,并将学习过程中的知识在这里抄录.总结.沉淀.同时希望对刷到的朋友有所帮助,一起加油哦!  生命就像一朵花,要拼尽全力绽放!死磕自个儿,身心愉悦! 写在前面,本篇章主要介绍S ...

  9. 【第7篇】AI语音交互原理介绍

    本章主要介绍AI语音交互的原理,包括语音交互的流程以及各流程节点所涉及的相关知识,如语音采集.语音识别.自然语言处理.语音合成等. 2.1 AI语音交互 AI语音交互通俗点说就是人与机器间进行语音理解 ...

  10. 我开发的开源项目,让.NET7中的EFCore更轻松地使用强类型Id

    在领域驱动设计(DDD)中,有一个非常重要的概念:"强类型Id".使用强类型Id来做标识属性的类型会比用int.Guid等通用类型能带来更多的好处.比如有一个根据根据Id删除用户的 ...