docs: app distribution page (#26239)
* docs: first draft of the app distribution page * docs: second iteration of the app distribution page. Fixed mentions * docs: third iteration of the app distribution page. Fixed mentions * docs: reworked app distribution page according to mentions * docs: minor fixes to the app distribution page according to mentions
This commit is contained in:
parent
cffb51e141
commit
6fc5ff77c1
3 changed files with 44 additions and 273 deletions
|
@ -91,11 +91,6 @@ These individual tutorials expand on topics discussed in the guide above.
|
||||||
* Electron Releases & Developer Feedback
|
* Electron Releases & Developer Feedback
|
||||||
* [Versioning Policy](tutorial/electron-versioning.md)
|
* [Versioning Policy](tutorial/electron-versioning.md)
|
||||||
* [Release Timelines](tutorial/electron-timelines.md)
|
* [Release Timelines](tutorial/electron-timelines.md)
|
||||||
* [Packaging App Source Code with asar](tutorial/application-packaging.md)
|
|
||||||
* [Generating asar Archives](tutorial/application-packaging.md#generating-asar-archives)
|
|
||||||
* [Using asar Archives](tutorial/application-packaging.md#using-asar-archives)
|
|
||||||
* [Limitations](tutorial/application-packaging.md#limitations-of-the-node-api)
|
|
||||||
* [Adding Unpacked Files to asar Archives](tutorial/application-packaging.md#adding-unpacked-files-to-asar-archives)
|
|
||||||
* [Testing Widevine CDM](tutorial/testing-widevine-cdm.md)
|
* [Testing Widevine CDM](tutorial/testing-widevine-cdm.md)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
@ -1,25 +1,38 @@
|
||||||
# Application Distribution
|
# Application Distribution
|
||||||
|
|
||||||
To distribute your app with Electron, you need to package and rebrand it. The easiest way to do this is to use one of the following third party packaging tools:
|
## Overview
|
||||||
|
|
||||||
|
To distribute your app with Electron, you need to package and rebrand it.
|
||||||
|
To do this, you can either use specialized tooling or manual approaches.
|
||||||
|
|
||||||
|
## With tooling
|
||||||
|
|
||||||
|
You can use the following tools to distribute your application:
|
||||||
|
|
||||||
* [electron-forge](https://github.com/electron-userland/electron-forge)
|
* [electron-forge](https://github.com/electron-userland/electron-forge)
|
||||||
* [electron-builder](https://github.com/electron-userland/electron-builder)
|
* [electron-builder](https://github.com/electron-userland/electron-builder)
|
||||||
* [electron-packager](https://github.com/electron/electron-packager)
|
* [electron-packager](https://github.com/electron/electron-packager)
|
||||||
|
|
||||||
These tools will take care of all the steps you need to take to end up with a distributable Electron applications, such as packaging your application, rebranding the executable, setting the right icons and optionally creating installers.
|
These tools will take care of all the steps you need to take to end up with a
|
||||||
|
distributable Electron application, such as bundling your application,
|
||||||
|
rebranding the executable, and setting the right icons.
|
||||||
|
|
||||||
|
You can check the example of how to package your app with `electron-forge` in
|
||||||
|
our [Quick Start Guide](quick-start.md#package-and-distribute-the-application).
|
||||||
|
|
||||||
## Manual distribution
|
## Manual distribution
|
||||||
|
|
||||||
You can also choose to manually get your app ready for distribution. The steps needed to do this are outlined below.
|
### With prebuilt binaries
|
||||||
|
|
||||||
To distribute your app with Electron, you need to download Electron's [prebuilt
|
To distribute your app manually, you need to download Electron's [prebuilt
|
||||||
binaries](https://github.com/electron/electron/releases). Next, the folder
|
binaries](https://github.com/electron/electron/releases). Next, the folder
|
||||||
containing your app should be named `app` and placed in Electron's resources
|
containing your app should be named `app` and placed in Electron's resources
|
||||||
directory as shown in the following examples. Note that the location of
|
directory as shown in the following examples.
|
||||||
Electron's prebuilt binaries is indicated with `electron/` in the examples
|
|
||||||
below.
|
|
||||||
|
|
||||||
On macOS:
|
> *NOTE:* the location of Electron's prebuilt binaries is indicated
|
||||||
|
with `electron/` in the examples below.
|
||||||
|
|
||||||
|
*On macOS:*
|
||||||
|
|
||||||
```plaintext
|
```plaintext
|
||||||
electron/Electron.app/Contents/Resources/app/
|
electron/Electron.app/Contents/Resources/app/
|
||||||
|
@ -28,7 +41,7 @@ electron/Electron.app/Contents/Resources/app/
|
||||||
└── index.html
|
└── index.html
|
||||||
```
|
```
|
||||||
|
|
||||||
On Windows and Linux:
|
*On Windows and Linux:*
|
||||||
|
|
||||||
```plaintext
|
```plaintext
|
||||||
electron/resources/app
|
electron/resources/app
|
||||||
|
@ -37,47 +50,44 @@ electron/resources/app
|
||||||
└── index.html
|
└── index.html
|
||||||
```
|
```
|
||||||
|
|
||||||
Then execute `Electron.app` (or `electron` on Linux, `electron.exe` on Windows),
|
Then execute `Electron.app` on macOS, `electron` on Linux, or `electron.exe`
|
||||||
and Electron will start as your app. The `electron` directory will then be
|
on Windows, and Electron will start as your app. The `electron` directory
|
||||||
your distribution to deliver to final users.
|
will then be your distribution to deliver to users.
|
||||||
|
|
||||||
## Packaging Your App into a File
|
### With an app source code archive
|
||||||
|
|
||||||
Apart from shipping your app by copying all of its source files, you can also
|
Instead of from shipping your app by copying all of its source files, you can
|
||||||
package your app into an [asar](https://github.com/electron/asar) archive to avoid
|
package your app into an [asar] archive to improve the performance of reading
|
||||||
exposing your app's source code to users.
|
files on platforms like Windows, if you are not already using a bundler such
|
||||||
|
as Parcel or Webpack.
|
||||||
|
|
||||||
To use an `asar` archive to replace the `app` folder, you need to rename the
|
To use an `asar` archive to replace the `app` folder, you need to rename the
|
||||||
archive to `app.asar`, and put it under Electron's resources directory like
|
archive to `app.asar`, and put it under Electron's resources directory like
|
||||||
below, and Electron will then try to read the archive and start from it.
|
below, and Electron will then try to read the archive and start from it.
|
||||||
|
|
||||||
On macOS:
|
*On macOS:*
|
||||||
|
|
||||||
```plaintext
|
```plaintext
|
||||||
electron/Electron.app/Contents/Resources/
|
electron/Electron.app/Contents/Resources/
|
||||||
└── app.asar
|
└── app.asar
|
||||||
```
|
```
|
||||||
|
|
||||||
On Windows and Linux:
|
*On Windows and Linux:*
|
||||||
|
|
||||||
```plaintext
|
```plaintext
|
||||||
electron/resources/
|
electron/resources/
|
||||||
└── app.asar
|
└── app.asar
|
||||||
```
|
```
|
||||||
|
|
||||||
More details can be found in [Application packaging](application-packaging.md).
|
You can find more details on how to use `asar` in the
|
||||||
|
[`electron/asar` repository][asar].
|
||||||
|
|
||||||
## Rebranding with Downloaded Binaries
|
### Rebranding with downloaded binaries
|
||||||
|
|
||||||
After bundling your app into Electron, you will want to rebrand Electron
|
After bundling your app into Electron, you will want to rebrand Electron
|
||||||
before distributing it to users.
|
before distributing it to users.
|
||||||
|
|
||||||
### Windows
|
#### macOS
|
||||||
|
|
||||||
You can rename `electron.exe` to any name you like, and edit its icon and other
|
|
||||||
information with tools like [rcedit](https://github.com/electron/rcedit).
|
|
||||||
|
|
||||||
### macOS
|
|
||||||
|
|
||||||
You can rename `Electron.app` to any name you want, and you also have to rename
|
You can rename `Electron.app` to any name you want, and you also have to rename
|
||||||
the `CFBundleDisplayName`, `CFBundleIdentifier` and `CFBundleName` fields in the
|
the `CFBundleDisplayName`, `CFBundleIdentifier` and `CFBundleName` fields in the
|
||||||
|
@ -104,60 +114,20 @@ MyApp.app/Contents
|
||||||
└── MyApp Helper
|
└── MyApp Helper
|
||||||
```
|
```
|
||||||
|
|
||||||
### Linux
|
#### Windows
|
||||||
|
|
||||||
|
You can rename `electron.exe` to any name you like, and edit its icon and other
|
||||||
|
information with tools like [rcedit](https://github.com/electron/rcedit).
|
||||||
|
|
||||||
|
#### Linux
|
||||||
|
|
||||||
You can rename the `electron` executable to any name you like.
|
You can rename the `electron` executable to any name you like.
|
||||||
|
|
||||||
## Rebranding by Rebuilding Electron from Source
|
### Rebranding by rebuilding Electron from source
|
||||||
|
|
||||||
It is also possible to rebrand Electron by changing the product name and
|
It is also possible to rebrand Electron by changing the product name and
|
||||||
building it from source. To do this you need to set the build argument
|
building it from source. To do this you need to set the build argument
|
||||||
corresponding to the product name (`electron_product_name = "YourProductName"`)
|
corresponding to the product name (`electron_product_name = "YourProductName"`)
|
||||||
in the `args.gn` file and rebuild.
|
in the `args.gn` file and rebuild.
|
||||||
|
|
||||||
### Creating a Custom Electron Fork
|
[asar]: https://github.com/electron/asar
|
||||||
|
|
||||||
Creating a custom fork of Electron is almost certainly not something you will
|
|
||||||
need to do in order to build your app, even for "Production Level" applications.
|
|
||||||
Using a tool such as `electron-packager` or `electron-forge` will allow you to
|
|
||||||
"Rebrand" Electron without having to do these steps.
|
|
||||||
|
|
||||||
You need to fork Electron when you have custom C++ code that you have patched
|
|
||||||
directly into Electron, that either cannot be upstreamed, or has been rejected
|
|
||||||
from the official version. As maintainers of Electron, we very much would like
|
|
||||||
to make your scenario work, so please try as hard as you can to get your changes
|
|
||||||
into the official version of Electron, it will be much much easier on you, and
|
|
||||||
we appreciate your help.
|
|
||||||
|
|
||||||
#### Creating a Custom Release with surf-build
|
|
||||||
|
|
||||||
1. Install [Surf](https://github.com/surf-build/surf), via npm:
|
|
||||||
`npm install -g surf-build@latest`
|
|
||||||
|
|
||||||
2. Create a new S3 bucket and create the following empty directory structure:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
- electron/
|
|
||||||
- symbols/
|
|
||||||
- dist/
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Set the following Environment Variables:
|
|
||||||
|
|
||||||
* `ELECTRON_GITHUB_TOKEN` - a token that can create releases on GitHub
|
|
||||||
* `ELECTRON_S3_ACCESS_KEY`, `ELECTRON_S3_BUCKET`, `ELECTRON_S3_SECRET_KEY` -
|
|
||||||
the place where you'll upload Node.js headers as well as symbols
|
|
||||||
* `ELECTRON_RELEASE` - Set to `true` and the upload part will run, leave unset
|
|
||||||
and `surf-build` will do CI-type checks, appropriate to run for every
|
|
||||||
pull request.
|
|
||||||
* `CI` - Set to `true` or else it will fail
|
|
||||||
* `GITHUB_TOKEN` - set it to the same as `ELECTRON_GITHUB_TOKEN`
|
|
||||||
* `SURF_TEMP` - set to `C:\Temp` on Windows to prevent path too long issues
|
|
||||||
* `TARGET_ARCH` - set to `ia32` or `x64`
|
|
||||||
|
|
||||||
4. In `script/upload.py`, you _must_ set `ELECTRON_REPO` to your fork (`MYORG/electron`),
|
|
||||||
especially if you are a contributor to Electron proper.
|
|
||||||
|
|
||||||
5. `surf-build -r https://github.com/MYORG/electron -s YOUR_COMMIT -n 'surf-PLATFORM-ARCH'`
|
|
||||||
|
|
||||||
6. Wait a very, very long time for the build to complete.
|
|
||||||
|
|
|
@ -1,194 +0,0 @@
|
||||||
# Application Packaging
|
|
||||||
|
|
||||||
To mitigate [issues](https://github.com/joyent/node/issues/6960) around long
|
|
||||||
path names on Windows, slightly speed up `require` and conceal your source code
|
|
||||||
from cursory inspection, you can choose to package your app into an [asar][asar]
|
|
||||||
archive with little changes to your source code.
|
|
||||||
|
|
||||||
Most users will get this feature for free, since it's supported out of the box
|
|
||||||
by [`electron-packager`][electron-packager], [`electron-forge`][electron-forge],
|
|
||||||
and [`electron-builder`][electron-builder]. If you are not using any of these
|
|
||||||
tools, read on.
|
|
||||||
|
|
||||||
## Generating `asar` Archives
|
|
||||||
|
|
||||||
An [asar][asar] archive is a simple tar-like format that concatenates files
|
|
||||||
into a single file. Electron can read arbitrary files from it without unpacking
|
|
||||||
the whole file.
|
|
||||||
|
|
||||||
Steps to package your app into an `asar` archive:
|
|
||||||
|
|
||||||
### 1. Install the asar Utility
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ npm install -g asar
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Package with `asar pack`
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ asar pack your-app app.asar
|
|
||||||
```
|
|
||||||
|
|
||||||
## Using `asar` Archives
|
|
||||||
|
|
||||||
In Electron there are two sets of APIs: Node APIs provided by Node.js and Web
|
|
||||||
APIs provided by Chromium. Both APIs support reading files from `asar` archives.
|
|
||||||
|
|
||||||
### Node API
|
|
||||||
|
|
||||||
With special patches in Electron, Node APIs like `fs.readFile` and `require`
|
|
||||||
treat `asar` archives as virtual directories, and the files in it as normal
|
|
||||||
files in the filesystem.
|
|
||||||
|
|
||||||
For example, suppose we have an `example.asar` archive under `/path/to`:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ asar list /path/to/example.asar
|
|
||||||
/app.js
|
|
||||||
/file.txt
|
|
||||||
/dir/module.js
|
|
||||||
/static/index.html
|
|
||||||
/static/main.css
|
|
||||||
/static/jquery.min.js
|
|
||||||
```
|
|
||||||
|
|
||||||
Read a file in the `asar` archive:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const fs = require('fs')
|
|
||||||
fs.readFileSync('/path/to/example.asar/file.txt')
|
|
||||||
```
|
|
||||||
|
|
||||||
List all files under the root of the archive:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const fs = require('fs')
|
|
||||||
fs.readdirSync('/path/to/example.asar')
|
|
||||||
```
|
|
||||||
|
|
||||||
Use a module from the archive:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
require('./path/to/example.asar/dir/module.js')
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also display a web page in an `asar` archive with `BrowserWindow`:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const { BrowserWindow } = require('electron')
|
|
||||||
const win = new BrowserWindow()
|
|
||||||
|
|
||||||
win.loadURL('file:///path/to/example.asar/static/index.html')
|
|
||||||
```
|
|
||||||
|
|
||||||
### Web API
|
|
||||||
|
|
||||||
In a web page, files in an archive can be requested with the `file:` protocol.
|
|
||||||
Like the Node API, `asar` archives are treated as directories.
|
|
||||||
|
|
||||||
For example, to get a file with `$.get`:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<script>
|
|
||||||
let $ = require('./jquery.min.js')
|
|
||||||
$.get('file:///path/to/example.asar/file.txt', (data) => {
|
|
||||||
console.log(data)
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Treating an `asar` Archive as a Normal File
|
|
||||||
|
|
||||||
For some cases like verifying the `asar` archive's checksum, we need to read the
|
|
||||||
content of an `asar` archive as a file. For this purpose you can use the built-in
|
|
||||||
`original-fs` module which provides original `fs` APIs without `asar` support:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const originalFs = require('original-fs')
|
|
||||||
originalFs.readFileSync('/path/to/example.asar')
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also set `process.noAsar` to `true` to disable the support for `asar` in
|
|
||||||
the `fs` module:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const fs = require('fs')
|
|
||||||
process.noAsar = true
|
|
||||||
fs.readFileSync('/path/to/example.asar')
|
|
||||||
```
|
|
||||||
|
|
||||||
## Limitations of the Node API
|
|
||||||
|
|
||||||
Even though we tried hard to make `asar` archives in the Node API work like
|
|
||||||
directories as much as possible, there are still limitations due to the
|
|
||||||
low-level nature of the Node API.
|
|
||||||
|
|
||||||
### Archives Are Read-only
|
|
||||||
|
|
||||||
The archives can not be modified so all Node APIs that can modify files will not
|
|
||||||
work with `asar` archives.
|
|
||||||
|
|
||||||
### Working Directory Can Not Be Set to Directories in Archive
|
|
||||||
|
|
||||||
Though `asar` archives are treated as directories, there are no actual
|
|
||||||
directories in the filesystem, so you can never set the working directory to
|
|
||||||
directories in `asar` archives. Passing them as the `cwd` option of some APIs
|
|
||||||
will also cause errors.
|
|
||||||
|
|
||||||
### Extra Unpacking on Some APIs
|
|
||||||
|
|
||||||
Most `fs` APIs can read a file or get a file's information from `asar` archives
|
|
||||||
without unpacking, but for some APIs that rely on passing the real file path to
|
|
||||||
underlying system calls, Electron will extract the needed file into a
|
|
||||||
temporary file and pass the path of the temporary file to the APIs to make them
|
|
||||||
work. This adds a little overhead for those APIs.
|
|
||||||
|
|
||||||
APIs that requires extra unpacking are:
|
|
||||||
|
|
||||||
* `child_process.execFile`
|
|
||||||
* `child_process.execFileSync`
|
|
||||||
* `fs.open`
|
|
||||||
* `fs.openSync`
|
|
||||||
* `process.dlopen` - Used by `require` on native modules
|
|
||||||
|
|
||||||
### Fake Stat Information of `fs.stat`
|
|
||||||
|
|
||||||
The `Stats` object returned by `fs.stat` and its friends on files in `asar`
|
|
||||||
archives is generated by guessing, because those files do not exist on the
|
|
||||||
filesystem. So you should not trust the `Stats` object except for getting file
|
|
||||||
size and checking file type.
|
|
||||||
|
|
||||||
### Executing Binaries Inside `asar` Archive
|
|
||||||
|
|
||||||
There are Node APIs that can execute binaries like `child_process.exec`,
|
|
||||||
`child_process.spawn` and `child_process.execFile`, but only `execFile` is
|
|
||||||
supported to execute binaries inside `asar` archive.
|
|
||||||
|
|
||||||
This is because `exec` and `spawn` accept `command` instead of `file` as input,
|
|
||||||
and `command`s are executed under shell. There is no reliable way to determine
|
|
||||||
whether a command uses a file in asar archive, and even if we do, we can not be
|
|
||||||
sure whether we can replace the path in command without side effects.
|
|
||||||
|
|
||||||
## Adding Unpacked Files to `asar` Archives
|
|
||||||
|
|
||||||
As stated above, some Node APIs will unpack the file to the filesystem when
|
|
||||||
called. Apart from the performance issues, various anti-virus scanners might
|
|
||||||
be triggered by this behavior.
|
|
||||||
|
|
||||||
As a workaround, you can leave various files unpacked using the `--unpack` option.
|
|
||||||
In the following example, shared libraries of native Node.js modules will not be
|
|
||||||
packed:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ asar pack app app.asar --unpack *.node
|
|
||||||
```
|
|
||||||
|
|
||||||
After running the command, you will notice that a folder named `app.asar.unpacked`
|
|
||||||
was created together with the `app.asar` file. It contains the unpacked files
|
|
||||||
and should be shipped together with the `app.asar` archive.
|
|
||||||
|
|
||||||
[asar]: https://github.com/electron/asar
|
|
||||||
[electron-packager]: https://github.com/electron/electron-packager
|
|
||||||
[electron-forge]: https://github.com/electron-userland/electron-forge
|
|
||||||
[electron-builder]: https://github.com/electron-userland/electron-builder
|
|
Loading…
Add table
Add a link
Reference in a new issue