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,启动压缩,并且在发布的时候裁剪了未使用的程序集:

极致优化 到1MB

在Demand项目文件中添加以下配置,以下配置禁用了一些功能,比如全球化等

<PublishTrimmed>true</PublishTrimmed>
<InvariantGlobalization>true</InvariantGlobalization>
<BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport>
<EventSourceSupport>false</EventSourceSupport>
<HttpActivityPropagationSupport>false</HttpActivityPropagationSupport>
<EnableUnsafeBinaryFormatterSerialization>false</EnableUnsafeBinaryFormatterSerialization>
<MetadataUpdaterSupport>false</MetadataUpdaterSupport>
<UseNativeHttpHandler>true</UseNativeHttpHandler>

然后我们继续上面的操作将其发布,并且部署到nginx中

在网络中查看加载大小,我们看到已经来到了1MB,去掉一些js其实应该更小,这样它的加载问题得到了很大的解决(来着小夜鲲大佬的建议)

结尾

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

来着token的分享

demo地址

GitHub

Gitee

blazor交流群:452761192

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

  1. 如何将WebAssembly优化到2MB?

    Blazor WebAssembly加载优化方案 对于Blazor WebAssembly加载方案的优化是针对于WebAssembly首次加载,由于BlazorWebAssembly是在首次加载的时候 ...

  2. 如何优化线上WebAssembly

    如何优化线上WebAssembly WebAssembly部署使用 HTTPS : 为什么?我可以通过一个案例查看 ,下面我们会通过masa docs站点进行测试 打开 http://docs.mas ...

  3. .NET周报 【2月第1期 2023-02-04】

    国内文章 .NET 入门到高级路线 https://www.cnblogs.com/hejiale010426/archive/2023/02/01/17083913.html 笔者介绍了.NET入门 ...

  4. 实现一个简单的在浏览器运行Dotnet编辑器

    之前已经实现过Blazor在线编译了,现在我们 实现一个简单的在浏览器运行的编辑器,并且让他可以编译我们的C#代码, 技术栈: Roslyn 用于编译c#代码 [monaco](microsoft/m ...

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

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

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

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

  7. .NET in Browser - Blazor

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

  8. 从开源模型、框架到自研,声网 Web 端虚拟背景算法正式发布

    根据研究发现,在平均 38 分钟的视频会议里面,大概会有 13 分钟左右的时间用于处理和干扰相关的事情.同时研究也表明在参加在线会议的时候,人们更加倾向于语音会议,其中一个关键原因就是大家不希望个人隐 ...

  9. Blazor WebAssembly的初次访问慢的优化

    Blazor WebAssembly初次访问需要加载很多dll,体积较大,因此第一次加载比较慢. 针对此问题Microsoft提供了优化方案:压缩 https://learn.microsoft.co ...

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

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

随机推荐

  1. ArcGIS工具操作报错999999的通用处理方式

      本文介绍一种解决ArcGIS中ERROR 999999报错(Configuration RasterCommander ImageServer can not be started)的方法.    ...

  2. 基于CentOS Stream 8的物联网平台深度优化方案

    系统架构全景图 图表 一.系统平台优化(CentOS Stream 8) 1. 系统基础配置 bash # 1. 系统更新与加固 sudo dnf update -y sudo dnf install ...

  3. HarmonyOS 应用开发实战指南

    HarmonyOS 应用开发实战指南 1. 开篇:为什么选择 HarmonyOS? 最近在开发鸿蒙应用时,发现很多开发者都在问:为什么要选择 HarmonyOS?这里分享一下我的看法: 生态优势 华为 ...

  4. hot100之堆

    虽然更多用的是桶 数组中的第k个最大元素(215) 桶排序 class Solution { public int findKthLargest(int[] nums, int k) { int[] ...

  5. oracle 存储过程 for loop 定时任务

    记录. 是这么个事,要实现一个需求,当人员表里的数据有更新后需要告知其他系统更新他们自己的人员数据. 我想了一下,表里是有时间戳字段的,那我只要监听这个时间就行,拿到数据后用存储过程把数据插入到中间表 ...

  6. Rust 修仙之道

    静修Rust三年多,有所感悟.今借道家修仙之法展一斑之管窥,只为博大家一乐.进入正文

  7. rollupjs

    掉落神坛的webpack webpack诞生之初的根本原因就是处理前端js模块化的工具. 如果浏览器本身慢慢的已经支持了模块化. 那么webpack存在的意义就不大了. webpack的其它瑕疵 在w ...

  8. 红米k40刷类原生系统

    下载相关文件 下载系统 这里是下载地址 (推荐)也可以按照手机代号,找到本文所需的所有资源,比如我找到的k40的所有资源 下载和安装相关驱动 进FASTBOOT 在已开机的情况下,连接电脑执行命令即可 ...

  9. mkl错误解决

    简介 RT 出现下述错误,需要安装一下mkl库才行 mkl_intel_thread.lib(scsr1_mmout_par_lp64.obj) : error LNK2001: 无法解析的外部符号 ...

  10. “7”势如虹|突破集成边界,谷云科技成为iPaaS领头羊!

    七载春秋,步履不停 5月18日,谷云科技RestCloud迎来了七周年生日.可能在大家看来,这似乎是一个常规的企业周年庆,然而,简约却不简单,在公司快速发展的背后,却蕴藏着涌动的力量,如果用一句话来概 ...