【CEP教程-17】插件的打包和发布

【CEP教程-17】插件的打包和发布

这篇文章介绍当插件完成开发和测试之后,如何进行打包、生成可安装程序交付到用户的手中。

整个插件发布的过程,我大体分了如下几个环节,这篇文章我们会按照这几个环节逐个展开。

  1. 目录结构整理
  2. 版本号和更新机制
  3. 代码混淆和加密
  4. 签名
  5. 构建安装程序
  6. 发布到平台

为了能够有优雅的开发体验,发布的这个过程,我们也希望能够容纳到上文提到的工程化当中,只需要一个发布的命令,就能够完成这些操作,大幅提升我们的开发和发布效率。

1. 目录结构整理

一般而言,我们的工程结构,都是以开发状态进行呈现的,尤其当引入了第三方库或者工程化的构建工具之后,开发状态的代码(或者目录结构)是存在很多冗余文件和目录的。真正发布之后的插件不应该存在这些无用的内容,所以我们需要对发布的目录和文件进行整理。 比如下图左边是一个开发状态下的目录结构,右边是一个发布后的目录结构

->

对于发布之后的目录结构,除了对CSXS的目录有强制要求之外,其它的文件夹和文件并没有特殊规定,你可以按照自己的喜好进行归类放置。

那为了实现开发到发布过程中这些目录和文件的位置变换,我们可以在webpack的打包脚本里头进行操作,我们可以安装一个webpack的文件拷贝插件

1
npm install --save-dev copy-webpack-plugin

安装完成之后,在webpack的配置文件中添加此插件,并针对想要的文件进行设置

1
2
3
4
5
6
7
// webpack.config.js
// 写在plugin数组里头
new copyWebpackPlugin([
{ from: "./src/CSXS", to: "CSXS" },
{ from: "./src/js", to: "js" },
{ from: "./src/jsx/init.jsx", to: "jsx/init.jsx" },
])

代码过程非常简单,就是将需要的文件,复制到目标目录下即可。

2. 版本号与更新机制

当我们的产品发布之后,难免会涉及到迭代升级,这就需要我们的插件具备版本检查的机制,这个东西本身和打包发布其实没有关系,是插件自身功能的一部分,在这里提及主要是很多人会忽略这个点。

对于插件更新,如果我们的插件发布到的是Adobe的插件商店,则Creative Cloud能够帮助我们管理版本升级,还能自动更新。但是考虑到国内市场CC商店基本属于不可用状态,我们一般也不把插件发布到官方商店当中,那如果要做版本更新的话,就得自己维护一个后台服务器,然后在插件启动的时候去访问服务器获取最新的版本信息进行提示更新。

3. 代码的混淆与加密

为了保护我们的产品,比如避免被破解,或者代码被他人抄袭,一般在发布的时候,都会对核心代码进行混淆和加密。我们可以在webpack的编译过程中完成此操作

安装js的压缩混淆插件,安装jsxbin插件

1
npm install --save-dev uglifyjs-webpack-plugin jsxbin-webpack-plugin

在webpack配置中引入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
optimization: {
minimizer: [
new UglifyJsPlugin({
test: /\.js(\?.*)?$/i,
uglifyOptions: {
mangle: true,
compress: true,
output: {
beautify: false
}
}
}),
new JSXBinWebpackPlugin({
test: /\.js$/
})
]
}

这样当你的JSX代码在编译输出之后,就会自动进行代码混淆,同时还会将混淆的代码通过PS的加密转成JSXBIN格式,大体长这样

uglify code

从普通用户视角,基本上是看不出来什么的,能够起到一定的代码保护作用。

注:软件安全是相对的,我们对代码的混淆、加密等等措施,并不能保证100%可靠,在专业人士手里,依然能够进行反解和破译,这些加密措施仅仅起到了防君子不防小人的效果,在一定程度上增加了破解成本而已。

4. 签名

默认情况下,宿主对安装的插件会进行签名检查,如果安装的插件没有进行签名,宿主就会报错,提示签名不存在而无法正常使用。

对插件进行签名,首先需要一份证书,这个证书可以从第三方证书签发机构进行购买,这种第三方购买的证书因为有签发机构做背书,可靠性会更好一些。在以前如果你的插件要上传到官方插件商店,就需要用这种第三方签发的证书进行签名,然而这种第三方的证书一般都巨贵……

另外一个途径是自己创建一个自签名的证书自己使用,官方提供了一个工具可以用来生成自签名证书和签名操作,你可以从下面链接进行下载。(我映象中应该还有人开发了对于的GUI版本,不过我没有找着,哪位小伙伴有可以分享一下给大家)

ZXPSignCMD

该工具提供了mac和win下的两个命令行工具,可以通过命令操作完成证书生成

1
2
# 括号里头的内容,按照自己的需要填写即可
ZXPSignCmd -selfSignedCert <countryCode> <stateOrProvince> <organization> <commonName> <password> <outputPath.p12>

生成的.p12文件就是你的证书文件,要保存好。

有了这个证书文件之后,我们可以对要发布的插件文件夹进行签名,签名的过程也是用上面这个工具来完成

1
2
# inputDirectory就是整个插件文件夹
ZXPSignCmd -sign <inputDirectory> <outputZxp> <p12> <p12Password>

这个命令执行完,会将你的插件文件夹进行签名,并生成一个压缩包文件以.zxp结尾,该文件格式是早期官方提供的Adobe Extension Manager所配套的格式文件,双击该文件会自动用插件管理器打开并安装。但是由于后来Adobe官方废弃了此插件管理器,后来集成到了Creative Cloud当中,顺利的话,如果电脑上安装了Creative Cloud,双击zxp文件会打开CC进行插件安装,但是也不见得都能成功……

所以,为了能够确保插件安装正常,我们在后面的环节介绍单独的插件安装方案。

为了能够将签名的过程集成到我们的构建发布流程中,我们可以将上面的签名过程集成到webpack当中,当代码完成编译、混淆、加密、目录结构调整之后,就会有一个完整的插件文件夹,我们对这个文件夹进行签名,用之前已经制作好的自签名证书进行签名。

我们可以通过webpack提供的事件来判断上述操作是否都完成了,至于签名,你其实也不需要自己去弄那个命令工具,已经有前辈帮我们写好了工具的npm封装

zxp-sign-cmd

zxp-sign-cmd

1
2
3
4
5
6
7
8
9
// 放到webpack plugin列表当中
{
apply: (compiler) => {
compiler.hooks.afterEmit.tap('AfterEmitPlugin', async (compilation) => {
// 在这里进行签名操作
// ...
});
}
}

签名之后生成的zxp文件,其实是一个压缩包,我们可以把它解压出来,依然是一个插件文件夹,会发现文件夹下多出来了一些文件,即表示签名完成了

signed plugin

不放心的话,你还可以通过ZXPSignCMD命令进行签名检查

verify signature

5. 构建安装程序

前面提到签名之后的zxp文件是不太好给用户进行安装的,因为大体用户都无法打开此文件。为了让用户可以顺利安装上我们的插件,我们需要构建一个可执行的安装程序,就好比安装普通应用程序那样,在windows下有一个.exe文件,用户双击即打开了软件安装向导,用户根据向导的提示完成软件的安装。

下面我们来介绍一下如何针对win和mac构建对应平台的可执行安装程序!

由于桌面软件开发已经是一个非常成熟的领域了,对应的软件安装程序也有非常多直接可用的,我们可以挑选一个喜欢的或者好用的,做一些配置,改造成我们的插件安装程序。

1) windows平台

win下有许多优秀的软件包制作工具,如NSISInno Setup, InstallShield等等,有一些是付费的,有一些是开源免费的,都能够满足要求,大家可以找一个自己喜欢的。我日常使用的是NSIS,一款小巧又功能强大的安装包制作工具,选择它是因为它提供了mac下的二进制文件,可以让我直接在mac上进行打包操作。

NSIS提供了GUI的软件制作界面,不过如果你想要实现复杂的安装程序,需要学习它的编程语法结构,这个门槛稍微有点高,因为它的语法和常规的编程语言不太一样,学习难度稍大。

nsis installer

这里给一个简单的小例子,大家可以感受一下,如果要完整的实现自己的打包脚本,还是建议大家去学习一下它的语法功能,如果觉得有难度,可以考虑换一些支持更加可视化的制作软件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
; Installer for Ps Plugins
; Written by xiaoqiang
; 2018/09/28
;
; Dependencies:
; ...

!include "MUI2.nsh"

; ---------- customize ---------
!define PANEL_NAME "com.cutterman.psdcleaner"
!define PANEL_PACKAGE_NAME "${PanelPackageName}"
!define OUT_PUT_FILE "${OutFileName}"

;-------------------------------------------------
; Defines
!define PANEL_INSTALL_DIR "$APPDATA\Adobe\CEP\extensions"
!define COMMON_PANEL_INSTALL_DIR "$COMMONFILES\Adobe\CEP\extensions"
!define COMMON_PANEL_INSTALL_DIR_X86 "$COMMONFILES32\Adobe\CEP\extensions"

Name "${PANEL_NAME} Installer"
OutFile "${OUT_PUT_FILE}"
ShowInstDetails show
InstallDir ${COMMON_PANEL_INSTALL_DIR}
LangString nsisunz_text 2052 "Extract: %f (%c -> %u)"

RequestExecutionLevel admin
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
Icon "favicon.ico"

Section
SetOutPath ${COMMON_PANEL_INSTALL_DIR}
; delete old version
RMDir /r "${COMMON_PANEL_INSTALL_DIR}\${PANEL_NAME}"
; install panel
File /r "${PANEL_PACKAGE_NAME}"
SectionEnd

通过自定义部分修改对应的插件名称和路径,就可以编译输出了

1
/usr/local/bin/makensis  -DOutFileName=${dist}/${win_output}.exe -DPanelPackageName=${path.join(dist, panelName)} ${__dirname}/build/package.nsi

我可以将这部分的代码放到webpack当中,在ZXP完成签名之后,将zxp解压成文件夹,然后对这个文件夹进行打包制作exe文件

package installers

1
2
3
4
async function packageWindows() {
await run(`cd ${__dirname}; ${nsis} -DOutFileName=${dist}/${win_output}.exe -DPanelPackageName=${path.join(dist, panelName)} ${__dirname}/build/package.nsi`);
await run(`cd ${dist}; zip -qr ${win_output}.zip ${win_output}.exe`);
}

2) mac平台

同样的 ,mac下也有很多类似的软件包制作工具,我用的是Package,一款免费小巧的软件包制作工具,它完全支持GUI界面傻瓜式操作,新手很友好,同时生成的配置文件又可以通过命令执行,真心不错。

Package Installer

先用GUI制作好安装过程,就会保存成一个工程文件,然后用命令行执行该工程文件,即可生成对应的安装包了

1
2
3
4
async function packageMac() {
await run(`/usr/local/bin/packagesbuild build/package.pkgproj`);
await run(`cd ${dist}; zip ${mac_output}.zip ${name}.pkg`);
}

将这些都弄好之后,只要我们执行编译发布的命令,就能够自动完成编译混淆加密签名打包这一系列的功能,甚至如果你有服务器的话,还可以把已经生成好的exe/pkg文件上传到服务器上,触发一次版本更新诸如此类的,大幅提升我们的软件开发效率。

deploy flow

6. 发布

当我们的软件包已经制作好之后,就可以交付给用户了。

  1. 如果你想要在Adobe的官方商店进行发布的话,你只需要提供zxp安装包,上传到Adobe Exchange Store的开发者后台,经过审核之后就可以发布了。不过由于Adobe目前都倾向于整UXP的插件CEP插件已经不被推荐了,不过你依然可以完成此过程,Adobe官方商店还支持付费购买,可以通过此渠道赚一点点小钱~~

  2. 如果你有自己的官方站点,可以将安装程序放到自己的网站上提供用户下载。

  3. 如果你有自己的社群,或者离用户/客户很近,就直接把安装程序发给对方吧~~

虽然你的软件开发完了也发布了,但是其实事情还没完,用户安装的时候也会遇到各种奇葩的现象,比如用户下载了你的exe,然后被杀毒软件给干掉了;比如你的Mac安装程序,那个pkg/dmg安装程序其实是没有苹果的官方签名的,这样在某些Mac电脑上就不会被允许打开,用户会一脸懵逼……

就算用户安装上了,开始使用了你的插件产品,依然会面临用户报各种问题,比如Ps版本不兼容,比如没有权限,比如你的代码有bug导致某些场景下无法正常运行等等,这个事情往往是最难的,因为场景发生在用户的电脑上,你自己无法复现现象,也猜不出来原因,你需要找一些方法来解决这类问题,这里面又可以写一篇文章了。

总结

好了,本篇文章的内容就全部讲完了。

另外,这是本系列教程的最终章了,我用了17篇长文介绍了Adobe CEP插件从入门到完整的发布一款插件产品的方方面面,整个花费了大半年的时间,好在没有鸽,坚持的写完了,为自己的坚持点个赞!

回顾了这十几篇文章,我自己还是比较满意的,每一篇都很认真的在写,内容也很详实,覆盖面足够,也有一定的深度,其中Action Manager劝退三部曲是本教程的精华,全网独一份。我觉得这应该是全网最好的CEP开发教程了,甚至比国外的DavideBarranca写的那本书还要全面和有深度一些。

也感谢期间各位小伙伴的关注,让我不至于独自一个人在往前走~~

这个系列教程虽然写完了,和CEP开发的内容并不会结束,我后续依然会不定期更新一些开发技巧和某些知识点的补充,以专题的形式出现,欢迎大家继续关注。

另外,后续会考虑开始写UXP的系列教程,正好借这个机会把我的插件迁移到UXP架构上,后续还会考虑涉猎一些C++的插件开发,另外我还熟悉Sketch、XD、Figma的插件开发,也熟悉IOS/Android以及后端开发,大家如果有其它想了解的内容,也欢迎在评论区回复或者加入微信群交流~~

今年的个人目标是考研上岸,所以后续的更新频率不会太高,也欢迎大家分享这些教程给需要的小伙伴~~ 可以注明出处

【CEP教程-17】插件的打包和发布

https://uiscripting.com/2022/07/21/deploy/

作者

小强

发布于

2022-07-21

更新于

2023-03-07

许可协议

评论