如何将 Electron 应用程序发布到 Mac App Store
在本文中,我将说明如何将MacOS基于Electron的应用程序发布到Mac App Store ,并提示所有需要注意的点。
截止本文发布日期(2020.2.12),该文章有效。由于苹果公司的政策,目前只能发布基于Electron 5.0.13和6.1.7的应用程序。而且未来可能很快会有所调整。
重要定义
- Sandboxing (沙盒化) - 在特殊环境中隔离应用程序,几乎不能访问任何内容。查看苹果对此的解释。
- Entitlements(权限)——为沙箱应用程序请求权限。完整的安全权利清单可以在这里找到。
- Provisioning profile (配置文件)——它连接您的开发人员帐户(证书)、绑定依赖和可以安装应用程序的设备。
发版
假设您已经有 Electron 应用程序,并且正在使用 Electron builder 来构建您的应用程序。
所有列出的代码都可以在 Electron Nuxt 这个代码库中找到。
1. 创建配置文件
访问 developers.apple.com 的证书、标识符和配置文件部分。在标识符部分,为macOS平台添加新的App ID。

接下来转到配置文件,为Mac应用程序商店创建新的配置文件。
下载已创建的配置文件并将其放置到源文件夹内 build
文件夹。将其命名为embedded. supplonprofile
2.创建 App
转到App Store Connect,然后选择我的应用程序。添加新的macOS应用。

选择在上一步中注册的Bundle ID。
提供所有必需的信息。
3. 配置文件修改
在build
文件夹中创建 entitlements.mas
。至少具备以下权限:
<!--?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>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>DEVELOPERID.full.package.name(此处替换)</string>
</array>
</dict>
</plist>
要查找 DEVELOPERID,请访问Membership 标签页。您可以在团队名称下找到作为团队ID,就是DEVELOPERID。full.package.Name是您注册的应用程序标识符。
在“build”文件夹中创建 entitlements.mas.inherit
文件。写入如下代码
<!--?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>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.inherit</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
</dict>
</plist>
创建 entitlements.mas.loginhelper.plist
。写入如下代码
<!--?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>
<key>com.apple.security.app-sandbox</key>
<true/>
</dict>
</plist>
4. 修改打包文件
转到package.json文件并添加到build部分(或修改 electron-builder.json)。
"mac": {
"target": [
"mas"
]
},
"mas": {
"hardenedRuntime": false,
"provisioningProfile": "build/embedded.provisionprofile",
"entitlements": "build/entitlements.mas.plist",
"entitlementsInherit": "build/entitlements.mas.inherit.plist",
"gatekeeperAssess": false,
"asarUnpack": []
}
5. 打包构建
至此,Electron-builder配置完成,您可以运行electron-builder命令来打包您的应用程序。如果您有多个开发人员证书,则需要提供适当的证书名称,例如
CSC_NAME=\"CERTIFICATE NAME (***********)\" electron-builder
注意:10.15 版本以上需要进行公证配置
6. 上传 App
生成过程之后,构建文件可以在dist/mas/*.pkg 找到,并可以通过 Transporter App 上传至Mac App Store。
在某些情况下,应用程序会被拒绝,因为打包期间不是所有的二进制文件都 Electron builder 签署。这时我们要用下面的方法来解决这个问题:
7. 创建修改脚本(可选)
创建 build/resignAndPackage.sh
脚本
#!/bin/bash
# Name of your app.
APP="APPLICATION NAME"
# The path of your app to sign.
APP_PATH="dist/mas/$APP_PATH.app"
# The path to the location you want to put the signed package.
RESULT_PATH="dist/mas/$APP-mac_store.pkg"
# The name of certificates you requested.
APP_KEY="3rd Party Mac Developer Application: CERTIFICATE NAME (***********)"
INSTALLER_KEY="3rd Party Mac Developer Installer: CERTIFICATE NAME (***********)"
# The path of your plist files.
PARENT_PLIST="build/entitlements.mas.plist"
CHILD_PLIST="build/entitlements.mas.inherit.plist"
LOGINHELPER_PLIST="build/entitlements.mas.loginhelper.plist"
FRAMEWORKS_PATH="$APP_PATH/Contents/Frameworks"
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Electron Framework"
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libffmpeg.dylib"
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Libraries/libffmpeg.dylib"
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework"
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper.app/Contents/MacOS/$APP Helper"
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper.app/"
codesign -s "$APP_KEY" -f --entitlements "$LOGINHELPER_PLIST" "$APP_PATH/Contents/Library/LoginItems/$APP Login Helper.app/Contents/MacOS/$APP Login Helper"
codesign -s "$APP_KEY" -f --entitlements "$LOGINHELPER_PLIST" "$APP_PATH/Contents/Library/LoginItems/$APP Login Helper.app/"
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$APP_PATH/Contents/MacOS/$APP"
codesign -s "$APP_KEY" -f --entitlements "$PARENT_PLIST" "$APP_PATH"
productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RESULT_PATH"
在 build/resignAndPackage.sh
中,将应用程序名称更改为您的应用程序名称(应该是package.json中的productName)。在两个地方将证书名称(**)替换为您的证书名称。
在 build/resignAndPackage.sh
中列出的二进制文件对 Electron 5.0.13 有效。如果您是其他版本,需要进行升级,否则需要查找额外的二进制文件。查找运行的二进制文件(源文件)
find -H YourAppBundle -print0 | xargs -0 file | grep "Mach-O .*executable"
可以通过在 package.json 中的 asarUnpack 字段中列出 node_modules 的二进制文件来解压缩它们。
8. 重新打包
CSC_NAME=\"CERTIFICATE NAME (***********)\" electron-builder && bash build/resignAndPackage.sh
并通过 Transporter App 将dist/mas/$APP-mac_store.pkg 上传到Mac App Store。
就这样。可能您会与Apple团队进行一次“有趣的旅行”,向他们解释为什么您构建了您的应用程序,为什么需要权利文件中列出的权限,但这是另外一回事了:-)