Работа с WebAssembly и C#: от А до Я в .NET

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: почему WebAssembly меняет правила игры для C# разработчиков

Долгое время веб-разработка была монополией JavaScript. Однако с появлением WebAssembly (Wasm) ситуация кардинально изменилась. Теперь разработчики на C# могут компилировать свой код в бинарный формат, который выполняется в браузере с почти нативной скоростью. Это открывает огромные возможности: от портирования тяжелых алгоритмов до создания полноценных SPA-приложений на Blazor.

В этой статье мы разберем, как работает WebAssembly в связке с C# и .NET, рассмотрим ключевые инструменты (Blazor, Wasmtime, Mono) и напишем практические примеры. К концу вы сможете самостоятельно запустить C# код в браузере или на сервере с помощью Wasm.

Основы WebAssembly и его интеграция с C#

Что такое WebAssembly простыми словами

WebAssembly — это низкоуровневый байт-код, который исполняется в виртуальной машине браузера. Он не заменяет JavaScript, а работает вместе с ним. Основные преимущества:

  • Производительность: бинарный код выполняется на 30-50% быстрее JS.
  • Безопасность: изолированная среда выполнения.
  • Переносимость: один и тот же .wasm файл работает в Chrome, Firefox, Safari и Edge.

Для C# экосистема WebAssembly реализована через несколько проектов: Blazor WebAssembly (фреймворк для UI), Mono Wasm Runtime (исполняет IL-код) и Wasmtime (для серверных сценариев).

Как C# компилируется в WebAssembly

Процесс выглядит так:

  1. Вы пишете код на C#.
  2. Компилятор Roslyn превращает его в IL (промежуточный язык).
  3. Mono Runtime (или NativeAOT) транслирует IL в WebAssembly.
  4. Браузер загружает .wasm файл и исполняет его.

Важно: существует два подхода — интерпретация через Mono (медленнее, но проще) и AOT-компиляция (быстрее, но требует настройки).

Практика: три способа запустить C# в WebAssembly

1. Blazor WebAssembly — для веб-интерфейсов

Blazor позволяет писать клиентскую часть на C# вместо JavaScript. Весь UI-код и бизнес-логика компилируются в Wasm.

Пример простого компонента:

@page "/counter"
<h3>Счетчик: @currentCount</h3>
<button @onclick="IncrementCount">+1</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

Этот код выполняется в браузере. Blazor автоматически загружает Mono Wasm Runtime и ваш .wasm файл. Для старта создайте проект:

dotnet new blazorwasm -o MyBlazorApp
cd MyBlazorApp
dotnet run

Результат: полноценное SPA-приложение без единой строчки JavaScript.

2. Прямая компиляция в .wasm с помощью NativeAOT

Если вам нужно выполнить конкретную функцию (не UI), используйте NativeAOT — он компилирует C# напрямую в нативный WebAssembly без Mono Runtime.

Шаги:

  1. Установите SDK .NET 8+ и workload: dotnet workload install wasm-tools
  2. Создайте консольное приложение:
dotnet new console -n WasmDemo
cd WasmDemo
  1. Измените .csproj, добавив поддержку Wasm:
<PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
    <UseNativeAot>true</UseNativeAot>
</PropertyGroup>
  1. Напишите код:
using System;

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Hello from WebAssembly!");
    }
    
    // Экспортируемая функция для вызова из JS
    [System.Runtime.InteropServices.UnmanagedCallersOnly(CallConvs = new[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })]
    public static int Add(int a, int b) => a + b;
}
  1. Скомпилируйте: dotnet publish -c Release

В папке bin/Release/net8.0/browser-wasm/publish появится файл WasmDemo.wasm, который можно вызывать из JavaScript:

const wasm = await WebAssembly.instantiateStreaming(fetch('WasmDemo.wasm'));
const result = wasm.instance.exports.Add(5, 3);
console.log(result); // 8

3. Wasmtime — запуск C# WebAssembly на сервере

Wasmtime — это среда выполнения WebAssembly вне браузера. С помощью пакета Wasmtime для .NET вы можете загружать .wasm файлы в своих серверных приложениях.

Пример:

using Wasmtime;

// Загружаем скомпилированный .wasm файл
using var engine = new Engine();
using var module = Module.FromFile(engine, "calc.wasm");
using var linker = new Linker(engine);
using var store = new Store(engine);

// Создаем экземпляр модуля
var instance = linker.Instantiate(store, module);

// Получаем функцию
var add = instance.GetFunction<int, int, int>("Add");
if (add != null)
{
    int result = add(store, 10, 20);
    Console.WriteLine($"10 + 20 = {result}"); // Вывод: 30
}

Это полезно для песочниц кода, плагинов или изоляции сторонних скриптов.

Оптимизация и ограничения

Производительность: что нужно знать

  • AOT vs Interp: NativeAOT дает прирост скорости 2-3x, но увеличивает размер .wasm файла (до 5

Блоги

Рекомендаций по книгам