美文网首页
再探.NET8 NativeAOT(二)

再探.NET8 NativeAOT(二)

作者: ChenReal | 来源:发表于2023-11-26 09:26 被阅读0次

乘着昨天良好的开局,这一回,我们开始进入实战项目的阶段。
翻了半天,终于找到一个代码量不大也不小的工具类应用:VuePacker。它的主要功能是前端开发工具,主要功能有:

  • 1、遍历某个目录下的所有*.vue代码,解析并将其组装成Vue Component结构的js代码
  • 2、将所指定的*.js代码合并打包成单一的js文件,并进行压缩最小化(minify)
  • 3、将所指定*.css代码打包成单一的css文件,并进行压缩最小化(minify)

看看NativeAOT能否一句将其拿下。

1、动手

先改TargetFramework,然后加上PublishAot,最后dotnet publish发布打包……一通熟手的操作下来,竟然无比顺利,成功编译生得到了exe。果然不出意外地出了意外,双击运行的时候,报 错 了!

Reflection-based serialization has been disabled for this application. Either use the source generator APIs or explicitly configure the 'JsonSerializerOptions.TypeInfoResolver' property.

报错信息的指向很明确,是个Json反序列化的报错。项目代码确实用到了System.Text.Json,沿着这条线索,终于找到解决方法。

首先,解释一下原理(纯粹个人理解)

AOT的编译是会根据代码实际情况对依赖的库进行裁剪,以保证生成文件足够苗条。但有些库可能用到某些动态写法,因此编译器裁剪后打包却不能正常工作。这时候,我们需要引入rd.xml来声明第三方库的编译打包方式,告诉编译器不要对它做裁剪,而是全量编译进去。等于做出一定牺牲,让文件变得臃肿一些,以保证应用能够正常运行,以空间换胜利。

接着,再试试rd.xml这一剂解药
  • 在项目创建rd.xml文件,文件内容如下:
    <Directives>
     <Application>
      <Assembly Name="System.Text.Json"  Dynamic="Required All">
      </Assembly>
     </Application>
    </Directives>
    
  • 打开.csproj文件,增加一下配置
    <ItemGroup>
      <RdXmlFile Include="rd.xml" />
     </ItemGroup>
    

重新发布后,报错消除,我的应用可以正常执行了!但是exe文件的大小,从原来的5.6M涨到了8.4M,竟直胖了50%!

2、优化

rd.xml的方案确实有效果,不过副作用也挺大,是最求极值的在下不能忍受。那么,下面就继续做些优化吧。优化思路:

  • A)换个JSON库?用Newtonsoft.Json?这是重量级选手,我敢保证这个生成的exe会更胖。JSON的库似乎都大不轻量级。
  • B)干脆不要JSON了,反正我的应用也仅仅是用反序列化解析appsetting.json的配置文件而已,几千行代码仅仅调用过一次。其实可以试试yml 或者 ini,这些配置解析的算法都比json轻的多。不过,这样也有坏处,就是对用户不大友好。以往版本都是用json做配置的,换一种配置方式用户教育成本,虽不大但还是有的。让用户无感升级才是最最理想的。
  • C)自己用正则表达式,写个简单的json配置解析方法?嗯,我看行!毕竟我的配置格式是非常简单的Key-Value,没有过多嵌套。正则表达式可以胜任~

按照方案C操作后,得到4.5M的exe文件。

3、继续优化

看来量少用或者不用第三方库,对优化exe文件大小会有立竿见影的效果。好吧,掌握了规律,那就再动动刀子,把仅剩一个的第三方库:NUglify换掉试试。

我发现Javascript打包混淆的代码,自己去造轮子显然不现实,只能找别人的轮子拼接过来。事实上这套代码并不好找,我在GitHub翻了好久,才找到一个停更多年的开源项目:https://github.com/Taritsyn/JSMin.NET将就着用把,反正也只是个试验罢了。

最后,一番折腾下来,我能做到极限大小的exe文件是3.2M。

总结

  • 学会用rd.xml全量编译处理第三方依赖库
  • 想帮exe文件瘦身,必须尽量量少用或者不用第三方库

相关文章

  • 再探pinpoint Agent(二)

    在再探pinpoint Agent(一)中介绍了运行的基本流程以及关键代码,本节主要讲解Agent中Plugin的...

  • for循环再探

    for循环的表达式一般如下: for(表达式1;表达式2;表达式3){ 表达式4; } 例如:for( i=0...

  • ByteBuf再探

    什么是ByteBuf ByteBuf是Netty中非常重要的一个组件,他就像物流公司的运输工具:卡车,火车,甚至是...

  • 再探React

    早在一年前,我就很蠢发表过一篇关于React的文章,这篇文章主要根据React官方的介绍初步介绍一下React,并...

  • 再探JavaScript

    一、数据类型二、表达式和运算符三、语句四、对象五、数组六、函数七、This八、闭包和作用域九、OOP十、正则和模式...

  • 再探雪景

    挥洒得随性 飘逸得纯净 就像一个 性情中人 活到最后才明白 那些装腔作势 那些别人的眼神 最终都会归零 自己让自己...

  • 再探老人

    也许会有那么一天 冰冷的金属,趴在我的身上 撩拨着我的心脏

  • 再探仙湖

    再次重逢, 你身边的百花已落尽, 风还是那阵风, 水还是那湖水, 只是细细去闻, 却没了那股春香, 多了些岁月的印...

  • 再探商丘

    商丘为什么叫商丘呢?因为这是商朝的祖先契出生的地方,在商丘这里叫阏(e四音)伯,阏伯观火星之地是个高土台,观台处就...

  • 再探目标

    最近在学习Metasploit渗透测试指南,才了解到,前几天所作的工作就是被动信息搜集,那么今天要做的就是主动信息...

网友评论

      本文标题:再探.NET8 NativeAOT(二)

      本文链接:https://www.haomeiwen.com/subject/fklowdtx.html