1.1 安装依赖包
开发者经常使用npm(或yarn add)指令来为Node.js项目安装依赖包,安装也不例外。 以下是npm和yarn安装依赖包的说明:
npm install electron --save-dev
yarn add electron --dev
官方建议我们安装依赖包作为开发依赖()。 这其实是为了避免以后制作应用程序安装包时将包及其可执行文件二次打包。 这部分我们稍后会详细解释。
如果想观察npm命令的具体执行细节,可以在其中添加两个参数,如下所示:
npm install electron --save-dev --timing=true --loglevel=verbose
使用上述指令安装依赖包,您将观察到整个安装过程的执行日志。 这里我会截取几个重要的日志并进行分析。
npm http fetch GET 200 https://registry.npm.taobao.org/electron 125ms
这是npm通过http协议获取包的注册信息的日志。 请求上述地址(我使用npm淘宝源)会得到json响应。 json中包含了所有版本的版本信息。 如果我们在安装时不指定版本号,则会安装最新版本。
> electron@9.2.0 postinstall D:\ElectronDeepDive\capture1\install\node_modules\electron
> node install.js
这是依赖包安装后npm执行依赖包中定义的hook的日志。 npm 包管理文档定义了一系列 npm 包的钩子。 钩子将在 npm 包安装后执行。 除了钩子之外,常用的还有以下钩子:
详细文档请参见:
该钩子定义在包中的.json文件中,代码如下:
"scripts": {
"postinstall": "node install.js"
}
.js程序是包中的重要程序,用于下载可执行文件和相关资源。 在下一节中,我们将解释可执行文件的下载过程。
1.2 下载的二进制文件
在.js中,程序通过以下代码获取当前操作系统的版本并下载二进制文件和相应的资源:
downloadArtifact({
version,
artifactName: 'electron',
force: process.env.force_no_cache === 'true',
cacheRoot: process.env.electron_config_cache,
platform: process.env.npm_config_platform || process.platform,
arch: process.env.npm_config_arch || process.arch
}).then(extractFile).catch(err => {
console.error(err.stack)
process.exit(1)
})
该方法由@/get包提供,该包是该包依赖的npm包。 从npm 3.x开始,npm将包管理方式从嵌套结构切换为扁平结构,因此@/get位于当前项目的目录下。 根目录下。
扩展:在npm 3.x之前,npm的包管理方式是嵌套结构,也就是说一个项目安装的依赖包位于当前项目根目录下的目录中。 假设依赖包之一依赖于其他 npm 包。 ,我们假设这个依赖包名为 ,那么它的依赖包就会安装在该目录的目录下,以此类推。 以这种方式管理依赖包将导致非常深的目录层次结构。 在操作系统中,最大文件路径长度为 260 个字符。 如果目录层次太深,依赖包的安装会失败。 而且,不同级别的依赖可能会引用同一个依赖包。 这种结构无法复用这个依赖包,而且这种情况很常见,造成大量的冗余和浪费。
从npm 3.x开始,npm的包管理方式升级为扁平化解构。 无论是当前项目的依赖包还是依赖包的依赖包,都会先安装在当前项目的目录下。 在安装过程中,如果 npm 发现当前项目目录中已经存在同版本的依赖包,则会跳过安装过程,项目直接使用已安装的依赖包。 只有版本不同,才会在这个包的目录下。 安装新的依赖包。 这样就很好的解决了前两个问题。 但这也引发了新的问题。 直到npm 5.x引入了锁机制,新的问题才得到解决。 这超出了本文的范围。 详情请参阅:
此外,npm 有一套复杂的规则来确定两个依赖包是否具有相同的版本。 这超出了本文的范围。 详情请参阅:
该方法的输入参数是一个配置对象。 对象的force属性标记了二进制文件是否需要强制下载。 如果环境变量的值为“true”,则无论本地是否有缓存,都会从服务器下载相应的文件。
配置对象的属性是需要下载的可执行程序的版本号。 该版本号是npm包的.json中定义的版本号。 该属性是当前操作系统的名称。 可能的值为“”、“win32”或“linux”等。Arch 是您当前操作系统的体系结构。 可能的值为“x32”或“x64”。 此信息可帮助您确定要下载的可执行文件的版本。
以上信息最终组装成的下载地址可能如下所示(版本号根据实际情况而定):
https://github.com/electron/electron/releases/download/v9.2.0/electron-v9.2.0-win32-x64.zip
如果是在操作系统内,以上文件会首先下载到以下目录:
C:\Users\ADMINI~1\AppData\Local\Temp
该目录由 Node.js 通过 os.() 确定。 文件下载后,程序会将其复制到缓存目录中,以供下次使用。 这种机制大大节省了开发者的时间和成本。 下一节我们将深入讲解安装过程中的缓存和镜像机制。
缓存完成后,执行上面代码中的回调方法。 该方法会将cache目录下的二进制文件压缩包解压到当前依赖包的dist目录下:
[project]\node_modules\electron\dist
除了下载二进制文件的压缩包外,还单独下载了.txt文件。 该文件记录了压缩二进制文件的值。 程序会比较该值与压缩包文件的值是否匹配,以避免用户请求被阻塞。 拦截并下载不安全的文件(这方面的效果只能说聊胜于无),或者下载过程意外终止,文件数据不完整。
1.3 缓存和镜像策略
我们上面提到的二进制文件压缩包下载成功后,会复制一份到缓存目录下,以供下次使用。 环境中默认的缓存目录为:
C:\Users\Administrator\AppData\Local\electron\Cache
这是由 Node.js 的 os.() 附加几个子目录决定的。 您可以通过设置 e 环境变量来提供用户定义的缓存目录。 在命令行临时设置该环境变量的方法是:
> set electron_config_cache=D:\ElectronDeepDive\capture1\cache
如果您以编程方式使用@/get包,还可以通过以下方式将环境变量设置写入代码中:
process.env.electron_config_cache="D:\\ElectronDeepDive\\capture1\\cache"
如果想一劳永逸地解决这个问题,也可以将这个环境变量配置到操作系统中,如下图:
图1-1 缓存目录环境变量设置
当国内网络环境不理想时,安装npm包很可能会失败。 这是因为二进制文件压缩包很难下载成功。 知道缓存目录位置后,可以先手动放置二进制包。 到对应的缓存目录,这样安装npm包时就不会出现阻塞。
你可以从同事电脑上复制对应版本的二进制包,也可以从淘宝的镜像源手动下载二进制包。 淘宝镜像源地址为:
https://npm.taobao.org/mirrors/electron/
下载的压缩包和hash文件必须按照以下路径放在cache目录下:
// 二进制包文件的路径
[你的缓存目录]/httpsgithub.comelectronelectronreleasesdownloadv9.2.0electron-v9.2.0-win32-x64.zip/electron-v9.2.0-win32-x64.zip
// 哈希值文件的路径
[你的缓存目录]/httpsgithub.comelectronelectronreleasesdownloadv9.2.0SHASUMS256.txt/SHASUMS256.txt
路径中【你的缓存目录】下的子目录的命名方式看起来有点奇怪。 这其实就是下载地址的格式(通过一个叫-的工具库,把url路径中的斜杠去掉,使其可以成为文件路径),在我的电脑上,这两个路径是下面的形式:
图1-2 二进制包文件路径
图1-3 哈希值文件路径
细心的读者可能注意到了,我的路径不是根据url地址格式化的,而是根据镜像源地址格式化的。 下面我们将介绍如何设置第三方镜像源。
@/get库下载二进制文件包的地址人为分为三部分:
这三部分组合起来最终形成下载地址。 每个部分都有其默认值和相应的环境变量,这些变量会覆盖该部分的值:
一般情况下,我们只需要设置镜像部分的环境变量即可。 比如设置淘宝的镜像源,我们只需要把环境变量的值设置为 即可。 设置方法与设置缓存目录的环境变量相同。 这将不会给出进一步的细节。
1.4 在bin目录下注入命令
依赖包安装完成后,npm会自动将命令文件注入到/.bin路径下。 不带扩展名的文件是为linux和mac准备的shell脚本。 .cmd 是传统的批处理脚本,.ps1 是运行时脚本。 下面的脚本。
命令文件中的脚本代码并不多。 以.cmd为例,简单说明一下:
@ECHO off
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
"%_prog%" "%dp0%\..\electron\cli.js" %*
ENDLOCAL
EXIT /b %errorlevel%
:find_dp0
SET dp0=%~dp0
EXIT /b
其中,~dp0指的是脚本执行的当前目录,SET是给变量赋值,%*是执行命令时输入的参数。 整个命令脚本的意义就是使用node来执行包中的cli.js文件,并将所有命令行参数一起传递。 有关批处理的更多详细信息,请参阅:
细心的读者会发现,npm 并没有将命令文件注入到所有依赖包中,而且即使将命令文件注入到包中,cli.js 文件也可能不存在。 例如,npm 并没有将命令文件注入到 core-js 包中,但是 Mocha 中注入了两套命令文件,或者说 Mocha 的独特之处在于它们的 .json 中有类似下面的配置(Mocha 配置了两个属性bin 对象,因此 npm 为其生成两组命令文件):
"bin": {
"electron": "cli.js"
}
npm 之所以在 /.bin 路径中添加命令文件,是因为许多包作者希望他们的脚本可以放在用户的环境变量中。 npm 满足了这种需求。 npm执行脚本之前,如:npm run dev,会自动创建一个命令行环境,然后将当前目录的/.bin添加到系统环境变量中,然后执行配置节中指定的脚本内容。 执行完成后然后将系统环境变量中的/.bin删除。 因此,当前目录/.bin子目录下的所有脚本都可以通过脚本名直接调用,无需添加路径。 当然,你的项目的.json必须配置相应的dev指令。 示例配置代码如下:
"scripts": { "dev": "electron ./index.js" }
完成上述配置后,您可以通过运行 npm run dev 命令开始安装。 我们看一下包中的cli.js是如何启动的。
1.5 开始使用命令
当开发者在当前项目下执行 npm run dev 时,实际上是执行了.cmd批处理文件,并传入了一个命令行参数./index.js(我们还没有创建这个文件,不过没关系。在这个节这个文件不是重点)。 我们知道.cmd批处理命令使用node来执行\\cli.js文件,同时也复制命令行参数。 那么我们看一下cli.js的执行逻辑。
cli.js中最重要的逻辑代码如下(为了便于理解,我对这段代码稍作改动):
var proc = require('child_process')
var child = proc.spawn(electronExePath, process.argv.slice(2), {
stdio: 'inherit',
windowsHide: false
})
这段代码使用Node.js对象创建一个子进程,让子进程执行可执行文件,并将当前进程的命令行参数传递给子进程。 之所以从第三个位置取命令行参数是因为根据Node.js的约定,.argv的第一个值为.,第二个值为正在执行的文件的路径,所以第三个值这就是我们所需要的。/index.js。
值得注意的是 cli.js 文件中的第一行代码:
#!/usr/bin/env node
这行代码是单行,是类 Unix 平台上可执行纯文本文件的第一行,#! 后面的命令行。 前缀告诉系统将文件传递给哪个解释器来执行。 虽然不支持lines,但这行代码仍然是必不可少的,因为这是npm的约定。
至于可执行程序如何接收这个参数,以及如何执行这个参数指向的程序文件,我们稍后会详细介绍。
1.6 版本管理方法
从2.0.0开始,版本管理方式遵循管理规则,是语义版本规范( )的实现。 这是 npm 团队维护的版本管理规范。 它实现了版本和版本范围的解析和计算。 ,比较。
版本号内容分为三部分:主版本号、次版本号和修订号,中间用点分隔。 版本号递增规则如下:
在此约束下,增加以下增量规则:
建议您使用最新的稳定版本。 如果您已经安装了旧版本或者发现有可用更新(关注官网发布页面获取更新信息),可以使用以下命令更新本地项目的版本:
npm install --save-dev electron@latest
该团队承诺仅维护三个最新的主要版本。 例如,当本文最新版本为v9.2.0时,团队将仅维护v9.xx、v8.xx和v7.xx。 v6.xx 将不再维护,当 v10.xx 发布时,v7.xx 将不再维护。 而且,当前版本的发布相当频繁。 平均一到两周就会发布新的稳定版本。 大量的更新不仅带来了更多的新功能、解决了更多的问题,也意味着你所使用的软件版本即将成为无人关心的版本,这就是为什么我建议大家跟上官方的原因团队版本发布。
我们通过npm包管理工具安装的依赖包都是稳定版本。 除了稳定版本之外,团队还维护测试版本和版本。 这是团队和一些激进开发者的战场。 除非特别需要,不建议用于商业用途。 项目中使用了这些版本。
另外,官方仓库的 Issue 页面往往会将一些重要的更新置顶,并与社区中的开发者讨论更新计划的细节。 最终方案确定后,将逐步实施更新。 例如,最近非常重要的删除模块的更新要求被固定到此页面的顶部。 这是开发者持续关注官方动态的最佳方式。 一旦您发现此页面顶部固定有不赞成的 () 内容或破坏性的 () 更新,您应该尽量避免在项目中使用它们。
新书推荐
我向大家推荐《实战》。 本书是市场上该领域最好的纸质材料。 目前,当当网正在促销中。 如果消费100-50元,实际支付200元,立减40元,折合160元。 400本书。 下单时使用折扣码[][][]即可获得即时折扣。
《实战:入门、进阶与性能优化》一书以实用为导向,讲解了如何结合现代前端技术来开发桌面应用程序。 不仅全面介绍了入门需要掌握的功能和原理,还重点介绍了开发中的重点和难点,旨在帮助读者实现快速进阶。 点击阅读原文即可购买本书。
留言并寄书
为了让真正需要书籍的读者能够获得奖品,本次活动我们将采用留言点赞的方式。 读者可以从以下几个角度留言:
活动时间:8月26日-8月27日
明晚6点,评论区点赞数前五的读者将获得《实战实战:入门、进阶与性能优化》一本。