Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loading xaml on demand to decrease app size after trimming #69

Open
hez2010 opened this issue Aug 21, 2022 · 1 comment
Open

Loading xaml on demand to decrease app size after trimming #69

hez2010 opened this issue Aug 21, 2022 · 1 comment

Comments

@hez2010
Copy link

hez2010 commented Aug 21, 2022

Currently XamlX emitted a huge !CompiledAvaloniaXaml.!XamlLoader.TryLoad which puts all xaml files into a single method, which leads to all generated code being preserved after trimming, even if some of those xaml files were not being used.

For example, the !XamlLoader.TryLoad for Avalonia.Themes.Fluent is:

	public static object TryLoad(string P_0)
	{
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Accents/AccentColors.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Accents/AccentColors.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Accents/Base.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Accents/Base.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Accents/BaseDark.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Accents/BaseDark.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Accents/BaseLight.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Accents/BaseLight.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Accents/FluentControlResourcesDark.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Accents/FluentControlResourcesDark.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Accents/FluentControlResourcesLight.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Accents/FluentControlResourcesLight.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Controls/AutoCompleteBox.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Controls/Button.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Controls/Button.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Controls/ButtonSpinner.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Controls/ButtonSpinner.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Controls/Calendar.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Controls/Calendar.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Controls/CalendarButton.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Controls/CalendarButton.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Controls/CalendarDatePicker.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
		if (string.Equals(P_0, "avares://Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml"))
		{
			return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Controls/CalendarDayButton.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
		}
                // .....
		return null;
	}

which leads to all those compiled xaml code being kept even if the user only use a Button in the app.

To make the loading process on demand, instead of emitting all things in a single TryLoad, emitting TryLoad_{uri} is a more properate choise. In this case, the TryLoad for avares://Avalonia.Themes.Fluent/Accents/AccentColors.xaml will become:

public static object TryLoad_avares://Avalonia.Themes.Fluent/Accents/AccentColors.xaml
{
    return CompiledAvaloniaXaml.!AvaloniaResources.Build:/Accents/AccentColors.xaml(XamlIlRuntimeHelpers.CreateRootServiceProviderV2());
}

To achieve trimming compatibility, we also need to introduce an attribute which save related types using string or Type with DynamicallyAccessedMembers, so that the trimmer can figure out which types are being used during compilation.

This is a breaking change, I would like to see the change landing before 11.0 GA getting released.

@kekekeks
Copy link
Owner

Another problem would be FluentTheme itself referencing all of the styles directly.
I wonder if IL linker supports weak references, so we could generate something like this:

if(CompilerServices.IsTypeReferenced<Button>())
    this.Add(new StyleInclude(...))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants