Как я сказал в первой части этой статьи, мы решили написать систему, которая преобразует команды для отправки многочисленных инструкций на различные IoT реле на Blazor. Где по-быстрому, практически на коленке собрали отличную систему работы с этими реле. Всё было просто замечательно и быстро! Но не всё было так просто, как обещали.

Теперь давайте погрузимся в тёмный лес странных вещей, с которыми пришлось разбираться в Blazor. Естественно, технология не самая новая, и на Stackoverflow с большинством описанных проблем более-менее разобрались. Местами остался неприятный осадок, местами — недопонимание.

Итак, подводные камни Blazor, на которые вы наткнётесь в ваших проектах.

Камень 1 — WASM


Практически самая бесполезная часть работы с Blazor. Почему? Потому что итоговый размер бинарника поражает воображение. Во время дебага приложения я залез в консоль и увидел, что конечный размер всех бинарников превысил 15 мегабайт. После запуска релиза размер был взят под контроль и составил 7 мегабайт.

В принципе, если мы говорим о том, что вы выпускаете приложение во внутрикорпоративной сети, и клиенты в конце концов закешируют сам WASM, то можно отмахнуться. Но для запуска чего-то подобного для мобильных пользователей размер бинарников может быть намного более устрашающим.

Конечно, существуют способы для уменьшения размера выходного бинарника, например, вот тут. Но тут уж очень сомнительные приёмы. Например, вырезание информации о временных зонах, которые обычно используются в приличных приложениях. С учётом всех ужимок можно спустить размер бинарника до четырёх мегабайт.

Но при всём при этом, если писать на vugu(golang), то можно начать с 3-х мегабайт и жать до одного.

Так что сама разработка на подобном фреймворке — это что-то, что должно происходить после долгого и основательного обдумывания. Опять же, даже если мы переключим наше приложение в режим server-side, то оно не будет по-человечески работать без стабильного канала. А если связь выпадает один раз и что-то не рендерится, то приложение вылетает по полной программе и страницу надо будет перезагружать. При этом теряется весь стейт приложения.

Итак, заключение: WASM в Blazor хоть и есть, но является одним из самых тяжеловесных фреймворков, которые существуют на рынке.

Камень 2 — Razor


Название Blazor происходит от Razor. И хотя сам Razor (2010) намного старше Blazor (2018), в нём есть определённые, мягко выражаясь, странности.

Например, очень странно видеть, как такой, казалось бы, достаточно старый движок, непростительно относится к мелким ошибкам в коде. Один пропущенный символ @ приводит к абсолютно полному пересмотру всего кода страницы. Причём это никак не сообщается в процессе разработки. VSCode вообще об этом умалчивает (и подсвечивает код, как будто он написан правильно), а Visual Studio просто перестаёт подсвечивать код как код, и показывает его как текст.

Причём во время сборки все опять молчат, как партизаны, но зато вы увидите хороший дамп во время дебага.

Для людей, пришедших в разработку с React, это будет очень раздражительно.

Вывод? За Razor нужен глаз да глаз. Пишите бога ради, но обязательно проверяйте, что вы написали, потому что очепятки останутся незамеченными без хорошего тестирования.

Камень 3 — Общение компонентов


Как и в React, в Blazor существует понятие о том, что такое компоненты. И действительно, лично для меня в обоих языках компонентная система была самой используемой фичей. Но при всём при этом компоненты в Blazor намного более необщительные, чем в React.

Если я меняю строку поиска в компоненте поиска и хочу отобразить новые результаты в списке результатов на той же странице, то приходится доставать бубны.

В React с этим не всё так гладко, но всё же, есть намного больше способов общаться между компонентами. Существуют Overmind, MobX и старый добрый Redux. В Blazor такого пока что не наблюдается. Приходится использовать свои собственные костыли или просто смириться с существующей системой компонентов.

Итогом этих поисков стал отдельный компонент под названием Refresher, который создавал виртуальные каналы. На эти каналы подписывались компоненты. При вызове события на канале все подписанные компоненты обновлялись. Немного странно и непривычно, но можно было жить.

Конечно, альтернативным вариантом было бы написание различных страниц и просто пропуск функционала обновления одних компонентов из других компонентов. Но это как-то бедно, я бы сказал.

Выводы: Прекрасное общение между компонентами нужно будет реализовывать руками.

Камень 4 — Жизненный цикл


И борьба с этим жизненным циклом. Если вы пришли из мира MVC, то вы наверняка знаете, что существуют различные стадии жизненного цикла страниц и компонентов. В Blazor незнание и непонимание любых аспектов жизненного цикла просто фатально.

Казалось бы, что может быть проще? У тебя есть компонент, который хочет подписаться на события в начале своего жизненного цикла и отписаться от них в конце этого цикла.

Прекрасно, так и сделаем.

async protected override Task OnInitializedAsync()

{

	Refresher.Subscribe("ReBlaze.Pages.Devices", () =>

	{

    	UpdateDb().Wait();

    	InvokeAsync(StateHasChanged);

	});

	await UpdateDb();

	await base.OnInitializedAsync();

}

public void Dispose()

{

	Refresher.Unsubscribe("ReBlaze.Pages.Devices");

	Context?.Dispose();

}

И тут мы начинаем влетать в очень интересные дебри и проблемы. Сразу же стало понятно, что что-то не так, когда в SQL профайлере начали появляться двойные запросы в базу данных, а компонент по обработке подписок оказался постоянно поломанным из-за переподписок.

Пришлось лезть и разбираться, и в итоге после недолгих поисков был найден виновник. Им оказался тот ученик, который не сел и не изучил систему обработки жизненного цикла от начала и до конца. Естественно, жизненный цикл будет разным для WASM и Server-side приложения. Это да.

Но он в том числе будет разным для Server-side и Server-side. Чего? Ну да, мы как бы забыли вам сказать, и вы с этим встретитесь в мануалах, но чуть глубже. У нас есть два варианта Server-Side Blazor, один из них это Server Pre-Render. Этот замечательный вариант обработки будет рендерить страницу на сервере, чтобы она была. Это сделано для совместимости с поисковиками и для того, чтобы страница быстрее доставлялась на клиент при первом открытии.

Когда пользователь обращается к странице в первый раз, мы её рендерим на сервере и отсылаем на сторону пользователя. А когда она отобразится, то специальный javascript дозагрузит все необходимые компоненты, и страница начнёт работать. Всё замечательно, но при этом мы ещё раз запустим ваше событие OnInitialized. Ну так, чисто чтобы поржать.

Что мы получаем в итоге?

Жесть и безобразие. Страницы, которые неправильно отображают пустые компоненты, двойные запросы и поломанные менеджеры состояния.

После того как все уже были сыты по горло этими проблемами, я удалил из репозитория весь код, связанный с системой событий, и отправил всех читать мануалы на два дня.

После такого жёсткого обращения с детьми у нас появилось представление о том, что да как надо делать, и как правильно обрабатывать события жизненного цикла.

Ввиду того что приложение было локальным, мы просто отключили Server-Sider Pre-render и пошли простым путём.

Выводы: Если вы изучаете Blazor, ни в коем случае не пропускайте никаких материалов о том, как работать с жизненным циклом. Такие материалы просто жизненно необходимы для понимания того, как писать программу.

Камень 5 — Сообщество


Оно есть, но оно очень вялое. Естественно, когда вы придёте в сектор корпоративной разработки на Blazor из мира npm, то вы решите, что всё вообще заброшено.

На Blazor написана одна и большая CMS под названием oqtane. Система позволяет писать свой код на Blazor и при этом более-менее по-человечески управлять контентом. С точки зрения разработки, выглядит это просто жестоко.

При создании плагина для Oqtane вам нужно будет установить саму CMS, после чего вам нужно будет создать сайт и в нём уже создавать плагин. Результатом создания плагина будет новый Solution, который надо будет открывать в VS и продолжать писать этот плагин.

Сомнительное удовольствие. Сам Oqtane пушится повсюду его создателем, и хотя коммиты делаются до сих пор, выглядит CMS в лучших традициях 2016 года.

Вывод? Самый лучший способ выучить Blazor — это либо прочитать инструкцию, либо взяться за толковый талмуд, учить методом тыка его не стоит. Он к этому очень непростителен.

Выводы


Что мы имеем? Что-то такое очень интересное. Попытка взять первое место в мире подобных фреймворков идёт в никуда. Если в 2019 году я ещё видел статьи о том, что Microsoft наконец-то выпустила убийцу React, то в 2021 году подобных статей поубавилось, да и хайпа не так много.

В итоге у нас получилась очень хорошая система для тех, кто работает в корпоративном секторе. Blazor как нельзя лучше подойдёт для внутрисетевых веб-сайтов, которые будут подгружать корпоративные данные и показывать их на экране. Портирование уже существующего C# кода на Blazor и WASM не займёт много времени. Поддержка компилирования на очень высоком уровне. И да, вы сможете напрямую использовать .NET WASM, он компилируется и очень даже стабилен. Естественно, определённые вещи в WASM недоступны, но обычная бизнес-логика переносится за секунды.

Плюс, Blazor очень легко встроить в уже существующие .NET проекты. С этим особых проблем нет.

Писать 3Д игру в браузере на Blazor? Нет, всё же лучше не стоит. Если уж очень хочется таким заниматься, то добро пожаловать в мир Rust. Yew вам в помощь. Тут мы получаем намного более компактные бинарники. Или, если хочется, вот вам C++ awesome-wasm.

С другой стороны, в мире WASM фреймворков высокоуровневых языков .NET является самым продвинутым. pyodide.org и vugu.org ещё не видели такой поддержки, как .NET. Только вот в этом и заключается загвоздка. .NET, golang, python — это языки, изначально разработанные для другой платформы, нежели WASM. И хотя мы и научили их компилироваться прямо в окно браузера, выглядят эти фреймворки очень даже сомнительно, в основном потому что тянут за собой наследие платформ, для которых они разрабатывались.

Хотя, несомненно, Server-Side Blazor лишён этих недостатков и просто является большой утилитой по сокрытию огромного количества подлежащего кода, который служит для выполнения ваших инструкций.

При наличии хорошего стабильного канала, эта утилита работает более чем прилично.

Учить Blazor стоит, но только если вы уже погружены в инфраструктуру .NET и готовы с ней работать. Начинать новый сервис можно и на более распространённых языках. Возьмитесь лучше за изучение TS и React.


НЛО прилетело и оставило здесь промокоды для читателей нашего блога:

15% на все тарифы VDS (кроме тарифа Прогрев) — HABRFIRSTVDS.

— 20% на выделенные серверы AMD Ryzen и Intel Core HABRFIRSTDEDIC.

Доступно до 31 декабря 2021 г.

Комментарии (3)


  1. Nurked
    02.11.2021 11:07

    Всё больше и больше меня удивляет политика майкрософта. Вечно гоняют я за какими-то инновация и, которые на поверку оказываются бесполезными. После чего эти инновации сливаются куда-то и переделываю я от начала до конца, и в конечном итоге получается приличный продукт.

    Вышел Windows 11. Мы сидим и ждём Windows 12.

    Вышел блазор. Он, конечно хорош, но страшно лимитирован, как вы пишите.

    Может ребятам пора прекращать этот порочный цикл? Веть есть же у них продукты, которые мы все любим. [та же vscode]

    Эээх.


    1. Kanut
      02.11.2021 11:22

      Ну да блазор пока ещё имеет свои границы. И "в прод" его пока мало кто готов пихать. С другой стороны у него всё равно есть приличная ниша куда он может прочно засесть. Например написание всяких "внутренних" вещей как указано в статье.


      То есть банально у нас куча вещей для интранета сделана на блазоре. Потому что C#/Wpf умеет куча людей, а вебом мы не занимаемся от слова совсем. И нам в этом плане блазор очень хорошо зашёл.


  1. x2v0
    02.11.2021 13:51

    правильно я понял, что главный недостаток wasm - он толстый?
    https://github.com/microsoft/reverse-proxy
    Что Вы думаете о связке wasm & yarp?