nix 中封装 elecron 应用

问题描述 投票:0回答:1

电子应用程序历来很难在 Nix 中打包(参见这个很酷的模因),但显然这不再是真的

如何在nix中打包一个Electron应用,并在NixOs中快速开发npm相关的东西?

javascript electron nix
1个回答
0
投票
(免责声明:我根本不是 JS 专家,只是想了解一下电子封装)

TL;DR: 如果您只想打包,并且已经有一个现有项目,您可以直接跳到“进行打包部分”部分。

如何在NixOs上快速开发

Npm/ Electron 有一种经常打包预构建二进制文件的文化(这不是很好,例如在安全性方面,但这是另一个问题),它期望有一个加载器,例如

/lib64/ld-linux-x86-64.so.2

。如果您使用 NixOs,这可能会成为问题,因为 NixOs 默认情况下会删除加载程序以实现最大的可重复性(请参阅
此处了解更多详细信息和解决方案)。如果您不想再打扰并且只需遵循可在任何标准 Linux 发行版上使用的常用教程,我建议您在 configuration.nix
:
中启用

programs.nix-ld.enable = true; ## If needed, you can add missing libraries here. nix-index-database is your friend to ## find the name of the package from the error message, like: ## $ nix run github:mic92/nix-index-database missinglib.so ## More details: https://github.com/nix-community/nix-index-database, you might like programs.nix-ld.libraries = options.programs.nix-ld.libraries.default ++ (with pkgs; [ # put here missing libraries ]);
(您可能需要重新启动才能正确传播环境变量)

这样,您就可以像在任何其他系统中一样

使用npm

现在,您可能想以干净纯粹的方式

打包您的程序,您可以使用您最喜欢的薄片等进行安装......让我们现在看看如何做到这一点。

创建一个电子项目(这里没什么有趣的)

对于本教程,我们将按照教程

中的说明创建一个基本的电子项目(因为我已启用 nix-ld):

$ mkdir my-electron-app && cd my-electron-app
$ nix-shell -p nodejs_latest
$ npm init # do set an author & description, and entrypoint = main.js
$ npm install --save-dev electron

然后在 
script

package.json
部分添加
start
命令,如下所示:
{
  "scripts": {
    "start": "electron ."
  }
}

然后,创建
https://www.electronjs.org/docs/latest/tutorial/quick-start

中列出的文件,特别是:

main.html

// main.js

// Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron')
const path = require('node:path')

const createWindow = () => {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  mainWindow.webContents.openDevTools();
  // and load the index.html of the app.
  mainWindow.loadFile('index.html')

  // Open the DevTools.
  // mainWindow.webContents.openDevTools()
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    // On macOS it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

index.html

<!--index.html-->

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    We are using Node.js <span id="node-version"></span>,
    Chromium <span id="chrome-version"></span>,
    and Electron <span id="electron-version"></span>.
  </body>
</html>

preload.js

// preload.js

// All the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
window.addEventListener('DOMContentLoaded', () => {
  const replaceText = (selector, text) => {
    const element = document.getElementById(selector)
    if (element) element.innerText = text
  }

  for (const dependency of ['chrome', 'node', 'electron']) {
    replaceText(`${dependency}-version`, process.versions[dependency])
    /* replaceText(`${dependency}-version`, process.versions[dependency]) */
  }
})

运行项目(可选)

如果您只想打包而不“交互式”测试您的软件,则可以跳过本节。

方法 1:如果您没有安装

nix-ld

,或者想要最大限度地提高纯度,您可能需要使用 NixOs 打包的

electron
。只需进入 shell:
$ nix-shell -p electron
$ electron .

它将启动您的项目(TODO:检查此解决方案在安装 npm 包后是否有效)

方法 2:另一方面,如果您运行:

$ npm start

它将尝试运行 npm 安装的 Electron。如果您安装了 
nix-ld

和所有库,它应该可以工作。如果您收到如下错误:

XXX: no such file or directory

或者错误提示您无法在 NixOs 上运行二进制文件,那么这可能意味着您运行 NixOs 并且没有启用 
nix-ld

(参见“如何在 NixOs 上快速开发,确保之后重新启动”部分)。如果你得到的是:

/tmp/electrontest/my-electron-app/node_modules/electron/dist/electron: error while loading shared libraries: libdrm.so.2: cannot open shared object file: No such file or directory

那么这意味着你需要安装在
nix-ld

提供

libdrm.so.2
的包中:
$ nix run github:mic92/nix-index-database -- libdrm.so.2 --top-level
xorg_sys_opengl.out                                   0 s /nix/store/br48s8nkd9d2y2qxzd52v9rsqhh5zrl1-xorg-sys-opengl-3/lib/libdrm.so.2
xorg_sys_opengl.out                                   0 s /nix/store/br48s8nkd9d2y2qxzd52v9rsqhh5zrl1-xorg-sys-opengl-3/lib/libdrm.so.2.4.0
libdrm.out                                            0 s /nix/store/lmqz8wx07avf4c5d0qqf0h5hwjni9yrj-libdrm-2.4.120/lib/libdrm.so.2
libdrm.out                                      110,352 x /nix/store/lmqz8wx07avf4c5d0qqf0h5hwjni9yrj-libdrm-2.4.120/lib/libdrm.so.2.4.0

在这里,您看到您想要该库
libdrm

。只需将其添加到

programs.nix-ld.enable
,如上所示,然后继续使用其他库(在我的测试中,我不需要在 KDE Plasma 中重新启动,但我的设置有点不同(旧版本),但如果您发现您的更改不是考虑到,您可能需要重新启动)。第一次可能有点烦人,但是一旦你的列表足够长,它应该适用于大多数程序(也许我们可以在 nixpkgs 中提出一套更完整的选项)。就我而言,我特别需要添加:
      libdrm
      mesa
      libxkbcommon

(但我已经列出了一个足够长的列表,
我在这里描述

做包装(有趣的部分)

要打包它,只需创建一个名为

package.nix

:

 的文件
# Inspired by pkgs/applications/editors/uivonim/default.nix # and pkgs/by-name/in/indiepass-desktop/package.nix { lib, buildNpmPackage, fetchFromGitHub, electron }: buildNpmPackage rec { pname = "my-electron-app"; version = "0.1"; src = ./.; npmDepsHash = ""; # you will get an error about mismatching hash the first time. Just copy the hash here # Useful for debugging, just run "nix-shell" and then "electron ." nativeBuildInputs = [ electron ]; # Otherwise it will try to run a build phase (via npm build) that we don't have or need, with an error: # Missing script: "build" # This method is used in pkgs/by-name/in/indiepass-desktop/package.nix dontNpmBuild = true; # Needed, otherwise you will get an error: # RequestError: getaddrinfo EAI_AGAIN github.com env = { ELECTRON_SKIP_BINARY_DOWNLOAD = 1; }; # The node_modules/XXX is such that XXX is the "name" in package.json # The path might differ, for instance in electron-forge you need build/main/main.js postInstall = '' makeWrapper ${electron}/bin/electron $out/bin/${pname} \ --add-flags $out/lib/node_modules/${pname}/main.js ''; }

和一个文件
default.nix

包含:

{ pkgs ? import <nixpkgs> {} }:
pkgs.callPackage ./package.nix {}

构建并运行:

$ nix-build $ ./result/bin/my-electron-app

享受吧!

您还可以输入:

$ nix-shell

您将获得一个安装了 Electron 的 shell,以便您可以使用以下命令进行调试:

$ electron .

进一步阅读

以下是我写的其他一些相关教程:

有关如何创建和测试派生的更多详细信息
    https://unix.stackexchange.com/questions/717168/how-to-package-my-software-in-nix-or-write-my-own-package- nixpkgs 的推导
  • 其他相关讨论:

    https://github.com/NixOS/nixpkgs/issues/46382
© www.soinside.com 2019 - 2024. All rights reserved.