codecamp

Electron ASAR Archives

在完成 应用程序打包 后,应用程序的源代码通常会被绑定到 ASAR存档 中,这是一种为 Electron 应用程序而设计的简易存档格式。通过捆绑到应用程序中,我们可以缓解 Windows 上加载长路径名称的问题,加速加载并隐藏你的源码, 避免粗略的检查。 通过捆绑到应用程序中,我们可以缓解 Windows 上加载长路径名称的问题,加速加载并隐藏你的源码, 避免粗略的检查。

打包后的应用运行在一个虚拟文件系统并且大多数API都可以正常执行, 但有些时候你可能在某种情况下需要在 ASAR 压缩文件内执行.

使用 ASAR 包

Electron 有两套 API:Node API 和 Web API 分别由 Node.js 和 Chromium 提供。 两套 API 都支持都支持从 ASAR 包内读取文件.

Node API

由于 Electron 的特殊补丁程序, Node API 比如 fs.readFile 和 require 使用 ASAR 就像是使用虚拟目录一样, 里面的文件也像是在文件系统内一样.

例如,假设我们在 /path/to 文件夹下有个 example.asar 包:

$ asar list /path/to/example.asar
/app.js
/file.txt
/dir/module.js
/static/index.html
/static/main.css
/static/jquery.min.js

在 ASAR 归档中读取文件:

const fs = require('fs')
fs.readFileSync('/path/to/example.asar/file.txt')

列出档案根目录下的所有文件:

const fs = require('fs')
fs.readdirSync('/path/to/example.asar')

使用档案中的模块:

require('./path/to/example.asar/dir/module.js')

你也可以在 ASAR 存档内使用 BrowserWindow 来显示一个网络页面:

const { BrowserWindow } = require('electron')
const win = new BrowserWindow()

win.loadURL('file:///path/to/example.asar/static/index.html')

Web API

在网页中,可以使用 file: 协议请求归档中的文件。 就像是 Node API, ASAR 存档可以被作为目录处理.

例如,用 $.get 获取文件:

<script>
let $ = require('./jquery.min.js')
$.get('file:///path/to/example.asar/file.txt', (data) => {
  console.log(data)
})
</script>

将 ASAR 归档文件看作是一个普通文件

某些情况下比如对 ASAR 归档文件进行校验,我们需要像读取 “文件” 那样读取 ASAR 文件。 为此你可以使用内置的没有asar功能的和原始fs模块一模一样的original-fs模块。

const originalFs = require('original-fs')
originalFs.readFileSync('/path/to/example.asar')

您也可以将 process.noAsar 设置为 true 以禁用 fs 模块中对 asar 的支持:

const fs = require('fs')
process.noAsar = true
fs.readFileSync('/path/to/example.asar')

Node API 的局限性

尽管我们已经尽了最大努力使得 ASAR 文件使用 Node API 时的应用尽可能的趋向于真实的目录结构,但仍有一些底层 Node API 我们无法保证其正常工作。

档案文件是只读的

归档文件中的内容不可更改,所以 Node APIs 里那些会修改文件的方法在使用 ASAR 文件时都无法正常工作.

工作目录不能设置为档案文件里的目录

尽管 ASAR 档案被视为目录,但文件系统中没有实际目录,因此您永远不能将工作目录设置为 ASAR 档案中的目录。将 asar 中的文件夹以 cwd 形式作为参数传入一些 API 中也会报错。

某些 API 需要额外解压档案包

大多数 fs API 可以在不解包的情况下从 ASAR 档案中读取文件或获取文件的信息,但是对于一些依赖于将真实文件路径传递给底层系统调用的 API,Electron 会将需要的文件提取到一个临时文件中,并将路径传递给API 的临时文件,使它们工作。对于这类API,会增加一些开销。

以下是一些需要额外解压的 API:

  • child_process.execFile
  • child_process.execFileSync
  • fs.open
  • fs.openSync
  • process.dlopen - 用在 require 原生模块时

fs.stat 的不真实统计信息

对 asar 档案中的文件取 fs.stat,返回的 Stats 对象不是精确值,因为这些文件不是真实存在于文件系统里。 所以除了文件大小和文件类型以外,你不应该依赖 Stats 对象的值。

执行 ASAR 档案中的二进制文件

有可以执行二进制文件的节点 API,如 child_process.exec、child_process.spawn 和 child_process.execFile,但仅支持 execFile 执行 ASAR 存档内的二进制文件。

因为 exec 和 spawn 允许 command 替代 file 作为输入,而 command 是需要在 shell 下执行的. 目前没有 可靠的方法来判断 command 中是否在操作一个 asar 包中的文件,而且即便可以判断,我们依旧无法保证可以在无任何 副作用的情况下替换 command 中的文件路径。

向 ASAR 档案添加未打包的文件

如上所述,某些 Node API 被调用时会解压文件到文件系统。 除了性能问题外,可能会触犯各种防病毒扫描程序。

作为解决方法,您可以使用 --unpack 选项将各种文件解压。在以下示例中,不会打包原生 Node.js 模块的共享库:

$ asar pack app app.asar --unpack *.node

运行命令后,您将会看到 app.asar.unpacked 文件夹与 app.asar 文件一起被创建了。 没有被打包的文件和 app.asar 会一起存档发布。


Electron 辅助功能
Electron ASAR 完整性
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }