27
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

なぜ私は Blazorの設計は失敗だったと思っているのか

27
Last updated at Posted at 2026-04-06

本記事は筆者の考えをベースに、ChatGPT 5.4 を用いて構成・推敲したものです。
内容の主張と判断は筆者によるものであり、文章表現の整理に ChatGPT 5.4 を活用しています。


Blazor は .NET Core 3.0 のタイミングで主流の流れに入り、2019 年 9 月 23 日の .NET Core 3.0 正式リリースとともに広く知られるようになりました。2026 年の今から見ると、もう約 6 年半が経っています。普通、フレームワークが本当に強ければ、このくらいの時間があれば複雑な商用システムの現場で広く定着していてもおかしくありません。ですが、少なくとも私の観測では、Blazor はそこまでの位置には行けませんでした。 (Microsoft for Developers)

以前私が在籍していた会社では、実際に Blazor を使って大規模な商用アプリケーションを開発していました。なので、これは外から眺めて適当に批判している話ではありません。むしろ、実際に使って、チーム開発をして、運用や保守まで触れたからこそ、私は「これは単にエコシステムが未成熟という話ではなく、設計の方向そのものに無理がある」と感じるようになりました。

この記事では Blazor Server に絞って話します。Blazor WebAssembly は、私の感覚ではさらに厳しい問題を抱えていますが、そこまで広げると話が散るので今回は扱いません。Blazor Server だけでも、十分に本質的な問題が見えます。

便利そうに見えるが、複雑さを消してはいない

Blazor Server の売り文句はとても魅力的です。C# で UI を書ける、フロントエンドとバックエンドを同じ言語で貫ける、JavaScript を減らせる。特に .NET を主戦場にしてきた開発者にとって、このメッセージはかなり刺さります。

でも、実際には複雑さは消えていません。Blazor Server は UI をサーバー側で動かし、ブラウザ側のイベントを SignalR でサーバーへ送り返し、差分更新をまたクライアントへ返すモデルです。つまり見た目は Web アプリでも、実態は「サーバー上で持っている UI セッションを遠隔操作している」構造です。 (Microsoft Learn)

ここが重要です。
Blazor Server は、前後分離が持っていた複雑さをなくしたのではなく、接続・状態・例外・認証・デプロイ経路の複雑さに置き換えただけです。

表面上は API の境界が減ったように見えます。しかし実際には、ブラウザはブラウザのままですし、ネットワークはネットワークのままですし、認証やセッション管理の問題も消えません。JavaScript エコシステムも依然として現実に存在します。
つまり、Blazor Server は前後分離のつらさを解決したのではなく、別の場所に隠しただけです。

フロントエンドの小さなミスが、接続レベルの障害になる

ここが、私が Blazor Server を根本的に信用できない最大の理由です。

通常の前後分離の構成であれば、フロントエンドのバグはまずフロントエンド側の問題として現れます。もちろんユーザー体験としては最悪ですが、少なくとも責務の境界は比較的わかりやすい。

Blazor Server ではそうはいきません。公式ドキュメントにもある通り、Blazor は多くの未処理例外をその circuit に対する致命的なエラーとして扱います。未処理例外で circuit が終了すると、ユーザーがそのまま操作を続けるにはページをリロードして新しい circuit を作り直すしかありません。他のユーザーや他のタブには影響しないこともありますが、当該ユーザーにとってはその場でアプリが実質的に死にます。 (Microsoft Learn)

これが意味するのは、UI 層の小さな不具合が、単なる「画面のバグ」では済まなくなるということです。
状態が飛ぶ。接続が切れる。再読み込みしないと戻れない。
結果として、ユーザーから見れば「さっきまで動いていたのに、急に壊れた」になります。

しかもチーム開発では、こういう脆さが増幅されます。
開発者の意識では「ページを少し触っただけ」でも、実際の影響は circuit の断絶です。つまり、フロントエンドを触っているつもりで、接続と状態のライフサイクルにまで手を突っ込んでいることになります。これは設計としてかなり危ういです。

SignalR・認証・接続ライフサイクルが絡み合いすぎている

Blazor Server の設計で、実務上もっとも厄介だと感じたのがここです。

Blazor Server は本質的に 長寿命の接続を前提とした有状態システム です。公式ドキュメントでも、サーバー側の Blazor は circuit を維持し、切断時にはその circuit を「切断済みプール」に入れて一定時間再接続を待つ仕組みを持つと説明されています。既定では 3 分ほど再接続の猶予があり、当然ながらサーバーはそれを無限に保持できず、タイムアウトやメモリ圧迫時には解放します。 (Microsoft Learn)

この時点で、もう普通の request/response 型の Web アプリとはかなり違います。
認証、初期表示、ユーザー状態の復元、切断、再接続、メモリ保持。これらが全部「一回の HTTP リクエスト」で閉じる話ではなくなります。

さらに面倒なのが認証です。Blazor は既存の ASP.NET Core の認証機構を使います。つまり、認証そのものは ASP.NET Core 側の世界に乗っています。ところが UI は circuit 上で生きているので、認証状態を UI 側のライフサイクルで扱う場面が頻繁に出てきます。しかも現実のアプリでは localStorage や sessionStorage、初期化スクリプト、ユーザー文脈の復元なども絡んできます。公式のセキュリティ文書でも、Blazor は既存の ASP.NET Core 認証メカニズムを利用すると明記されています。 (Microsoft Learn)

この構造のせいで、ログイン状態と接続確立の順序がかなり気持ち悪い のです。
認証は済んでいるのか。UI はどこまで出していいのか。SignalR 接続はいつ張るのか。ローカル側の状態はいつ読むのか。
このへんが綺麗に分離されず、工程上はどうしても「まとめて面倒を見る」形になりがちです。

そして公网公開では、この問題がさらに露骨になります。
匿名ユーザーでも circuit を作れます。切断後も一定時間サーバーが保持します。つまり、匿名アクセスは単なる軽い GET リクエストではなく、サーバー資源を伴う接続単位のコスト になります。 (Microsoft Learn)

だから、私の結論ははっきりしています。
Blazor Server をインターネットに公開するなら、ログイン画面はアプリ本体から切り離したほうがいい です。
認証前の匿名アクセスでそのままアプリ本体の circuit を生やす構成は、あまりにも無防備です。

もちろん、どんなシステムにも DoS や濫用の問題はあります。ですが Blazor Server は、その攻撃面が API だけでなく UI 実行系そのものにも広がっている。これがかなり重い。

失敗の見え方が貧弱すぎる

Blazor Server は、失敗の表現が非常に弱いです。

ネットワーク断、サーバー例外、circuit 終了、サーバー再起動、負荷分散環境での再接続失敗。これらは本質的にはまったく別の問題です。ですが、ユーザーが受け取る体験としては、わりと簡単に同じような「切れた」「リロードして」といった形に潰れてしまいます。公式ドキュメントでも、未処理例外で circuit が終了した場合、ユーザーはページの再読み込みでしか継続できないと説明されています。 (Microsoft Learn)

これは単にメッセージがダサい、という話ではありません。
問題の責務や原因が違うのに、表面上の失敗表現が似てしまうのです。

ユーザーから見ると、
「自分の回線が悪いのか」
「システムが落ちたのか」
「さっき押した操作は成功したのか失敗したのか」
が見えにくい。

開発者から見ると、
「UI のバグなのか」
「接続なのか」
「認証なのか」
「再接続に失敗しただけなのか」
が見えにくい。

設計として、失敗の意味がここまで潰れやすいのはかなりつらいです。

公式テンプレートは現実のデプロイに対して強くない

Blazor Server はテンプレートから起こすと一見快適です。ですが、その快適さはデフォルト前提の上に成り立っているだけです。

公式ドキュメントでは、アプリがルートパス / 以外に配置される場合、つまりサブパス配下、IIS のサブアプリ、リバースプロキシでプレフィックスが付く構成などでは、app base path を明示的に設定しなければいけない と説明しています。 (Microsoft Learn)

これ自体は技術的に不思議な話ではありません。問題は、こういう構成が実務では珍しくも何ともないことです。
サブパス配備、ゲートウェイ配下、環境ごとのパス差分、静的リソースのプレフィックス。全部よくある話です。

にもかかわらず、Blazor はそこから少し外れただけで途端に繊細になります。
「テンプレートは動くけど、現場に持っていくと面倒が増える」
この感覚はかなり強いです。

コンポーネント化は、思ったほど得をしない

Blazor はコンポーネントベースを大きく打ち出しています。ですが、実務感覚でいうと、ここもかなり微妙です。

シンプルな UI は、そもそも普通の HTML と CSS で十分です。
わざわざ Razor コンポーネントに切り出したところで、劇的に得するわけではありません。むしろ少し書き方が重くなるだけ、という場面が多い。

逆に複雑な UI、たとえばドラッグ&ドロップ、リッチテキスト、重い表、仮想スクロール、ブラウザの低レイヤー API を使うようなものになると、結局 JavaScript interop に寄っていきます。Blazor の公式文書でも JS 相互運用は基本機能として扱われていますし、Server 側では SignalR の circuit が失われると JSDisconnectedException が関わることも明示されています。 (Microsoft Learn)

つまり現実にはこうなりがちです。

  • 簡単なものは Blazor でなくてもよい
  • 難しいものは結局 JS が必要
  • その間に Razor と C# のラッパー層が増える

これを「一貫したコンポーネントモデル」と呼ぶのは、かなり苦しいと思っています。
実際には、複雑な UI ほど「Razor は殻、実体は JS」という構成になりやすいです。

CSS isolation も、理想ほど万能ではない

CSS isolation の思想自体は理解できます。公式にも、コンポーネント単位に CSS のスコープを閉じることで、グローバルスタイル依存やスタイル衝突を減らせると書かれています。 (Microsoft Learn)

ただ、現実の商用アプリは自前の CSS だけでは終わりません。
第三者コンポーネント、既存のデザインシステム、社内共通 CSS、古いスタイル資産、局所的な上書き。そういうものが必ず混ざります。

すると CSS isolation は、「汚染を防ぐ便利な仕組み」であると同時に、「外から調整しにくい壁」にもなります。
特に第三者ライブラリの見た目を崩さずに少しだけ変えたい、みたいな実務でよくある要求に対して、素直に気持ちよく効いてくれる場面は案外少ないです。

つまり CSS isolation は悪ではないけれど、複雑な現場での総コストまで含めると、必ずしも得ばかりではない ということです。

資源モデルが重い。そこを無視してはいけない

Blazor Server のもう一つの本質は、ユーザーごとの状態をサーバー側が抱えることです。公式ドキュメントは circuit ごとのメモリ管理、切断プール、再接続猶予についてかなりはっきり書いています。ブラウザのタブが増えれば circuit も増えますし、切断後もしばらく保持されます。 (Microsoft Learn)

これはつまり、単純な HTTP ベースの Web よりも、ユーザー数に対してサーバー資源の食い方が重くなりやすいということです。
しかも、そのコストを払って得ているのは「本来ブラウザが持てるはずの UI 状態を、サーバーが代わりに持つ」という構造です。

小規模な内製システムなら許容できるかもしれません。
でも、公網、同時接続、水平スケール、ロードバランサー越しの再接続、長期運用まで考えたとき、このモデルはかなり不利です。

私が本当に嫌なのは、「境界を消したのに、責任を引き受けていない」こと

Blazor Server が好きだという人の気持ちはわかります。
「C# だけでフロントもバックも行けるなら最高じゃないか」という期待は、とても自然です。

でも、前後分離の境界は、単に文化や流行で存在しているわけではありません。
ブラウザ、レンダリング、接続、認証、サーバー処理、それぞれが別の問題領域だから、境界が必要だったのです。

Blazor Server はその境界を曖昧にします。
しかし、曖昧にしたあとに発生する責務までうまく整理してくれているかというと、私はそう思いません。

  • UI のミスが接続断になる
  • 接続断が状態喪失になる
  • 認証と初期化と接続の順序が絡む
  • 複雑な UI は結局 JS に逃げる
  • デプロイ条件が現実的になるほど繊細さが出る

要するに、
学習コストを減らしたように見せて、その裏で別の運用コストと設計コストを増やしている のです。

Blazor は命名の時点で境界を曖昧にした

これはアーキテクチャの本質的欠陥とは少し違いますが、私は Blazor の命名もかなり良くなかったと思っています。

Blazor という名前は Razor に近く、しかもコンポーネントの拡張子は .razor です。一方で、従来の Razor Pages や MVC View では .cshtml が使われます。両者には技術的な連続性があり、構文にも似ている部分があります。だからこそ、一見すると「Razor の延長線上にあるもの」に見えやすい。

ですが、実務で開発者が向き合うものとして見ると、これはかなり別物です。cshtml は基本的にサーバー側で HTML を生成するビューですが、.razor はコンポーネント、イベント、状態管理、再レンダリングを持ち、Blazor Server ではさらに接続や circuit の問題まで背負います。見た目の近さのわりに、実際のプログラミングモデルはかなり違います。

このズレは、学習だけでなく情報探索の段階でもノイズになりやすかったと思います。特に AI がまだ一般化していなかった頃は、Blazor の情報を探しているつもりでも、Razor Pages や .cshtml の情報へ引っ張られやすく、欲しい答えに素直に辿り着きにくい場面がありました。

もちろん、これは Blazor Server の本質的欠陥そのものではありません。ですが、名前・用語・拡張子の設計が境界認識を曖昧にし、結果として学習コストと検索コストを上げていたのは確かだと私は感じています。Blazor はアーキテクチャだけでなく、命名の段階でも「わかりやすそうに見えて、実際には誤解を招きやすい」技術だったと思います。

結論

私は Blazor Server が「まったく使えない」と言いたいわけではありません。
社内向け、小規模、ユーザー数も限られる、チームも小さい、インターネットに直接さらさない、そこまでフロントエンドが複雑でない。そういう条件なら、成立するケースはあります。

ただ、長期保守する商用アプリの主力フロントエンドとして見ると、私は強く懐疑的です。

Blazor Server は、前後分離のつらさを消したのではなく、
接続・状態・例外・認証・デプロイに押し込めただけです。

そしてその代償は、プロジェクトが大きくなればなるほど、
チーム開発になればなるほど、
公網運用に近づけば近づくほど、
どんどん重くなっていきます。

だから私は、Blazor Server の問題を「まだ若いフレームワークだから」で片付ける気にはなれません。
これは成熟度の問題だけではなく、設計の方向そのものに無理がある と考えています。


ZYC.Framework について

ZYC.Framework は、.NET 10 と WPF をベースにした、高性能・モジュール型・拡張可能なデスクトップ自動化開発フレームワークです。モジュールアーキテクチャを中核に、マルチワークスペース/マルチタブ UI、WebView2、Blazor、.NET Aspire との連携を備えており、モダンなデスクトップアプリ、社内ツール、複雑な自動化システムの構築に適しています。

ネイティブな操作性を保ちながら Web 技術も活用し、明確なモジュール境界で継続的に拡張できる基盤を探しているなら、ZYC.Framework は有力な選択肢になります。

27
17
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?