メインコンテンツへスキップ

ASAR アーカイブ

アプリケーションの配布を作成した後、アプリのソースコードは通常、ASAR アーカイブにバンドルされます。これは、Electron アプリ用に設計されたシンプルな拡張アーカイブ形式です。アプリをバンドルすることで、Windows の長いパス名に関する問題を軽減し、require を高速化し、簡単な検査からのソースコードを隠すことができます。

バンドルされたアプリは仮想ファイルシステムで実行され、ほとんどの API は通常どおり動作しますが、いくつかの注意点のため、ASAR アーカイブを明示的に操作したい場合があります。

ASAR アーカイブの使用

Electron には、Node.js が提供する Node API と、Chromium が提供する Web API の 2 つの API セットがあります。どちらの API も ASAR アーカイブからのファイルの読み取りをサポートしています。

Node API

Electron の特別なパッチにより、fs.readFilerequire などの Node API は 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('node:fs')
fs.readFileSync('/path/to/example.asar/file.txt')

アーカイブのルートの下にあるすべてのファイルのリスト表示

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

アーカイブからのモジュールの使用

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

BrowserWindow を使用して、ASAR アーカイブ内のウェブページを表示することもできます。

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 API を提供する組み込みの original-fs モジュールを使用できます。

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

process.noAsartrue に設定して、fs モジュールでの asar のサポートを無効にすることもできます。

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

Node API の制限事項

Node API で ASAR アーカイブをできる限りディレクトリのように動作させるために努力しましたが、Node API の低レベルの性質のために、依然として制限事項があります。

アーカイブは読み取り専用です

アーカイブは変更できないため、ファイルを修正できるすべての Node API は ASAR アーカイブでは機能しません。

作業ディレクトリをアーカイブ内のディレクトリに設定できません

ASAR アーカイブはディレクトリとして扱われますが、ファイルシステムには実際のディレクトリが存在しないため、作業ディレクトリを ASAR アーカイブ内のディレクトリに設定することはできません。一部の API の cwd オプションとして渡すと、エラーが発生します。

一部の API での追加展開

ほとんどの fs API は、展開せずに ASAR アーカイブからファイルを読み取るか、ファイルの情報を取得できますが、基になるシステムコールに実際のファイルパスを渡す必要がある一部の API の場合、Electron は必要なファイルを一時ファイルに抽出し、API が動作するように一時ファイルのパスを API に渡します。これにより、これらの API のオーバーヘッドが少し増加します。

追加の展開を必要とする API は次のとおりです。

  • child_process.execFile
  • child_process.execFileSync
  • fs.open
  • fs.openSync
  • process.dlopen - ネイティブモジュールでの require によって使用されます。

fs.stat の偽の統計情報

asar アーカイブ内のファイルに対する fs.stat とその関連関数によって返される Stats オブジェクトは、これらのファイルはファイルシステムに存在しないため、推測によって生成されます。そのため、ファイルサイズを取得したり、ファイルの種類を確認したりする場合を除き、Stats オブジェクトを信頼しないでください。

ASAR アーカイブ内のバイナリの実行

child_process.execchild_process.spawnchild_process.execFile など、バイナリを実行できる Node API がありますが、execFile のみが ASAR アーカイブ内のバイナリの起動をサポートしています。

これは、execspawnfile ではなく command を入力として受け入れるため、command はシェルで実行されるためです。コマンドが asar アーカイブ内のファイルを使用しているかどうかを確実に判断する方法はなく、たとえそうであっても、副作用なしでコマンド内のパスを置き換えることができるかどうかを確実に確認することはできません。

展開済みファイルを ASAR アーカイブに追加する

上記のように、一部の Node API は呼び出されるとファイルをファイルシステムに展開します。パフォーマンスの問題に加えて、さまざまなウイルス対策スキャナーがこの動作によってトリガーされる可能性があります。

回避策として、--unpack オプションを使用して、さまざまなファイルを展開せずに残しておくことができます。次の例では、ネイティブ Node.js モジュールの共有ライブラリはパックされません。

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

コマンドを実行すると、app.asar ファイルとともに app.asar.unpacked という名前のフォルダーが作成されます。これには展開されたファイルが含まれており、app.asar アーカイブと一緒に配布する必要があります。