Reducing Blazor WASM size by providing custom ICU data

 
 
  • Gérald Barré

The International Components for Unicode (ICU) is a set of libraries that provide Unicode and internationalization support for software applications. Unicode is a standardized encoding system representing almost all written languages worldwide. ICU provides a wide range of functions for working with Unicode text, including string search and replace, character conversion, and text normalization. It also supports various global scripts and locales, allowing applications to adapt to different language and cultural conventions.

One of the key benefits of ICU is that it enables applications to handle text consistently across different platforms and languages. This is especially important for international applications, as it ensures text is displayed and processed correctly regardless of the language or locale.

In a Blazor application, ICU data files provide support for globalization features such as date and time formatting, number formatting, and string comparison. However, the browser must download these files when the application loads, which increases both the application size and its load time.

Many applications only need to support a small number of languages, so the ICU data files can be customized to include only the required locale data. This can reduce the application size by a few hundred kilobytes and improve load time.

#Build custom ICU data files

  1. Open the dotnet/icu repository

  2. Create a new Codespace for the repository

  3. Customize the files icu-filters/icudt_*.json. For instance, you can remove a few locales to reduce the size of the data files

  4. Open a terminal in the Codespace

  5. Build the data files using ./build.sh /p:TargetOS=Browser /p:TargetArchitecture=wasm /p:IcuTracing=true

  6. Download the data files from artifacts/bin/icu-browser-wasm/

  7. Copy the file to the root folder of the Blazor project

.NET uses sharding to split the ICU data files into multiple files, allowing the browser to download only what is needed and reducing the overall download size (source code on GitHub). The following files are created:

  • icudt.json contains the data for all locales
  • icudt_CJK.json contains the data for all locales that use CJK characters
  • icudt_EFIGS.json contains the data for English, French, Italian, German, and Spanish locales
  • icudt_no_CJK.json contains the data for all locales that do not use CJK characters

#Use custom ICU data files

By default, the ICU data files are provided by the .NET SDK. To use custom ICU data files, configure the project as follows:

app.csproj (csproj (MSBuild project file))
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">

  <Target Name="UseCustomICU" AfterTargets="ResolveRuntimePackAssets">
    <ItemGroup>
      <ReferenceCopyLocalPaths Remove="@(ReferenceCopyLocalPaths)"
                               Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dat' AND $([System.String]::Copy('%(ReferenceCopyLocalPaths.FileName)').StartsWith('icudt'))" />

      <ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)icudt.dat" DestinationSubPath="icudt.dat" />
      <ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)icudt_CJK.dat" DestinationSubPath="icudt_CJK.dat" />
      <ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)icudt_EFIGS.dat" DestinationSubPath="icudt_EFIGS.dat" />
      <ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)icudt_no_CJK.dat" DestinationSubPath="icudt_no_CJK.dat" />
    </ItemGroup>
  </Target>
</Project>

If you only want to use the main ICU data file, you can force the app to load only icudt.dat by adding the following property to the project file:

csproj (MSBuild project file)
  <PropertyGroup>
    <BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
  </PropertyGroup>

A custom data file including only en_US and fr_FR locales is 131 kB after Brotli compression, compared to 321 kB for the original. That's a saving of 190 kB!

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?