Error cannot find module ‘custom-electron-titlebarmain‘

隆芷阳
2023-12-01

Keywords: angular-electron | custom-electron-titlebar

这类问题的解决思路在Angular-Electron框架上基本可以看作一个通用的解决方案。

问题描述

简单阐述下怎么出现的问题:

开发项目的过程中,我使用了插件custom-electron-titlebar,正常在项目根目录下下载,并按照官方文档,在主进程main.ts文件中进行配置后。在dev环境下,一切正常,但是build项目,安装exe可执行程序之后发现,我双击打开客户端软件时直接提示我:

A JavaScript error occurred in the main process

继续看错误详情发现:

Uncaught Exception:
Error: cannot find module 'custom-electron-titlbear/main'

Require stack:
xxxx/xxx/xxx/app.asar/main.js

有用的错误信息就这两个了,找不到这个模块,以及在哪里没找到。

问题原因

那,不禁就要问了,为啥我dev运行没有问题,build之后会有问题?

我去网上搜索了一下,一个有用的答案是——没有答案,没什么卵用,还得自己分析。

Angular-Electron使用了two-package.json的项目结构:

  • 其实我们可以简单的理解为,这两个package.json,一个为渲染进程服务,一个为主进程服务
  • 在项目dev环境下,项目将所有的依赖都集中放到了一个公共区域,谁用谁取,由于这个区域是公共的,所以主进程中使用的依赖依然可以正确找到自己对应的模块。
  • 但是在build时,却分开了,也就是各自打包各自的,分开到了不同的区域,主进程找主进程的,子进程找子进程的,所以production环境下,主进程找不到模块了。

这么说可能不准确,但是简单的理解下这个意思还是可以的。

关于这块我们可以验证下,根据错误信息中的Require stack,我们可以发现这个模块是在app.asar/main.js中没找到,那我们可以解压下这个asar文件,一个简单的方法是在electron-builder.json配置中加上asar:false配置,这样最终生成出来的app.asar就不是一个压缩文件,而是一个正常的文件夹。

我们可以在build之后看下release打包输出文件夹的win-unpack文件夹,这个是免安装文件夹,方便我们查看,可以很明显的看到app.asar生成的nodeModules依赖中并没有custom-electron-titlebar包。

破案了!

解决方案

分析出了原因,解决方案显而易见了,那就在app/package.json这个依赖区中下载一下custom-electron-titlebar呗。这样我们再build时,就能正常的把这个包打进去了,主进程就可以用了。

值得注意的是,如果某个插件包,不仅在主进程中用了,在渲染进程中也用了,那可能两个package.json中都要下载一遍。


没什么问题的话,到这一步基本就解决问题了,但是也会有一些额外的问题,这个就需要具体问题具体分析了,我这里提供一个我遇到的问题:

问题:依赖冲突

我在主进程的package.json下载custom-electron-titlebar之后,由于这个包依赖electron,我使用的Angular-Electron框架呢,也是依赖electron的,很不幸就依赖冲突了。

因为在渲染进程的package.json中下载这个包时,根据npm的规则,nodeModules中出现的包不会重复下载不同的版本,会进行复用,所以不会出现依赖冲突,但是当你下载到主进程的package.json中时,主进程中可没有electron的依赖项,所以在下载custom-electron-titlebar时,不可避免的会再去下载一遍electron,而且electron下载的版本可不是深度绑定的,默认下载的是最新版本。

so,如果下载的electron版本和渲染进程中依赖的electron版本不一致,啧啧,依赖冲突不可避免。

那显而易见,最简单的解决方案是啥,统一版本呗。

看看custom-electron-titlebar下载的electron版本是多少,然后把我们渲染进程中依赖的electron版本进行升/降级。

是个好方法,但是问题太大,版本的升降会带来一些不可预知的意外错误,而且,一旦electron发布了新版,啧啧,你又得统一一次,所以这个方案不是很可取。

比较好的方案是使用对等依赖来解决因为依赖项版本问题导致的冲突。

  • 什么是对等依赖,简单来说就是宿主包和依赖插件之间的依赖关系,
  • 比如:我规定了要使用我这个插件,angular的版本必须是13.0.0,那你安装angular依赖时,如果不是13.0.0,那就不会安装成功。

所以回到我们这个问题上,我们只需要在主进程的package.json中指定electron依赖的版本必须是x.x.x(渲染进程中eletron依赖项的版本),那我们在下载依赖项时就能避免依赖冲突的问题。

对等依赖在package.json配置如下:

  "peerDependencies": {
    "electron": "21.1.1"
  }

至此,完结。

 类似资料: