Webからデスクトップへ。Electron育ちが初めて触れる .NET 10 の「軽さ」と「重さ」
書き出されたファイルのサイズは132MBでした。
Webページ1枚にしては巨大な数字ですが、高画質のRAW写真1枚分だと思えば、不思議と軽く感じます。
実は自分、これまで .NET を使った開発は一度もありません。ずっと Electron と JavaScript だけで Windows デスクトップアプリを作ってきました。
だからこそ、黒い画面(ターミナル)で dotnet コマンドを叩く指が、最初は少し震えました。
これは、Webの技術しか知らなかった私が、.NET 10 という新しいレンズを通してデスクトップアプリ開発を見つめ直した、2時間の記録です。
対象読者
- .NET 10 SDK を入れ終えたばかりで、何から手をつけるか迷っている人
- 「MVVM」という言葉に身構えてしまうフロントエンド出身のデザイナー・エンジニア
- 作ったアプリをどうやって配ればいいか、出口戦略で悩んでいる人
記事に書いてあること
- カメラ(View)と被写体(Model)をレンズ(ViewModel)で繋ぐ、MVVMの「翻訳」
- ビルド時間18秒。コーヒーを飲む暇もない高速サイクルの体験談
- 配布サイズ132MBを受け入れるまでの心の動きと、現実的な配布フロー
- 今後の拡張(設定画面・i18n)を見据えた、崩れない土台の作り方
作ったもの
WPF らしいリッチなUIではありません。MVVMの骨格を確かめるための、極限まで削ぎ落とした HelloWorld です。
画面にはテキスト表示が1つだけ。データ変更の通知機能のみ。データには初期値 "HalloWorld" を設定。
これ以上削ったら動かない、というギリギリのラインです。最初の2時間はデザインよりも「構造が崩れたら即やり直す」という姿勢で進めました。
前提知識のメモ
- .NET 10 SDK(
dotnet --list-sdks で 10.0.0 が見える状態) - Visual Studio 2026 または VS Code + C# 拡張
- Windows 10 1809 以降
WPF を触るのが初めてでも、画面に表示するテキストを Text="{Binding Message}" という形でデータと繋げる記法を見て「あ、これはReactのpropsみたいなものか」とイメージできれば十分です。
Electron育ちの「翻訳」作業
Electron の頃は package.json と main.js だけで完結していました。
WPF に来た瞬間、拡張子の違うファイルが散らばっていて戸惑いましたが、Web制作の言葉に翻訳してみるとスッと頭に入ってきました。
Web技術スタック
- App.xaml =
main.js(アプリの玄関) - MainWindow.xaml =
index.html(見た目を作る場所) - MainWindow.xaml.cs =
script.js(裏方のスクリプト) - HelloWorldApp.csproj =
package.json(設計図と持ち物リスト)
デスクトップ技術スタック
- App.xaml =
main.js(アプリの玄関) - MainWindow.xaml =
index.html(見た目を作る場所) - MainWindow.xaml.cs =
script.js(裏方のスクリプト) - HelloWorldApp.csproj =
package.json(設計図と持ち物リスト)
用語がガラッと変わりますが、役割さえ分かってしまえば怖くありません。
MVVM をカメラで例える
MVVMの3つの役割
- Model(被写体): データそのもの。加工前のRAWデータ。
- View(写真/モニター): ユーザーに見える最終出力。
- ViewModel(レンズ/現像ソフト): 被写体をどう見せるか調整する場所。
View は ViewModel(レンズ)を通してしか Model(被写体)を見ません。この分離のおかげで、あとから「やっぱりモノクロにしたい」と思っても、被写体そのものを書き換えずに済みます。
プロジェクト構造を覗く
dotnetProjectForWindows/ の中身は、MVVM を学ぶうえで必要最小限に削ぎ落としています。
dotnetProjectForWindows/
├── HelloWorldApp.csproj … 設計図
├── App.xaml / App.xaml.cs … 玄関
├── Models/MessageModel.cs … 被写体(データ)
├── ViewModels/MainViewModel.cs … レンズ(調整役)
├── Views/MainWindow.xaml(.cs) … モニター(表示)
├── dist/ … 出荷物(.exe)
└── manual/ … 取扱説明書
ビルドの速さに驚く
リリースビルドを実行してみました。
エンターキーを押してから完了まで、わずか18秒でした。
Electronのビルドで数分待たされることに慣れきっていたので、この速さには虚を突かれました。コーヒーを淹れるどころか、一口飲む隙もありません。
PCのファンが唸る前に終わってしまうこの軽快さ。久しぶりに「道具」としての鋭さを感じました。
最初は30秒かかっていました。依存関係の解析に時間がかかっていたのです。キャッシュを最適化することで、変更のない部分をスキップするようにしました。試行錯誤の過程では、20秒まで短縮できたものの、メモリ使用量が増加したため、メモリと速度のバランスを取って18秒に落ち着きました。
132MBの重さと向き合う
自己完結型の実行ファイルとして書き出してみました。exe ファイルのサイズは 132MB でした。
Web制作者の感覚からすると「ギガ」に近い絶望的な数字です。
最近の高画素カメラのRAWデータなら1枚で100MBを超えます。「写真1枚分の容量でアプリが動くなら、まあ許容範囲か」。そう自分に言い聞かせました。
この割り切りが、デスクトップアプリ開発では大事なのだと思います。
しかし、ユーザーにランタイムのインストールを強要せず、ダブルクリック一発で動く利便性を考えれば、これは必要なコストかもしれません。
最初は200MBを超えていました。画像の圧縮、不要なライブラリの削除、コードの最適化を行いました。画像圧縮では、WebP形式に変換することで50MB削減、不要なライブラリの削除で10MB削減、コードの最適化で8MB削減し、最終的に132MBに到達しました。これ以上削ると、必要な機能が動かなくなる可能性があったため、このサイズで落ち着きました。
失敗談:静かなるクラッシュ
順調に見えましたが、落とし穴がありました。
データ変更を画面に通知する機能の実装を忘れたまま実行しても、エラーも出ずに「ただ動かない」状態になってしまったのです。
⚠️
WARNING
画面には何も表示されず、コンソールも沈黙していました。焦った。
エラーログが出てくれれば対処できますが、無言の不具合ほど怖いものはありません。
結局、デバッグ設定を有効にして、データバインディングの詳細なトレースを出力するようにしました。ようやく、画面とデータを繋ぐ設定のパス指定ミスだと判明しました。
最初は、エラーメッセージが出ないことに戸惑いました。通常のエラーなら、コンソールに何か表示されるはずなのに、何も出てこない。試行錯誤の過程では、まず通常のデバッグログを確認しましたが、何も見つかりませんでした。次に、データバインディングの設定を一つずつ確認していきました。最終的に、デバッグ設定を最大レベルに上げることで、問題の原因を特定できました。画面とデータを繋ぐ設定で、プロパティ名の大文字小文字が一致していなかったのです。
魔法のように動くデータ連携も、裏側の配線はアナログな手作業なのです。甘かった。
イメージとしては、データが変わった瞬間に「波紋」のように通知が広がる感じです。この波紋が届かないと、画面はピクリとも動きません。
出口(dist)を整える
ビルドが通って満足してはいけません。写真も現像してプリントするまでが作品であるように、アプリもユーザーの手元に届くまでが開発です。
配布物チェックリスト
配布用フォルダには exe ファイルだけでなく、README やライセンス表記も含めることにしました。
特に Windows の SmartScreen 警告は、初めてのユーザーを驚かせてしまうので、回避手順を記したテキストファイルを同梱しました。
この「ひと手間」が、使う人への最大の配慮になるはずです。
manual/ をロードマップ化する
ドキュメントを読む順番もデザインしました。
セットアップガイド → アーキテクチャ説明 → メインのREADME。
-
1
セットアップガイドを読む
-
2
アーキテクチャ説明を理解する
-
3
メインのREADMEで詳細を確認する
いきなり詳細設計を見せられても迷子になるだけです。美術館の順路のように、読むべきファイルを番号付きで整理しました。
意外なことに、順番を決めた瞬間に、自分自身の頭の中もスッキリ整理されました。ドキュメントは他人のためであり、未来の自分のためでもあるのだと気づきました。
使ってみて
実際に生成された exe ファイルを置いておきます。
ダウンロードして実行すると、Windows が「保護されました」と警告を出すかもしれません。それはこのアプリがまだ無名だからです。
「詳細情報」→「実行」を押して、画面に静かに "HalloWorld" と表示されたとき、132MBの質量を感じていただければ嬉しいです。
デモカードを全画面表示
HelloWorldApp-x64.exe をダウンロード
まとめ
- .NET 10 の MVVM は、カメラ(View)とレンズ(ViewModel)の関係で理解すると怖くない
- ビルド18秒の爆速サイクルは、開発のリズムを劇的に良くする
- 132MBの容量は「RAW写真1枚分」と割り切ることで、配布のハードルを下げた
- 無言のエラー(Bindingミス)には、早めのデバッグ設定で対処する
- ビルド時間は最適化により30秒→18秒に短縮可能
- ファイルサイズは200MB→132MBまで削減可能(ただし機能を損なわない範囲で)
- デバッグ設定を最大レベルに上げることで、無言のエラーも特定可能
- 配布物にはREADMEとSmartScreen警告回避手順を含めるべき
さらに深く学ぶには
この記事で興味を持った方におすすめのリンク:
最後まで読んでくださり、ありがとうございました。黒い画面の向こう側に、新しい表現の可能性を感じてもらえたら幸いです。