You want to create a high performance native AOT Razor library. This library should be quick and use less memory. .NET 8 now supports native AOT, which makes Razor libraries faster and more efficient. The Razor Slices story illustrates how to update old code for high performance native AOT. This approach helps you achieve better performance. By following the right steps, you can build modern and lightweight web apps.
Key Takeaways
Native AOT compilation in .NET 8 makes apps run faster. It also makes them smaller. It turns code into native files before running. This means you do not need the .NET runtime.
Razor libraries help web development by letting you reuse UI components. This makes your project easier to organize. It also helps your app work better. You do not need JavaScript for this.
Use fewer dependencies in your project. This helps your app start faster. It also lowers problems. Your app will be easier to fix and share.
Be careful with reflection. It can cause trouble with native AOT. Do not use runtime type discovery. Precompile Razor views to keep things working well.
Make your library smaller or faster, depending on what you need. Use Span-friendly APIs to make your app work better and use less memory.
Native AOT and Razor Basics
What Is Native AOT
Native Ahead-Of-Time (AOT) compilation in .NET 8 makes apps faster and smaller. Native AOT turns your .NET code into files that work on one system. This happens when you build your app. Your app does not need the .NET runtime on the computer where it runs. The app starts right away and uses less memory because it is already ready for the system.
Native Ahead-Of-Time compilation, called Native AOT, changes your code into native code for a chosen platform. There is no JIT at runtime.
Here is a simple comparison between Native AOT and traditional compilation:
Native AOT apps cannot use unbound reflection. When you publish, unused code gets removed. This makes your app smaller. These features make Native AOT a good choice for high performance native AOT libraries.
Why Razor Libraries Matter
Razor libraries are important in .NET web development today. You use them to make UI parts you can use again and to let the server create content. This helps your app work better and gives users a good experience.
Razor libraries let you build without JavaScript. You use C# and .NET and do not need to handle hard client-side code.
The way components work helps you keep your project neat. You can use the same parts in many apps, which saves time.
Razor Components use the browser as a thin client. The server does the work and updates the UI, so your app is faster and uses less memory.
Here is how Razor libraries help big projects:
When you use Razor libraries with Native AOT, your web apps start fast, use less memory, and are easy to manage. This mix is important for building .NET solutions that work well and can grow.
High Performance Native AOT Strategies
To build a high performance native AOT Razor library, you must plan well. You should try to use fewer dependencies, handle reflection carefully, and pick the best optimization settings. These steps help you make web apps that are fast, reliable, and light.
Minimizing Dependencies
Try to keep your dependencies small. Fewer dependencies help your app start faster and avoid problems. Using only what you need makes your app easier to update and share.
Here is a table that shows the good and bad sides of using native AOT with fewer dependencies:
To keep dependencies low, you can:
Check your project and remove packages you do not use.
Pick libraries that work with native AOT.
Stay away from libraries that use a lot of dynamic features or reflection.
When your project is small, it is easier to make a high performance native AOT Razor library.
Handling Reflection and Trimming
Reflection can be tricky with native AOT. Native AOT cuts out code you do not use, so reflection might not find everything at runtime. You should write your code to avoid these problems.
Here are some tips:
Write code that does not need to find types while running.
Precompile all Razor views, since you cannot compile them at runtime.
Tip: Always test your app after trimming to make sure nothing is missing.
Trimming and native AOT make your app faster and smaller. For example, ASP.NET apps get smaller files and run faster. SignalR now lets you use different types for hub methods, which helps with dynamic needs. SignalR also tracks what happens in each hub method, so you can debug more easily.
Optimizing for Size or Speed
You can choose to make your native AOT Razor library smaller or faster. Each choice has ups and downs. If you make the file smaller, it may download faster, but it might run slower. If you make it faster, it may run better, but the file could be bigger.
Making your app smaller can sometimes make the files bigger because of precompiled code. This can slow down downloads. But your app runs faster because it does not need to compile code while running. You should pick what works best for your app.
You can set the <OptimizationPreference>
in your project file. Here is a table that explains your choices:
To make your app even faster, use Span-friendly APIs. These help you work with data quickly and use less memory. When you use Span-friendly APIs and the right settings, your app can be very fast.
Note: Always check your app to see how changes affect size and speed. Change your settings based on how your app is used.
If you follow these tips, you can make a high performance native AOT Razor library that is fast, efficient, and ready for today’s web apps.
Setup and Configuration
To make a high performance native AOT Razor library, you need to plan. You should set up your project, turn on native AOT, and add Razor components the right way. Here are the steps to help you begin.
Project Structure
First, put your project files in order. Put Razor components in their own folder, like /Components
or /Pages
. Put your logic and services in other folders. This setup helps you find things fast and keeps your project tidy.
Tip: Name your folders clearly for components, services, and tools. This helps you manage your project as it gets bigger.
Enabling Native AOT
You have to change your project file to use native AOT. Open your .csproj
file and add these settings:
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<PublishAot>true</PublishAot>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>link</TrimMode>
</PropertyGroup>
These settings decide how your app builds and runs.
PublishAot
makes a file that works by itself.PublishTrimmed
andTrimMode
help make your app smaller.
You might need to add a package for daily builds:
<ItemGroup>
<PackageReference Include="Microsoft.DotNet.ILCompiler" Version="8.0.0-*" />
</ItemGroup>
Change your nuget.config
if you need a special NuGet feed.
Integrating Razor Components
Add your Razor components to your project and link them in your main app. Precompile your Razor views so you do not need to compile them later. This step helps your app work better with native AOT.
AOT compilation in Blazor WebAssembly makes your app run faster, especially for hard tasks. Your app is quicker because .NET code turns into native code. This can make your app bigger, but it will be faster and use less memory.
If you follow these steps, your project will be ready for a high performance native AOT Razor library. Always test your build to make sure everything works right.
Real-World Example: Razor Slices
Retrofitting for Native AOT
The Razor Slices story teaches us a lot. Damian Edwards and David Fowler wanted Razor Slices to work with native AOT. They started with a library that used old Razor code. To make it work with native AOT, you must find code that uses reflection or dynamic features. These features do not work well with native AOT. You should swap them for code that runs when you build the app. In Razor Slices, the team stopped compiling views at runtime. They made sure all Razor files were ready before running. This helped the library start faster and use less memory.
Tip: Always look for runtime features in your code. Try to use solutions that work at compile time instead.
Using Source Generators
C# source generators are very important for Razor Slices and native AOT. You use source generators to make code while building your app. This means you do not need reflection when the app runs. Source generators help you avoid problems with trimming and linking. They let you create the code you need for Razor views before your app starts. This makes your app faster and helps it work better with native AOT. Your build is smoother and your app runs quicker.
Here is a simple example of using a source generator:
[Generator]
public class MyRazorGenerator : ISourceGenerator
{
public void Execute(GeneratorExecutionContext context)
{
// Generate code for Razor views here
}
public void Initialize(GeneratorInitializationContext context) { }
}
Leveraging Span APIs
You can make your Razor library faster by using Span-friendly APIs. Span lets you work with parts of memory without copying data. In Razor Slices, the team used Span APIs to handle strings and buffers better. This change made the library use less memory and run faster. Using Span APIs helps your app process data quickly and safely.
Here are some good things about Span APIs:
Uses less memory
Processes data faster
Makes code safer and has fewer bugs
When you use both source generators and Span APIs, you can build a high performance native AOT Razor library that is fast, small, and easy to keep up.
Troubleshooting
Common Issues
When you build a native AOT Razor library, you may face some common problems. You should know what to look for so you can fix issues quickly.
You might see a segfault when you call a library made with .NET Native AOT from Java on Linux. This can happen because the two systems do not always work well together.
Sometimes, the segfault appears after your program finishes running. This means your code works, but there could be trouble with memory cleanup.
You may run into runtime errors if your app uses APIs that do not support native AOT. Some code patterns need the JIT compiler, which native AOT does not use.
If you publish a Blazor WebAssembly app in release mode and use IIS Express, you might get an AOT runtime error. The app may work with dotnet-serve, but not with IIS Express. This shows that you need to serve the right files for native AOT to work.
Tip: Always test your app on the target system and server to catch these issues early.
Debugging Tips
You can solve many problems by following smart debugging steps. Use the right tools and check your code for patterns that do not work with native AOT.
Check your project for unsupported APIs before you publish.
Use source generators to replace reflection and dynamic code.
Test your app after trimming to make sure all needed code stays in the build.
If you see errors, look at your build logs and runtime messages. These can show you where the problem starts.
Note: Always keep your tools up to date. New versions often fix old problems.
Resources
You can learn more and solve problems by using helpful resources. These guides and forums give you answers and tips from other developers.
You can read about planned updates for Native AOT in .NET.
You can find guides for calling C# libraries from other languages.
Tip: Join developer forums and follow .NET updates to stay ahead of new changes.
You can make a high performance native AOT Razor library if you follow simple steps.
Use NativeAOT compilation in .NET. This helps your app start quickly and use less memory.
Write code using new C# features like pattern matching and async streams. These make your code safer and easier to read.
Pick packages from the big NuGet ecosystem. These packages help you fix many problems.
Test your app many times and keep making your code better. Try native AOT in your Razor projects and tell others what you learn.
FAQ
How do you check if your Razor library supports native AOT?
Open your .csproj
file and look for <PublishAot>true</PublishAot>
. Test your app after trimming. If it runs without errors, your library supports native AOT.
What should you do if your app fails after trimming?
Look at your code for reflection or dynamic features. Change them to compile-time solutions. Use source generators when you can. Test your app again to see if it works.
Can you use third-party packages with native AOT?
Pick packages that work with native AOT. Check the documentation to make sure. Stay away from packages with lots of reflection or dynamic code. Test your app after you add new packages.
How do you make Razor views work with native AOT?
Precompile all Razor views before you publish your app. This step means you do not need runtime compilation. Use source generators to make code during build time.
What tools help you debug native AOT issues?
Use build logs, runtime messages, and analyzers. Source generators help you find problems early. Check official .NET resources for updates and answers.