Add Trimming for MudBlazor and rework Icons for the Trimming support#4639
Add Trimming for MudBlazor and rework Icons for the Trimming support#4639Garderoben merged 8 commits intoMudBlazor:devfrom
Conversation
Codecov Report
@@ Coverage Diff @@
## dev #4639 +/- ##
==========================================
- Coverage 91.39% 91.37% -0.02%
==========================================
Files 366 365 -1
Lines 12573 12535 -38
==========================================
- Hits 11491 11454 -37
+ Misses 1082 1081 -1
Continue to review full report at Codecov.
|
|
Thanks for your work on this. I did quite a bit of work on this previously but couldn't get it to work. |
|
Let me first say I appreciate this PR 👍
I am not sure that is true. Remove it and recompile and the build will fail
That leads you down a path that I failed on as once you mark one method you have to mark the dependencies and so on and so on. Probably the only way is to make the relevant methods trim friendly. Its up to the core team if we want to ignore the trim warnings @henon @just-the-benno |
You are correct, for some reason I thought that by default it's disabled.
Ok, tmr I will make analysis and check on the MudBlazor.Docs with trimming to see what got broken and how bad it is. My project obviously doesn't use all the components so I don't know how usable it is actually. |
|
This is great work would be a shame to lose momentum on it. I hope to have a look at the trim warnings as well. Maybe there are some easy wins. |
|
@ScarletKuro Thank you very much for making a non-breaking PR. And yes, next major version we'll remove the old way of using the icons in favor of the new structure if @Garderoben agrees. |
|
Wow! Amazing! and @henon yes, yes yes! |
|
I uploaded it as a dev nuget 6.0.11-dev.1 |
JonBunator
left a comment
There was a problem hiding this comment.
We have a powershell script that automatically updates the icons: https://github.com/MudBlazor/MudBlazor/tree/dev/tools%2FIcons
I guess your PR will break it, won't it?
Yes, this PR will break it. But looking at the script it shouldn't be hard to adopt it.
Did this today. I tried trimming with MudBlazor.Docs to see what will work and what not. The MudBlazor library was something like ~1.2mb. Components that got broken for sure: I didn't really find yet why MudSelect got broken, but when you click on the Item, the dropdown doesn't disappear. [JSInvokable]
public void RaiseOnScroll(ScrollEventArgs e)
{
_onScroll?.Invoke(this, e);
}It's using JSInvokable and has no references, so it's simply got trimmed. There are other places with such issue, for example: KeyInterceptor, ResizeListenerService, ScrollSpy maybe some more but it's not hard to find those. My bet is that if we mark them with The rest actually looks like working fine. I had no issues with form validation, didn't see bugs in the MudDataGrid either. |
|
Okay, I think i fixed all interop, and now |
|
@JonBunator updated powershell script. |
Thank you! |
|
@ScarletKuro Great work. I would suggest adding the fixes to this PR. We don't want to merge known bugs even if the next PR fixes them. @henon @Garderoben after these fixes and before we merge should we publish the PR to MudBlazorTest ?Trimming bugs don't hit the test suite. Maybe the core team could run through the docs to see if they can find any broken bits and then compare to dev. |
|
Added to PR. the pattern was taken from aspnetcore. I think I can fix some TrimAnalyzer warnings, the JsonSerializer with SourceGenerator, but this will be somekind of breaking change. Currently it has no restriction on the eventType object, We can use JsonSerializerContext and make a "whitelist" of web events [JsonSerializable(typeof(EventArgs))]
[JsonSerializable(typeof(ChangeEventArgs))]
[JsonSerializable(typeof(ClipboardEventArgs))]
[JsonSerializable(typeof(DragEventArgs))]
[JsonSerializable(typeof(ErrorEventArgs))]
[JsonSerializable(typeof(FocusEventArgs))]
[JsonSerializable(typeof(KeyboardEventArgs))]
[JsonSerializable(typeof(MouseEventArgs))]
[JsonSerializable(typeof(PointerEventArgs))]
[JsonSerializable(typeof(ProgressEventArgs))]
[JsonSerializable(typeof(TouchEventArgs))]
[JsonSerializable(typeof(WheelEventArgs))]
internal sealed partial class WebEventJsonContext : JsonSerializerContext
{
}And then it will be trimm friendly. The breaking thing here is that it won't accept any kind of type. |
|
I made a new nuget with the new changes for testing: https://www.nuget.org/packages/MudBlazor/6.0.11-dev.2 |
|
@Garderoben @henon Is it ok to use MudBlazor-Test to publish this with docs? I saw it was used recently. |
|
Sure, why not? |
Just wanted to make sure someone wasnt using it for a current piece of work because I saw it was at 6.0.10 |
|
I published this to As discussed no icons in there as the reflection is not annotated but at least this tells us its trimmed version of docs. See if we can find any more issues. |
|
@mikes-gh did you host the MudBlazor.Docs.Wasm not the MudBlazor.Docs.WasmHost? If yes then as side note the table/datagrid won't be able to load the api(webapi/periodictable / webapi/americanStates) to show anything. Also if u want you can edit/remove the Content Security Policy in index.html to get rid of some errors in console. |
|
Youre right I'll republish |
|
OK Done sorry for delay. vscode publish wasnt working so had to use my work machine to publish with vs 2022 |
|
@ScarletKuro Could you fix the material icons in the docs please. I see for custom icons the class is instantiated so the custom icons don't get trimmed but material still only uses reflection so they are not in MudBlazor.dll. Of course this means that the docs wont have much saving from trimming but this is expected as the docs showcase nearly all the features. Or we could turn off trimming for the docs but there might be some savings? (I added |
|
@Garderoben For the purposes of the docs how about serving the icon page svg strings from the wasm host via api. That way we can keep the larger MudBlazor.dll server side and use only the smaller version in the WASM startup. |
Ty, now it's working
Ok i will look this one when I will have time.
If you just turn off the PubishTrimmed for wasm client then the libs won't be trimmed I have another question. Does it make sense to fix MudDataGrid trimm warnings or not? Because as I understood that someone is working on DataGrid anyway? We can avoid those either by using expression overload with type which is already marked with DynamicallyAccessedMembers public static MemberExpression Property(Expression? expression [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties|DynamicallyAccessedMemberTypes.NonPublicProperties)] Type type, string propertyName)else if(isNumber){
var nullableDoubleType = typeof(double?);
var isnotnull = Expression.IsTrue(Expression.Property(field, nullableDoubleType, "HasValue"));
var isnull = Expression.IsFalse(Expression.Property(field, nullableDoubleType, "HasValue"));
}
else if (isBoolean){
var isnotnull = Expression.IsTrue(Expression.Property(field, typeof(bool?), "HasValue"));
}
else if (isDateTime){
var nullableDateTimeType = typeof(DateTime?);
var isnotnull = Expression.IsTrue(Expression.Property(field, nullableDateTimeType, "HasValue"));
var isnull = Expression.IsFalse(Expression.Property(field, nullableDateTimeType, "HasValue"));
}or using wrapper internal class NullableProperty<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T> where T : struct
public static PropertyInfo HasValue { get; } = typeof(T?).GetProperty("HasValue");
}else if(isNumber){
var isnotnull = Expression.IsTrue(Expression.Property(field, NullableProperty<double>.HasValue));
var isnull = Expression.IsFalse(Expression.Property(field, NullableProperty<double>.HasValue));
}
else if (isBoolean){
var isnotnull = Expression.IsTrue(Expression.Property(field, NullableProperty<bool>.HasValue));
}
else if (isDateTime){
var isnotnull = Expression.IsTrue(Expression.Property(field, NullableProperty<DateTime>.HasValue));
var isnull = Expression.IsFalse(Expression.Property(field, NullableProperty<DateTime>.HasValue));
} |
|
it is already released as a preview nuget https://www.nuget.org/packages/MudBlazor/6.0.11-dev.3 |
|
@henon I'm rather waiting for version v6.0.11 for the fixes concerning memory leaks. I hope it will be available soon |
|
@Garderoben I ask again because I think it's important to have a new official (non-dev) version available to fix memory leaks. When will the release be available? |
|
There have been several inquiries about the release date of v6.0.11 but unfortunately no response as of yet. According to NuGet stats, v6.0.10-dev4 has been downloaded 2500 times already and browsing through the MudBlazor Issues, In our case, we are eagerly awaiting to make some new features available to our customers Somehow I can't help to feel that MudBlazor has lost traction over the last weeks. Please don't get me wrong, I do realize this is an open-source project and I very much appreciate My team already asked me twice now if I'm still sure that we made the right decision to choose MudBlazor. |
|
@ScarletKuro I personally use a fork of the dev branch on my project to get the latest features and I can also fix bugs and open PRs at the same time. I asked myself the same things, should I or not go with MudBlazor because of the overhead. Many form components are bugged and should be rewritten from scratch but still, this is an excellent open source project. A paid version or paid support could probably help. |
|
I think @Garderoben wanted to do the release two weeks ago but then something got in the way. That is exactly the reason why the preview releases exist, so we can make the fixes available to you all without much work on our part (no need to write the changelog and all the other adminstrative stuff @Garderoben does when he releases). He hasn't been feeling so well the last weeks so please give him some space and time. And yes, it is not easy to be there and serve the community all the time. Especially with that volume of issues and PRs we have. We'd really have to do this full time to be able to keep up. Until the time is right to go that way with paid support etc, we kindly ask you guys to sort out issues yourself and fix bugs you need fixed for your projects. It still requires a lot of work on our part to review the PRs. For any PRs which are time critical bug fixes you can request a review from me. I'll try to review as soon as I have a free hour and I'll do preview releases regularly to get those fixes out to the community. |
@boukenka There would not be much different between an official release and a dev preview except the name and the version. There is no guarantee that an "official" release contains less bugs than a dev preview. |
|
@ScarletKuro thanks! |
|
FYI v6.0.11 has finally been released. |
|
Unfortunately I have a breaking change after upgrading. But only because I have a special requirement in one project, I use reflection to get the icon from the Icons.Filled class. Is there a way to prevent this trimming for a specific project? |
|
@MarianSWA yes, there is a way. You can look commits of this PR, I did this for the docs. .GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);And to get the value its Another, more advance and harder way is to use LinkerConfig.xml and add this type to exception. Let me know if you need additional help with that. |
|
@ScarletKuro The first solution worked perfectly, thanks for the detailed answer 😄 |
…udBlazor#4639) * Add IsTrimmable to the library Make Icons as const to support trimming Add const Icon support in MudBlazor.Docs * Change Update-MudIcons.ps1 for new Icons structure * Add DynamicDependency to prevent trimming for JavaScript interop Fix conflict Fix * Do not trim icons for MudBlazor.Docs * Introduce WebEventJsonContext for trimming friendly deserialization in EventManager * Use trim friendly Expression.Property overload for FilterDefinition Remove unnecessary attribute from EventManager * Suppress warning for validation. And mark datagrid with RequiresUnreferencedCode * Add trim warning suppression in MudDataGrid Co-authored-by: Meinrad Recheis <[email protected]>
…udBlazor#4639) * Add IsTrimmable to the library Make Icons as const to support trimming Add const Icon support in MudBlazor.Docs * Change Update-MudIcons.ps1 for new Icons structure * Add DynamicDependency to prevent trimming for JavaScript interop Fix conflict Fix * Do not trim icons for MudBlazor.Docs * Introduce WebEventJsonContext for trimming friendly deserialization in EventManager * Use trim friendly Expression.Property overload for FilterDefinition Remove unnecessary attribute from EventManager * Suppress warning for validation. And mark datagrid with RequiresUnreferencedCode * Add trim warning suppression in MudDataGrid Co-authored-by: Meinrad Recheis <[email protected]>
…udBlazor#4639) * Add IsTrimmable to the library Make Icons as const to support trimming Add const Icon support in MudBlazor.Docs * Change Update-MudIcons.ps1 for new Icons structure * Add DynamicDependency to prevent trimming for JavaScript interop Fix conflict Fix * Do not trim icons for MudBlazor.Docs * Introduce WebEventJsonContext for trimming friendly deserialization in EventManager * Use trim friendly Expression.Property overload for FilterDefinition Remove unnecessary attribute from EventManager * Suppress warning for validation. And mark datagrid with RequiresUnreferencedCode * Add trim warning suppression in MudDataGrid Co-authored-by: Meinrad Recheis <[email protected]>
…udBlazor#4639) * Add IsTrimmable to the library Make Icons as const to support trimming Add const Icon support in MudBlazor.Docs * Change Update-MudIcons.ps1 for new Icons structure * Add DynamicDependency to prevent trimming for JavaScript interop Fix conflict Fix * Do not trim icons for MudBlazor.Docs * Introduce WebEventJsonContext for trimming friendly deserialization in EventManager * Use trim friendly Expression.Property overload for FilterDefinition Remove unnecessary attribute from EventManager * Suppress warning for validation. And mark datagrid with RequiresUnreferencedCode * Add trim warning suppression in MudDataGrid Co-authored-by: Meinrad Recheis <[email protected]>
…udBlazor#4639) * Add IsTrimmable to the library Make Icons as const to support trimming Add const Icon support in MudBlazor.Docs * Change Update-MudIcons.ps1 for new Icons structure * Add DynamicDependency to prevent trimming for JavaScript interop Fix conflict Fix * Do not trim icons for MudBlazor.Docs * Introduce WebEventJsonContext for trimming friendly deserialization in EventManager * Use trim friendly Expression.Property overload for FilterDefinition Remove unnecessary attribute from EventManager * Suppress warning for validation. And mark datagrid with RequiresUnreferencedCode * Add trim warning suppression in MudDataGrid Co-authored-by: Meinrad Recheis <[email protected]>
…udBlazor#4639) * Add IsTrimmable to the library Make Icons as const to support trimming Add const Icon support in MudBlazor.Docs * Change Update-MudIcons.ps1 for new Icons structure * Add DynamicDependency to prevent trimming for JavaScript interop Fix conflict Fix * Do not trim icons for MudBlazor.Docs * Introduce WebEventJsonContext for trimming friendly deserialization in EventManager * Use trim friendly Expression.Property overload for FilterDefinition Remove unnecessary attribute from EventManager * Suppress warning for validation. And mark datagrid with RequiresUnreferencedCode * Add trim warning suppression in MudDataGrid Co-authored-by: Meinrad Recheis <[email protected]>
…udBlazor#4639) * Add IsTrimmable to the library Make Icons as const to support trimming Add const Icon support in MudBlazor.Docs * Change Update-MudIcons.ps1 for new Icons structure * Add DynamicDependency to prevent trimming for JavaScript interop Fix conflict Fix * Do not trim icons for MudBlazor.Docs * Introduce WebEventJsonContext for trimming friendly deserialization in EventManager * Use trim friendly Expression.Property overload for FilterDefinition Remove unnecessary attribute from EventManager * Suppress warning for validation. And mark datagrid with RequiresUnreferencedCode * Add trim warning suppression in MudDataGrid Co-authored-by: Meinrad Recheis <[email protected]>
…udBlazor#4639) * Add IsTrimmable to the library Make Icons as const to support trimming Add const Icon support in MudBlazor.Docs * Change Update-MudIcons.ps1 for new Icons structure * Add DynamicDependency to prevent trimming for JavaScript interop Fix conflict Fix * Do not trim icons for MudBlazor.Docs * Introduce WebEventJsonContext for trimming friendly deserialization in EventManager * Use trim friendly Expression.Property overload for FilterDefinition Remove unnecessary attribute from EventManager * Suppress warning for validation. And mark datagrid with RequiresUnreferencedCode * Add trim warning suppression in MudDataGrid Co-authored-by: Meinrad Recheis <[email protected]>

@henon
As promised, if I find a non breaking way for Icons I will make a PR.
Fixes #2424
Description
This was detailed discussed in the issue ticket so I will move to details of this PR.
Since for better Trimming support there was need to switch from property to const string and not to hold class reference on Icons there was a little nuance - namespaces.
In MudBlazor you could access non-custom icons two ways, for example:
Icons.Filled.Addand
Icons.Filled.Material.Addthis is an issue for const because you can't do something like that
If you try to access it like this
Icons.Filled.ConstIconcompiler will give an error and tell you to useExampleConst.ConstIconinstead. This would be a breaking change because even inside MudBlazor in some places the icon was accessed viaIcons.Filledand in someIcons.Material.FilledSo my solution to this problem is following, ik its ugly and verbose, but at same time it's genius to keep the backward compatibility.
To keep the namespaces for Icons.Material.Filled(etc) I did this
to keep Icons.Filled I did this
Pretty much one of them just references another. Of course, I had to copy-paste all the fields twice, but don't worry, this doesn't add any extra size for the library, and luckily for us this gets trimmed without any issues.
NB! Icons.Filled, Icons.Outlined, Icons.Rounded, Icons.Sharp, Icons.TwoTone I moved to "Obsolete" folder(if you think the folder should have different name, please let me know), because in future I think the icons should be accessed only via Icons.Material.* and in new major version we should keep only one option.
Docs
I had to slightly modify the MudBlazor.Docs to support the const fields.
Difference
I also added to the MudBlazor.csproj
Otherwise, the trimming won't work with
<PublishTrimmed>true</PublishTrimmed>because dotnet doesn't touch libraries that aren't marked withIsTrimmableunless you force it with some magic like TrimmableAssembly or ManagedAssemblyToLink which is not obvious for most people.How Has This Been Tested?
Run the existing unit tests. Mostly visually, I made sure that the Icons work properly in MudBlazor.Docs and tested it on my production application.
Types of changes
Checklist:
dev).