首页/文章/electron

Electron-builder 构建MacOS应用小白教程(打包 & 签名 & 公证 & 上架

2024-07-23
338812 分钟
...

macOS 应用构建,看似近在咫尺,实则坑坑致命。

打包

package.json中,dependencies会被打进 Electron 应用的包里,而devDependencies则不会,所以必要的依赖需要放到dependencies中。files中定义自己需要被打进 Electron 包里的文件。以下是一个完整的 mac electron-builder的配置文件。

const base = {
  appId: 'com.xxxx.xxxx', 
  productName: 'Electron 打包模版', 
  icon: './media/images/icon.ico',
  files: [  
    'main.js',
    'bundles',
    'updater/win/index.html',
    'updater/build/bootstrap.js',
    'updater/mac/Updater.js',
    'updater/mac/index.html'
  ],
  publish: { 
    provider: 'generic', 
    url: '' 
  },
  mac: {
    target: [  
      "dmg",
      "zip",
      "pkg",
      "mas"
    ],
    icon: 'media/images/icon.icns',
    hardenedRuntime: true,
    entitlements: 'electron-builder/entitlements.plist',  
    entitlementsInherit: 'electron-builder/entitlements.plist',
    provisioningProfile: 'electron-builder/comalibabaslobs.provisionprofile'
  },
  pkg: {
    isRelocatable: false,
    overwriteAction: "upgrade",
  },
  mas: {
    icon: 'media/images/icon.icns',
    hardenedRuntime: true,
    entitlements: 'electron-builder/entitlements.mas.plist',
    entitlementsInherit: 'electron-builder/entitlements.mas.plist',
  },
  dmg: {
    background: 'media/images/dmg-bg.png',
    icon: 'media/images/icon.icns',
    iconSize: 100,
    sign: false,
    contents: [ 
      {
        x: 112,
        y: 165,
      },
      {
        type: 'link',
        path: '/Applications',
        x: 396,
        y: 165,
      },
    ],
  },
  extraMetadata: {  
    env: 'production',
  }
};

module.exports = base;

签名

MacOS 10.15 之前,应用如果没有进行签名,首次打开的时候就会出现“恶意软件”提示。

1. 加入开发者

加入 Apple Developer Program(需要缴纳年费)

如果是管理员,会看到可以申请 Developer ID Application,如果不是管理员就会像我这种,看到是灰色的。Electron 打包是需要用这个身份生成证书的。

2. 生成签名证书

如果有管理员权限,点击生成新的证书。

Choose File 里面的文件从哪里来?打开 mac 的钥匙串访问 -> 证书助理 -> 从证书颁发机构请求证书,这里生成了 CertificateSigningRequest.certSigningRequest 的文件,这个文件可以被多次用来生成 mac 证书。

填写必要信息,用户邮箱填写你的 app开发者邮箱,常用名称随便取一个,然后选择保存到本地磁盘。

3. 安装签名证书

上次文件后就生成证书了,下载证书安装。如果出现了次证书不受信任的情况,在列表中双击证书,将使用此证书时更改为始终信任。

如果安装的证书不对,会出现 Command failed: codesign ...

4. 证书导出 p12 给其它人使用

在 mac 的钥匙串访问中,找到证书,然后 右键 -> 导出证书,一般导出 .p12 形式,然后输入证书安装的密码。其它人拿着你的证书,告诉他安装密码即可安装。

5. 不要 Developer ID Application 签名证书,不影响 Electron 应用打包

在打包过程中,找不到 Developer ID Application 签名证书的情况下,会跳过处理。但是应用不签名和公证会影响electron-autoupdater 自动更新能下载无法打开,用户首次打开会提示恶意软件,应用无法上架到appStore。

公证

MacOS 10.14.5 之后,应用如果没有进行公证(将安装包上传到 Apple 审查),首次打开的时候就会出现更严重的“恶意软件”提示。没有进行过公证也无法上传到 Apple Store 中提供给其他人下载。

代码公证

const { notarize } = require('electron-notarize');
notarize({
  appPath: '',          
  appBundleId: '',      
  appleId: '',          
  appleIdPassword: '',  
  ascProvider: ''       
})
  1. appPath打包后应用的路径,.app 或者 .dmg 结尾。

  2. appBundleId 跟 Electron-builder 配置的 appId 一致,这个 appId 要妥善命名。不要发布应用以后再修改,不然会导致应用无法自动更新。比较好的命名一般都是 com.xxx(公司名).xxx(应用英文名)

  1. 苹果开发者的账号 appleId,填写自己的开发者id 就可以,确保自己是属于开发者。应用专用密码 appleIdPassword,登录 appleid.apple.com/account/man…

这个密码生成后只会出现一次,之后再也没办法看到,所有请保存下来。如果忘记了密码,就重新创建一个,为方便管理不用的密码进行删除后重新创建比较合适。

  1. ascProvider 证书的提供者,通过 mac 钥匙串访问查看。你所有使用的签名证书,括号里面的就是证书提供者。

  1. 公证会把程序压缩包上传到 apple 服务器,保证网络通畅。公证成功后,开发者邮箱会收到邮件。

  1. notarize {}后面是绝对的json结构,不要出现这些是单引号的情况,不然会报错。 appPathappBundleIdappleIdPasswordascProvider

命令行工具公证

需要下载 xcode

  1. 一句话命令公证
xcrun altool --notarize-app --primary-bundle-id "com.xxx.xxx" --username "your developer appleid" --password "appleId-password" --asc-provider "ProviderShortname" -t osx --file xxx.dmg
  • "com.xxx.xxx":在苹果开发者注册的id

  • your developer appleid:你登录的苹果开发者id
  • app-password:你登录的苹果开发者的应用专用密码
  • "ProviderShortname":

  1. ascProvider 证书的提供者命令行查询
xcrun altool --list-providers -u "apple id" -p "appleIdPassword(应用专用密码)

  1. 公证成功后
No errors uploading 'xxxxxxx-xxxx.dmg'.
RequestUUID = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

上架 AppStore 商店

Electron 应用如果要能发到 appStore,需要 electron-builder 构建 mas(Mac应用商店),经过签名公证后上传到 app store connect,上传之前应用需要支持sandbox。

注册AppId

在 electron-builder 配置的 appId,无论写什么我们都是可以打包配置成功的,因为不涉及到发到 appStore。如果需要发到 appStore,就需要到 apple 开发者官网中去申请一个正式的了。

沙盒配置

在 entitlements.mas.plist 配置写入如下代码 com.apple.security.app-sandbox 进行沙盒配置。

<?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/>
   </dict>
</plist>

打包配置

mac 打包配置 mas 信息,需要在 mac 中配置 target:["mas"]mas:{}设置,并且需要 provisioningProfile,这些都会报错。

...
mac: {
    target: [
      "mas"
    ],
    icon: 'media/images/icon.icns',
    hardenedRuntime: true,
    entitlements: 'electron-builder/entitlements.plist',
    entitlementsInherit: 'electron-builder/entitlements.plist',
    provisioningProfile: 'electron-builder/comalibabaslobs.provisionprofile'
},
mas: {
    icon: 'media/images/icon-1688.icns',
    hardenedRuntime: true,
    entitlements: 'electron-builder/entitlements.mas.plist',
    entitlementsInherit: 'electron-builder/entitlements.mas.plist'
 }
...

证书申请

苹果开发者 Certificates 申请这两个证书,并且安装。在打包 mas 包的时候,会自动寻找这两个证书进行签名。

  • 3rd Party Mac Developer Application(Mac 提交证书)

  • 3rd Party Mac Developer Installer(Mac 安装程序证书,苹果发行版或第三方Mac开发者应用程序)

配置文件

苹果开发者 Profiles 申请 Mac App Store 配置信息。并且在打包配置中主动使用此配置信息 provisioningProfile: 'electron-builder/comalibabaslobs.provisionprofile'

...
mac: {
    ...
    provisioningProfile: 'electron-builder/comalibabaslobs.provisionprofile'
    ...
}
...


$ cd ~/Library/MobileDevice/Provisioning\ Profiles/ 
打开访达 -> 顶部导航栏 前往 -> 前往文件夹 -> 输入~/Library/MobileDevice/Provisioning\ Profiles/点击前住


打开Xcode,进入Preferences->Accounts,选择对应的Apple ID点击Download Manual Profiles,描述文件就会马上出现在刚才打的目录里面

上传应用包

苹果出的上传工具 Transporter,可在 appStore 下载,上传的格式为 pkg 或者 ipa 格式。找到 mas 下的 pkg 包进行上传。

Transporter 软件点交付,会先经过验证,然后上传,如果出错,会给出具体原因。以下是常见的签名错误,检查自己的证书和配置是否正确。

添加测试

苹果应用管理网站中会看到自己上传的应用,Transporter上传到网站里看到会有延时,不要误以为是没有成功。所有上传的文件会到 TestFlight,经过验证后,就可以添加内部或者外部测试人员。之后在 App Store里构建正式对外版本。

应用图标(windows & macOS)

  1. 准备一个 1024 * 1024 的 png 图片
  2. 线上 png 转 ico 和 icns(目前线上转 icns 会有点问题,建议是使用 iconutil 工具进行转换)
icowindow图标  https:
ico 至少要 256 x 256如果线上地址转成 256x256 的就可以了 512x512 有可能转不出来

icnsmac图标    https:
  1. mac 有些时候还需要做一个安装图片 在打开 mac 应用后,需要用户把左侧的应用图标拖拽到右侧,应用会被安装在 mac 应用程序中。例如:

Q&A

1、在进行mas签名的时候,自签名证书会出错,考虑重新安装下证书,直到这个证书默认有效。

3rd Party Mac Developer Application: Hangzhou xxxxx Advertising Co., Ltd. (xxxxxxx): this identity cannot be used for signing code

2、app 交付到 mac store,需要申请 Mac App Distribution 和 Mac Installer Distribution 证书。

安装后如下,应该默认证书有效,而不是需要手动信任的。

首先进行开发者ID进行签名,如果应用需要上架到AppStore,则需要生成mas,再进行 Mac App Distribution 和 Mac Installer Distribution 分发签名。

3、交付失败,证书签名错误。代码签名无效,必须使用配置文件中包含的证书进行签名。

查看 profile 配置

provisioningProfile: 

如下方式生成: Profiles -> Mac App Store -> 选择注册的ID -> 选择签名用的 Mac App Distribution

选择签名用的 Mac App Distribution,查看下是否用这个证书进行签名的。签名证书里面查看 Mac App Distribution,确认本地用哪个证书进行签名的。虽然证书名称一致,后面的过期时间可以分辨安装的不同证书。

4、没有公证的 pkg 包可以进行交付么?

用 Transporter 交付 pkg 包到 appleStore,不需要进行公证。公证的作用是为了安装时候 mac 信任此软件。

总结

  1. mac 上首次安装不出现“恶意软件”提示,需要对应用进行签名和公证两步操作。
  2. mac 进行签名和公证后,用 electron autoUpdater 进行自动更新,就能够下载和安装,如果没有进行签名和公证,或者只进行了签名,都是只能下载,但是无法自动安装和打开。
  3. mac 上 4 个证书,自己分发申请 Developer ID Application 并进行公证即可,如果需要上架到 AppStore,需要申请 Mac Installer DistributionMac App Distribution
    • 开发不需要签名和公证申请 Mac Developer 或者 Apple Development
    • 开发需要签名和公证申请 Developer ID Application
    • 上架AppStore申请 Mac Installer Distribution
    • 上架AppStore申请 Mac App Distribution
  4. mac 开发必用的两个网站,第一个开发使用,第二个应用发布使用。
  5. 一些打包配置信息官网可查,一定要学会看官方文档。 electron-builder 官网
  6. 小技巧:appid 和 应用专用密码可以存到环境变量中。node用process.env读取。

cat ~/.bash_profile

vi ~/.bash_profile

例如bash_profile文件
export LC_ALL=en_US.UTF-8
读取process.env['LC_ALL']

参考

解释了apple 开发的概念:learn.microsoft.com/zh-cn/appce…

如果您觉得这篇文章有帮助,请点个赞吧~

分享文章

相关文章

更多文章 →
electron2025-03-05
不依赖第三方库自己实现 Electron 的主与渲染进程的国际化功能
正文 直接贴出代码: 主进程实现 首先需要在 文件中获取当前系统的语言,然后初始化国际化相关: 文件: 文件 然后在主进程中就可以通过 来实现国际化了。 渲染进程的实现 App 在启动的时候渲染进程已经执行了国际化的初始化,所以在主进程已经保存了一份当前语言的 信息,所以渲染进程就不需要进程这一步,直接从主进程获取即可。 主进程进程添加一个 事件,供渲染进程获取国际化相关数据: 首先我们要在 preload 中提前将国际化相关的信息写入...
学习
electron2025-03-05
应用多开,限制只启动一个应用,防止多个实例
通过app.requestSingleInstanceLock来控制应用的多开,返回值为boolean。 此方法的返回值表示你的应用程序实例是否成功取得了锁。如果它取得锁失败,你可以假设另一个应用实例已经取得了锁并且仍旧在运行,并立即退出。 即:如果当前进程是应用程序的主要实例,则此方法返回true,同时你的应用会继续运行。如果当它返回false,如果你的程序没有取得锁,它应该立刻退出,并且将参数发送给那个已经取到锁的进程。 在macO...
学习
electron2024-09-23
Electron实现文件缓存背景
背景 基于Electron研发的一款IM企业通信桌面端应用,会存在非常多文件、图片、视频类型回话消息。在Electron应用(桌面客户端软件)中,快速加载并显示图片是提升用户体验的关键。然而,传统的图片加载方式往往存在加载速度慢、资源占用高等问题,影响了用户的使用体验。 解决的问题 1. 支持自定义配置存储的磁盘位置 2. 支持长期存储 3. 支持自定义存储大小 4. 支持自定义存储类型(如图片、视频、文件,或者更细致化到MIME) 5...
学习
electron2024-09-23
我的 Electron 客户端也可以全量和增量更新了
前言 本文主要介绍 客户端应用的自动更新,包括全量和增量这两种方式。 全量更新: 运行新的安装包,安装目录所有资源覆盖式更新。 增量更新: 只更新修改的部分,通常是渲染进程和主进程文件。 本文并没有拿真实项目来举例子,而是起一个 新的项目 从 0 到 1 来实现自动更新。 如果已有的项目需要支持该功能,借鉴本文的主要步骤即可。 前置说明: 1. 由于业务场景的限制,本文介绍的更新仅支持 操作系统,其余操作系统未作兼容处理。 2. 更新流...
学习
electron2024-09-20
我的 Electron 客户端被第三方页面入侵了
问题描述 公司有个内部项目是用 来开发的,有个功能需要像浏览器一样加载第三方站点。 本来一切安好,但是某天打开某个站点的链接,导致 整个客户端直接变成了该站点的页面 。 这一看就是该站点做了特殊的处理,经排查网页源码后,果然发现了有这么一句代码。 翻译一下就是:如果当前窗口不是顶级窗口的话,将当前窗口设置为顶级窗口。 奇怪的是两者不是 跨域 了吗,为什么 还可以影响顶级窗口。 先说一下我当时的一些解决办法: 1. 用 替换 2. 给 添...
学习
electron2024-09-13
Electron+WebRTC实现局域网内的远程控制软件
我的工位上有一台笔记本(windows),一个显示器,一台服务器(linux)。显示器同时连接笔记本和服务器,当需要用到服务器的时候:1.使用todesk等软件进行连接;2.直接把显示器切换到服务器桌面,然后给服务器插上鼠标键盘。在这种场景下,屏幕画面的传输对我来说并不是必要的,这种场景下能不能用一套键鼠控制两个电脑呢?边做边学便有了这个小工具。记录下来,其中遇到的问题和解决方案。 通过electron + Vue + primevue...
学习

评论

请登录后发表评论

去登录
加载评论中...

目录