Electron Mac 向けビルド:Universal(Intel/Apple Silicon)を作る手順
Electron アプリを Mac 向けにリリースする際、Intel チップと Apple Silicon(M1/M2/M3)の両方に対応させたいと思ったことはありませんか。Universal Binary を使えば、1 つのアプリで両アーキテクチャをサポートできます。
この記事では、Electron アプリを Mac の Intel と Apple Silicon の両方で動作する Universal Binary としてビルドする手順を、初心者の方にもわかりやすく解説します。実際のコード例を交えながら、electron-builder を使った具体的な設定方法をご紹介しますね。
背景
Apple の Mac アーキテクチャ変遷
Apple は 2020 年から Mac のプロセッサを Intel から独自開発の Apple Silicon(M シリーズチップ)へ移行し始めました。この大きな変化により、Mac アプリの開発者は新しい課題に直面することになります。
Apple Silicon は ARM64 アーキテクチャを採用しており、従来の Intel Mac が使用していた x86_64 アーキテクチャとは根本的に異なるのです。
以下の図は、Apple の Mac プロセッサの変遷と、それぞれのアーキテクチャを示しています。
mermaidflowchart TB
subgraph old["2020年以前"]
intel["Intel Mac<br/>アーキテクチャ: x86_64"]
end
subgraph new["2020年以降"]
m1["Apple Silicon Mac<br/>アーキテクチャ: arm64"]
end
subgraph transition["移行期間"]
both["Intel と Apple Silicon<br/>が共存"]
end
old --> transition
transition --> new
style intel fill:#e3f2fd
style m1 fill:#f3e5f5
style both fill:#fff3e0
この図からわかるように、現在は移行期間であり、Intel Mac と Apple Silicon Mac の両方が市場に存在しています。
Rosetta 2 の役割
Apple Silicon Mac では、Intel 向けにビルドされたアプリも「Rosetta 2」という変換レイヤーを通じて実行できます。しかし、Rosetta 2 を経由すると、ネイティブ実行と比べてパフォーマンスが低下してしまうのです。
ユーザーに最高のパフォーマンスを提供するには、各アーキテクチャに最適化されたネイティブコードを提供することが重要になります。
Universal Binary とは
Universal Binary は、複数のアーキテクチャ(Intel の x86_64 と Apple Silicon の arm64)のバイナリコードを 1 つのファイルに含めた実行ファイル形式です。
この形式を採用すると、ユーザーは自分の Mac のアーキテクチャを気にすることなく、同じアプリをダウンロードして使えるようになります。システムが自動的に適切なバイナリを選択して実行してくれるのですね。
課題
別々のビルドを配布する問題点
Electron アプリを Intel 用と Apple Silicon 用に別々にビルドして配布する場合、以下のような課題が発生します。
ユーザー体験の低下
ユーザーは自分の Mac がどちらのアーキテクチャなのかを確認し、正しいバージョンを選択してダウンロードしなければなりません。この手間は、特に技術に詳しくないユーザーにとって大きな障壁となってしまいます。
配布管理の複雑化
開発者側も、2 つの異なるビルドを管理し、それぞれのダウンロードリンクを提供する必要があります。バージョンアップの際も、両方のビルドを更新しなければなりません。
サポートコストの増加
どちらのバージョンをダウンロードすべきか、という問い合わせが増える可能性があります。また、間違ったバージョンをダウンロードしたユーザーへの対応も必要になるでしょう。
以下の図は、別々にビルドを配布する場合の問題点を示しています。
mermaidflowchart TD
dev["開発者"] -->|ビルド| intel_build["Intel 向けビルド<br/>x86_64"]
dev -->|ビルド| arm_build["Apple Silicon 向けビルド<br/>arm64"]
intel_build -->|配布| server1["配布サーバー<br/>Intel版"]
arm_build -->|配布| server2["配布サーバー<br/>ARM版"]
user["ユーザー"] -->|判断が必要| choice{"自分の Mac は<br/>どちら?"}
choice -->|Intel| server1
choice -->|Apple Silicon| server2
choice -->|わからない| confusion["混乱・エラー"]
style confusion fill:#ffebee
style choice fill:#fff3e0
図からわかるように、ユーザーが自分で判断しなければならない点が、大きな課題となっています。
ネイティブモジュールの対応
Electron アプリで Node.js のネイティブモジュール(C/C++ で書かれたアドオン)を使用している場合、さらに複雑になります。
これらのモジュールも各アーキテクチャ向けにコンパイルする必要があり、Universal Binary の作成時には両方のバージョンを含める必要があるのです。
解決策
Universal Binary で一本化
Universal Binary を作成することで、これらの課題を一気に解決できます。1 つのアプリファイルに両アーキテクチャのコードを含めることで、ユーザーは何も考えずにアプリをダウンロードして使えるようになるのです。
以下の図は、Universal Binary のビルドと配布のフローを示しています。
mermaidflowchart LR
dev["開発者"] -->|ビルド| builder["electron-builder<br/>Universal設定"]
builder -->|コンパイル| intel_code["x86_64 バイナリ"]
builder -->|コンパイル| arm_code["arm64 バイナリ"]
intel_code -->|結合| universal["Universal Binary<br/>両方を含む"]
arm_code -->|結合| universal
universal -->|配布| server["配布サーバー<br/>1つのファイル"]
server -->|ダウンロード| user["ユーザー"]
user -->|実行| auto["システムが自動選択"]
style universal fill:#c8e6c9
style auto fill:#c8e6c9
この図からわかるように、ユーザーは何も判断する必要がなく、システムが自動的に適切なバイナリを選択して実行してくれます。
electron-builder の活用
Electron アプリのビルドツールとして広く使われている electron-builder は、Universal Binary の作成をサポートしています。設定ファイルに適切なオプションを追加するだけで、簡単に Universal Binary をビルドできるのです。
electron-builder の導入
まず、プロジェクトに electron-builder をインストールしましょう。
bash# electron-builder をプロジェクトに追加
yarn add --dev electron-builder
このコマンドで、electron-builder が開発用の依存関係として追加されます。
基本的な設定方針
Universal Binary を作成するための設定は、主に以下の 3 つのポイントに注目します。
- ターゲットアーキテクチャの指定: x86_64 と arm64 の両方を指定
- ビルド環境の準備: Apple Silicon Mac でのビルドを推奨
- ネイティブモジュールの処理: 両アーキテクチャ向けにリビルド
これらの設定を順番に見ていきましょう。
具体例
package.json の設定
まず、package.json にビルド設定を追加します。ここで Universal Binary を作成するための基本設定を行うのです。
以下は、package.json の基本構造です。
json{
"name": "my-electron-app",
"version": "1.0.0",
"description": "Electron アプリのサンプル",
"main": "main.js",
"scripts": {
"start": "electron .",
"build": "electron-builder"
}
}
この基本構造に、electron-builder の設定を追加していきます。
build セクションの追加
package.json に build セクションを追加し、Mac 向けの設定を記述しましょう。
json{
"build": {
"appId": "com.example.myapp",
"productName": "MyElectronApp",
"mac": {
"target": {
"target": "default",
"arch": ["x64", "arm64"]
},
"category": "public.app-category.utilities"
}
}
}
arch 配列に x64(Intel 用)と arm64(Apple Silicon 用)の両方を指定することで、Universal Binary が作成されます。
DMG パッケージの設定
Mac アプリの配布形式として一般的な DMG ファイルの設定も追加しましょう。
json{
"build": {
"mac": {
"target": {
"target": "dmg",
"arch": ["x64", "arm64"]
}
},
"dmg": {
"contents": [
{
"x": 130,
"y": 220
},
{
"x": 410,
"y": 220,
"type": "link",
"path": "/Applications"
}
],
"window": {
"width": 540,
"height": 380
}
}
}
}
この設定により、ユーザーフレンドリーな DMG インストーラーが作成されます。
electron-builder.yml での設定
package.json が大きくなるのを避けたい場合は、専用の設定ファイル electron-builder.yml を作成する方法もあります。
プロジェクトのルートディレクトリに electron-builder.yml ファイルを作成しましょう。
yaml# アプリケーション ID とプロダクト名の設定
appId: com.example.myapp
productName: MyElectronApp
# ビルドに含めるファイル・除外するファイル
files:
- '**/*'
- '!**/*.ts'
- '!*.md'
- '!.gitignore'
# ビルドから除外するディレクトリ
directories:
buildResources: build
output: dist
この基本設定では、TypeScript ファイルやマークダウンファイルなど、配布に不要なファイルを除外しています。
Mac 向けの詳細設定
次に、Mac 専用の設定を追加します。
yaml# Mac 向けの設定
mac:
# ターゲットの指定(DMG 形式で Universal Binary を作成)
target:
- target: dmg
arch:
- x64 # Intel Mac 用
- arm64 # Apple Silicon Mac 用
# アプリケーションカテゴリ
category: public.app-category.utilities
# アイコンの設定
icon: build/icon.icns
# 署名の設定(必要に応じて)
identity: null
arch に x64 と arm64 の両方を指定することで、Universal Binary が作成されます。
DMG の外観設定
DMG ファイルを開いたときの見た目を設定します。
yaml# DMG の設定
dmg:
# DMG ウィンドウのサイズ
window:
width: 540
height: 380
# アイコンの配置
contents:
- x: 130
y: 220
- x: 410
y: 220
type: link
path: /Applications
# 背景画像(オプション)
background: build/background.png
この設定により、ユーザーがアプリを Applications フォルダにドラッグ&ドロップしやすいレイアウトが作成されます。
ネイティブモジュールの対応
Electron アプリで Node.js のネイティブモジュールを使用している場合、特別な処理が必要になります。
electron-rebuild の使用
ネイティブモジュールを各アーキテクチャ向けに再ビルドするには、electron-rebuild を使用します。
bash# electron-rebuild をインストール
yarn add --dev @electron/rebuild
インストール後、package.json にスクリプトを追加しましょう。
json{
"scripts": {
"rebuild": "electron-rebuild -f -w ネイティブモジュール名",
"postinstall": "electron-rebuild"
}
}
postinstall スクリプトを追加することで、yarn install 実行時に自動的にネイティブモジュールが再ビルドされます。
両アーキテクチャ向けのビルド
Universal Binary を作成する際、electron-builder は自動的に両アーキテクチャ向けにネイティブモジュールをビルドしてくれます。
ただし、Apple Silicon Mac 上でビルドを実行することを強く推奨します。Apple Silicon Mac では Rosetta 2 を使って Intel 向けのコードもビルドできますが、Intel Mac では ARM64 向けのコードをビルドできないからです。
ビルドスクリプトの最適化
ビルドプロセスを効率化するため、package.json に便利なスクリプトを追加しましょう。
json{
"scripts": {
"start": "electron .",
"build:mac": "electron-builder --mac",
"build:mac:universal": "electron-builder --mac --x64 --arm64",
"build:all": "electron-builder -mwl",
"clean": "rm -rf dist"
}
}
各スクリプトの役割を説明します。
| # | スクリプト名 | 説明 |
|---|---|---|
| 1 | start | 開発モードでアプリを起動 |
| 2 | build:mac | Mac 向けビルド(現在のアーキテクチャのみ) |
| 3 | build:mac:universal | Universal Binary を作成 |
| 4 | build:all | Mac・Windows・Linux 向けにビルド |
| 5 | clean | ビルド成果物を削除 |
ビルドの実行
設定が完了したら、実際にビルドを実行してみましょう。
bash# Universal Binary をビルド
yarn build:mac:universal
このコマンドを実行すると、electron-builder が以下の処理を順番に行います。
- 依存関係の確認とインストール
- x64(Intel)向けのバイナリをコンパイル
- arm64(Apple Silicon)向けのバイナリをコンパイル
- 両バイナリを 1 つの Universal Binary に結合
- DMG パッケージを作成
ビルドが完了すると、dist ディレクトリに DMG ファイルが作成されているはずです。
ビルド結果の確認
ビルドが成功したら、作成された Universal Binary が正しく両アーキテクチャに対応しているか確認しましょう。
lipo コマンドでの確認
macOS の lipo コマンドを使うと、バイナリに含まれるアーキテクチャを確認できます。
bash# アプリ内のバイナリを確認
lipo -archs dist/mac-universal/MyElectronApp.app/Contents/MacOS/MyElectronApp
正しく Universal Binary が作成されていれば、以下のように表示されます。
x86_64 arm64
この出力は、バイナリが Intel(x86_64)と Apple Silicon(arm64)の両方に対応していることを示しています。
file コマンドでの詳細確認
file コマンドを使うと、さらに詳細な情報を確認できます。
bash# バイナリの詳細情報を表示
file dist/mac-universal/MyElectronApp.app/Contents/MacOS/MyElectronApp
出力例は以下のようになります。
vbnetMyElectronApp: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64:Mach-O 64-bit executable arm64]
「universal binary with 2 architectures」と表示されていれば、正しく Universal Binary が作成されています。
コード署名と公証の設定
Mac アプリを一般配布する際は、Apple の開発者証明書で署名し、公証(notarization)を受ける必要があります。
署名の設定
electron-builder.yml に署名の設定を追加しましょう。
yamlmac:
# 署名の設定
identity: 'Developer ID Application: Your Name (TEAM_ID)'
# Hardened Runtime の有効化(公証に必要)
hardenedRuntime: true
gatekeeperAssess: false
# エンタイトルメントの設定
entitlements: build/entitlements.mac.plist
entitlementsInherit: build/entitlements.mac.plist
identity には、Apple Developer アカウントの証明書名を指定します。
エンタイトルメントファイルの作成
build/entitlements.mac.plist ファイルを作成し、必要な権限を定義します。
xml<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- JIT コンパイルを許可 -->
<key>com.apple.security.cs.allow-jit</key>
<true/>
<!-- 署名されていないコードの実行を許可 -->
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<!-- Hardened Runtime を有効化 -->
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>
これらの設定は、Electron アプリが正常に動作するために必要な権限です。
公証の自動化
electron-builder は、Apple の公証プロセスも自動化できます。
yamlmac:
# 公証の設定
notarize:
teamId: YOUR_TEAM_ID
afterSign: scripts/notarize.js
環境変数に Apple ID とアプリパスワードを設定しておく必要があります。
bash# 環境変数の設定(.env ファイルなどで管理)
export APPLE_ID="your-apple-id@example.com"
export APPLE_APP_SPECIFIC_PASSWORD="xxxx-xxxx-xxxx-xxxx"
これらの情報は機密情報なので、決してコードリポジトリにコミットしないよう注意してください。
トラブルシューティング
Universal Binary のビルド時によくあるエラーと解決方法をご紹介します。
エラー: Error: Cannot build for arm64 on x64
このエラーは、Intel Mac で arm64 向けのビルドを試みた場合に発生します。
解決方法: Apple Silicon Mac でビルドを実行するか、CI/CD 環境で Apple Silicon ランナーを使用してください。
エラー: native module not compatible
ネイティブモジュールが特定のアーキテクチャに対応していない場合に発生します。
解決方法: 以下のコマンドでモジュールを再ビルドします。
bash# 両アーキテクチャ向けに再ビルド
yarn add @electron/rebuild
yarn electron-rebuild
それでも解決しない場合は、モジュールが Universal Binary に対応しているかドキュメントを確認しましょう。
ビルドサイズが大きくなる問題
Universal Binary は 2 つのアーキテクチャのコードを含むため、ファイルサイズが約 2 倍になります。
対策方法: 以下のような最適化を検討してください。
- 不要な依存関係の削除: package.json の dependencies を見直し
- アセットの最適化: 画像や動画ファイルを圧縮
- asar アーカイブの使用: コードをアーカイブ化してサイズを削減
electron-builder.yml に asar の設定を追加しましょう。
yaml# asar アーカイブの設定
asar: true
asarUnpack:
- '**/*.node' # ネイティブモジュールは展開
この設定により、ネイティブモジュール以外のファイルがアーカイブ化され、サイズが削減されます。
CI/CD での自動ビルド
GitHub Actions を使って、Universal Binary のビルドを自動化することもできます。
GitHub Actions ワークフローの設定
.github/workflows/build.yml ファイルを作成します。
yamlname: Build Universal Binary
# トリガーの設定(タグがプッシュされたとき)
on:
push:
tags:
- 'v*'
jobs:
build-mac:
# macOS ランナーを使用(Apple Silicon 対応)
runs-on: macos-latest
steps:
# リポジトリをチェックアウト
- name: Checkout code
uses: actions/checkout@v3
まず、リポジトリのコードをチェックアウトします。
Node.js のセットアップ
次に、Node.js 環境をセットアップしましょう。
yaml# Node.js のセットアップ
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'yarn'
キャッシュを有効にすることで、2 回目以降のビルドが高速になります。
依存関係のインストールとビルド
依存関係をインストールし、ビルドを実行します。
yaml# 依存関係のインストール
- name: Install dependencies
run: yarn install --frozen-lockfile
# Universal Binary のビルド
- name: Build Universal Binary
run: yarn build:mac:universal
env:
# Apple 署名用の環境変数(GitHub Secrets から取得)
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
機密情報は GitHub Secrets に登録し、環境変数として参照します。
ビルド成果物のアップロード
ビルドした DMG ファイルを GitHub Release にアップロードしましょう。
yaml# Release へのアップロード
- name: Upload to Release
uses: softprops/action-gh-release@v1
with:
files: dist/*.dmg
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
これで、タグをプッシュするだけで自動的に Universal Binary がビルドされ、Release に公開されるようになります。
まとめ
Electron アプリを Mac の Intel と Apple Silicon の両方に対応させる Universal Binary の作成方法をご紹介しました。
electron-builder を使えば、設定ファイルに arch: ["x64", "arm64"] を追加するだけで、簡単に Universal Binary を作成できます。これにより、ユーザーは自分の Mac のアーキテクチャを気にすることなく、同じアプリをダウンロードして最高のパフォーマンスで使用できるようになるのです。
重要なポイントをまとめると、以下のようになります。
- アーキテクチャの指定: package.json または electron-builder.yml で x64 と arm64 を指定
- ビルド環境: Apple Silicon Mac でのビルドを推奨
- ネイティブモジュール: electron-rebuild で両アーキテクチャ向けに再ビルド
- 署名と公証: 一般配布には Apple の開発者証明書と公証が必要
- 確認方法: lipo コマンドで Universal Binary を検証
Universal Binary を採用することで、ユーザー体験が向上し、配布管理も簡素化されます。Mac アプリをリリースする際は、ぜひ Universal Binary での配布を検討してみてください。
Apple Silicon への移行はまだ進行中ですが、Universal Binary を提供することで、すべてのユーザーに最適な体験を届けることができるでしょう。
関連リンク
articleElectron Mac 向けビルド:Universal(Intel/Apple Silicon)を作る手順
articleElectron IPC 方式比較:ipcRenderer vs contextBridge + postMessage の安全性
articleElectron ビルド失敗解決:native module 再ビルドと node-gyp 地獄からの脱出
articleElectron アーキテクチャ超図解:Main/Renderer/Preload の役割とデータフロー
articleElectron 運用:コード署名・公証・アップデート鍵管理のベストプラクティス
articleElectron オフライン帳票・PDF 生成を Headless Chromium で実装
articleWebSocket Close コード早見表:正常終了・プロトコル違反・ポリシー違反の実務対応
articleStorybook 品質ゲート運用:Lighthouse/A11y/ビジュアル差分を PR で自動承認
articleWebRTC で高精細 1080p/4K 画面共有:contentHint「detail」と DPI 最適化
articleSolidJS フォーム設計の最適解:コントロール vs アンコントロールドの棲み分け
articleWebLLM 使い方入門:チャット UI を 100 行で実装するハンズオン
articleShell Script と Ansible/Make/Taskfile の比較:小規模自動化の最適解を検証
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来