[electron] Учебник Ultimate Deep Truth из 5000 слов предоставлен вам

Node.js внешний интерфейс React.js Electron
[electron] Учебник Ultimate Deep Truth из 5000 слов предоставлен вам

предисловие

Эта статья содержит打包,自动更新,简易API,调试,进程通信и другие связанные точки знаний, есть много контента, который может вызвать дискомфорт, пожалуйста, проверьте, если это уместно (вручную смешно).

electron

Введение

electronРазработанная Github, это библиотека с открытым исходным кодом для создания настольных приложений с помощью HTML, CSS и JavaScript, которая может быть упакована как приложения для систем Mac, Windows и Linux.

Electron — это среда выполнения, включающая Node и Chromium, которую можно понимать как запуск веб-приложений в среде узла.

структура

Электрон в основном делится на основной процесс и процесс рендеринга, взаимосвязь следующая

пробег электронаpackage.jsonсерединаmainПоле указывает на то, что процесс скрипта вызываетсяосновной процесс

Создайте веб-страницу в основном процессе для отображения страницы пользователя,Электрон имеет один и только один основной процесс

Electron использует Chromium для отображения веб-страниц, каждая страница работает сама по себе渲染进程середина

быстрый старт

Далее, пусть код говорит, неудержимыйhello world

Создайте папку и выполнитеnpm init -y, сгенерироватьpackage.jsonзагрузка документаelectronмодуль и добавить зависимости разработки

mkdir electron_hello && cd electron_hello && npm init -y && npm i electron -D

Скорость загрузки слишком низкая или не работает, попробуйте использовать cnpm, способ установки следующий

# 下载cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
# 下载electron
cnpm i electron -D

Создайте index.js и напишите следующее

const {app, BrowserWindow} = require('electron')

// 创建全局变量并在下面引用,避免被GC
let win

function createWindow () {
    // 创建浏览器窗口并设置宽高
    win = new BrowserWindow({ width: 800, height: 600 })
    
    // 加载页面
    win.loadFile('./index.html')
    
    // 打开开发者工具
    win.webContents.openDevTools()
    
    // 添加window关闭触发事件
    
    win.on('closed', () => {
        win = null  // 取消引用
    })
}

// 初始化后 调用函数
app.on('ready', createWindow)  

// 当全部窗口关闭时退出。
app.on('window-all-closed', () => {
   // 在 macOS 上,除非用户用 Cmd + Q 确定地退出,
   // 否则绝大部分应用及其菜单栏会保持激活。
   if (process.platform !== 'darwin') {
        app.quit()
   }
})
  
app.on('activate', () => {
// 在macOS上,当单击dock图标并且没有其他窗口打开时,
// 通常在应用程序中重新创建一个窗口。
    if (win === null) {
      createWindow()
    }
})

Создать index.html

<!DOCTYPE html>
<html>
    <head>
      <meta charset="UTF-8">
      <title>Hello World!</title>
    </head>
    <body>
        <h1 id="h1">Hello World!</h1>
        We are using node
        <script>
            document.write(process.versions.node)
        </script>
        Chrome
        <script>
            document.write(process.versions.chrome)
        </script>,
        and Electron
        <script>
            document.write(process.versions.electron)
        </script>
    </body>
</html>

Последний отзывpackge.jsonв основное поле и добавьте команду запуска

{
    ...
    main:'index.js',
    scripts:{
        "start": "electron ."
    }
}

воплощать в жизньnpm run startПосле этого появится наше приложение.

отладка

Мы знаем, что у электрона есть два процесса, основной процесс и процесс рендеринга, как нам нужно отлаживать их в процессе разработки? Старушка ест хурму, давай наберём мягкую

процесс рендеринга

BrowserWindow используется для создания и управления окном браузера, мы можем вызвать API на его экземпляре.

win = new BrowserWindow({width: 800, height: 600})
win.webContents.openDevTools() // 打开调试

Отладка такая же как у Хрома, должно быть так кисло?

основной процесс

Отладка с помощью VSCode

Откройте проект с помощью VSCode и нажмите кнопку отладки.

Щелкните раскрывающийся список после отладки

Выберите добавить конфигурацию, выберите узел

В это время будет включена конфигурация отладки по умолчанию, которая может выглядеть так:

Какой? У вас нет, если нет, просто скопируйте следующее и замените свою конфигурацию

Это почти все, тогдаconfigurationsСкопируйте второй элемент внутри в свойconfigurationsВнутри первая конфигурация используется для отладки узла

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "启动程序",
      "program": "${workspaceFolder}/main.js"
    },
    {
        "name": "Debug Main Process",
        "type": "node",
        "request": "launch",
        "cwd": "${workspaceFolder}",
        "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
        "windows": {
          "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
        },
        "args" : ["."]
      }
  ]
}

можно увидеть${workspaceFolder}, это переменная о VSCode, используемая для представления пути к текущей открытой папке.

Для получения дополнительных переменных, пожалуйста, нажмите здесь

После изменения конфигурации отлаживаем панель и выбираем ту, которую только что настроили

Отметьте место в коде, которое необходимо отладить, а затем щелкните маленький зеленый треугольник, и вы можете успешно отладить

связь процесса

В Electron модули, связанные с графическим интерфейсом (такие как диалог, меню и т. д.), доступны только в основном процессе, а не в процессе рендеринга. Для того, чтобы использовать их в процессе рендеринга, модуль ipc необходим для отправки сообщений между процессами в основной процесс.Несколько методов межпроцессного взаимодействия описаны ниже.

Привет братья

ipcMainа такжеipcRendererЭто два хороших друга, и с помощью этих двух модулей может быть достигнута технологическая коммуникация.

  • ipcMain Используется в основном процессе для обработки синхронной и асинхронной информации, отправляемой процессом рендеринга (веб-страница).

  • ipcRenderer Используется в процессе рендеринга для отправки синхронной или асинхронной информации в основной процесс, а также может использоваться для получения ответной информации от основного процесса.

Связь между двумя вышеуказанными модулями можно понимать как发布订阅模式Далее мы рассмотрим их конкретное использование.

основной процесс

const {ipcMain} = require('electron')

// 监听渲染程序发来的事件
ipcMain.on('something', (event, data) => {
    event.sender.send('something1', '我是主进程返回的值')
})

процесс рендеринга

const { ipcRenderer} = require('electron') 

// 发送事件给主进程
ipcRenderer.send('something', '传输给主进程的值')  

// 监听主进程发来的事件
ipcRenderer.on('something1', (event, data) => {
    console.log(data) // 我是主进程返回的值
})

Приведенный выше код использует асинхронную передачу сообщений, а электронный также предоставляет API для синхронной передачи.

Отправка синхронного сообщения заблокирует весь процесс рендеринга, и вам следует избегать его использования, если только вы не знаете, что делаете.

Не используйте ipc для передачи большого количества данных, это приведет к большим проблемам с производительностью, и это серьезно затормозит все ваше приложение.

удаленный модуль

Используя удаленный модуль, вы можете вызывать объекты основного процесса метода без необходимости отправлять явные межпроцессные сообщения.

const { dialog } = require('electron').remote
dialog.showMessageBox({type: 'info', message: '在渲染进程中直接使用主进程的模块'})

webContents

WebContents отвечает за отрисовку и управление веб-страницами, это атрибут объекта BrowserWindow, и мы используем метод Send для отправки асинхронных сообщений процессу визуализации.

основной процесс

const {app, BrowserWindow} = require('electron')

let win

app.on('ready', () => {

    win = new BrowserWindow({width: 800, height: 600})
    
    // 加载页面
    win.loadURL('./index.html')
    
    // 导航完成时触发,即选项卡的旋转器将停止旋转,并指派onload事件后。
    win.webContents.on('did-finish-load', () => {

        // 发送数据给渲染程序
        win.webContents.send('something', '主进程发送到渲染进程的数据')
    })
})

процесс рендеринга

<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <script>
            require('electron').ipcRenderer.on('something', (event, message) => {
                console.log(message) // 主进程发送到渲染进程的数据
            })
        </script>
    </body>
</html>

Обмен данными процесса рендеринга

В большинстве случаев мы используем реализацию API HTML5, такую ​​​​как localStorage, sessionStorage и т. Д., Также можно реализовать с использованием механизма электронного IPC.

основной процесс

global.sharedObject = {
    someProperty: 'default value'
}

процесс рендеринга

первая страница

require('electron').remote.getGlobal('sharedObject').someProperty = 'new value'

вторая страница

console.log(require('electron').remote.getGlobal('sharedObject').someProperty) // new value

Суммировать

Вышеупомянутые четыре метода могут реализовать связь между основным процессом и процессом рендеринга, вы можете найти применениеremoteМодули самые простые и могут использоваться непосредственно в коде процесса рендеринга.electronмодуль

Общие модули

Сочетание клавиш и меню

локальный ярлык

Он будет запускаться только тогда, когда приложение сфокусировано, основной код выглядит следующим образом.

Тест официального документа не действует

const { Menu, MenuItem } = require('electron')
const menu = new Menu()
  
menu.append(new MenuItem({
  label: '自定义快捷键',
  submenu: [
    {
      label: '测试',
      accelerator: 'CmdOrCtrl+P',
      click: () => { 
          console.log('我是本地快捷键')
      }
    }
  ]
}))
Menu.setApplicationMenu(menu)

Глобальные сочетания клавиш

Зарегистрируйте глобальную переменную, она будет запущена независимо от того, сфокусировано ли приложение или нет, используйтеglobalShortcutДля регистрации основной код выглядит следующим образом:

const {globalShortcut, dialog} = require('electron')

app.on('read', () => {
    globalShortcut.register('CmdOrCtrl+1', () => {
        dialog.showMessageBox({
            type: 'info',
            message: '你按下了全局注册的快捷键'
          })
    })
})

Дисплей выглядит следующим образом, используяdialogмодуль

контекстное меню

Контекстное меню — это меню, отображаемое при щелчке правой кнопкой мыши, которое задается в процессе рендеринга.

Основной код выглядит следующим образом

const remote = require('electron').remote;  // 通过remote模块使用主程序才能使用的模块
const Menu = remote.Menu;
const MenuItem = remote.MenuItem;
var menu = new Menu();
menu.append(new MenuItem({ label: 'MenuItem1', click: function() { console.log('item 1 clicked'); } }));
menu.append(new MenuItem({ type: 'separator' }));
menu.append(new MenuItem({ label: 'MenuItem2', type: 'checkbox', checked: true }));

window.addEventListener('contextmenu', (e) => {
  e.preventDefault();
  menu.popup(remote.getCurrentWindow());
}, false);

меню приложения

Выше мы проходимMenuМодуль создает локальные сочетания клавиш, а меню приложения также используетMenuМодуль, мы видим, что он выглядит так же, на самом деле он аналогичен в реализации. Для его достижения мы используем метод создания шаблона. Основной код выглядит следующим образом:

const {app, Menu} = require('electron')
const template = [
  {
    label: '操作',
    submenu: [{
        label: '复制',
        accelerator: 'CmdOrCtrl+C',
        role: 'copy'
    }, {
        label: '粘贴',
        accelerator: 'CmdOrCtrl+V',
        role: 'paste'
    }, {
        label: '重新加载',
        accelerator: 'CmdOrCtrl+R',
        click: function (item, focusedWindow) {
            if (focusedWindow) {
                // on reload, start fresh and close any old
                // open secondary windows
                if (focusedWindow.id === 1) {
                    BrowserWindow.getAllWindows().forEach(function (win) {
                        if (win.id > 1) {
                            win.close()
                        }
                    })
                }
                focusedWindow.reload()
            }
        }
    }]
  },
  {
    label: '加载网页',
    submenu: [
      {
        label: '优酷',
        accelerator: 'CmdOrCtrl+P',
        click: () => { console.log('time to print stuff') }
      },
      {
        type: 'separator'
      },
      {
        label: '百度',
      }
    ]
  }
]

if (process.platform === 'darwin') {
    const name = electron.app.getName()
    template.unshift({
      label: name,
      submenu: [{
        label: `关于 ${name}`,
        role: 'about'
      }, {
        type: 'separator'
      }, {
        label: '服务',
        role: 'services',
        submenu: []
      }, {
        type: 'separator'
      }, {
        label: `隐藏 ${name}`,
        accelerator: 'Command+H',
        role: 'hide'
      }, {
        label: '隐藏其它',
        accelerator: 'Command+Alt+H',
        role: 'hideothers'
      }, {
        label: '显示全部',
        role: 'unhide'
      }, {
        type: 'separator'
      }, {
        label: '退出',
        accelerator: 'Command+Q',
        click: function () {
          app.quit()
        }
      }]
    })
}

app.on('read', () => {
    const menu = Menu.buildFromTemplate(template);
    Menu.setApplicationMenu(menu);
})

системный трей

основной код

const { app, Tray } = require('electron') 
/* 省略其他代码 */
let tray;
app.on('ready', () => {
    tray = new Tray(__dirname + '/build/icon.png');//系统托盘图标
    
    const contextMenu = Menu.buildFromTemplate([ // 菜单项
      {label: '显示', type: 'radio', click: () => {win.show()}},
      {label: '隐藏', type: 'radio', click: () => {win.hide()}},
    ])
    
    // tray.on('click', () => { //  鼠标点击事件最好和菜单只设置一种
    //   win.isVisible() ? win.hide() : win.show()
    // })
    
    tray.setToolTip('This is my application.') // 鼠标放上时候的提示
    
    tray.setContextMenu(contextMenu) // 应用菜单项
})

Список модулей

Menu

MenuItem

globalShortcut

dialog

tray

открыть страницу

shell

Когда основной процесс открывает страницу, он вызывает браузер по умолчанию, чтобы открыть страницу, используяshellмодуль

const { app,shell } = require('electron')

app.on('ready', () => {
    shell.openExternal('github.com')
})

Когда приложение запускается, оно открывается в браузере по умолчанию.githubстраница

window.open

Используется в процессе рендеринга, текущее приложение открывает страницу

window.open('github.com')

webview

использоватьwebviewМожет отображать внешний веб-контент в отдельном фрейме и обрабатывать

Вы можете использовать его непосредственно в index.html

<webview id="foo" src="https://www.github.com/" style="display:inline-flex; width:640px; height:480px"></webview>

Список модулей

shell

window.open

webview

QA

Пожалуйста, загрузите другие модули приложений и API

демонстрационное приложение

Китайская версия демо-приложения

трафарет

electron-forge

electron-forgeВключатьvue,react,AngularИ т.д. Шаблоны вне коробки.

npm i -g electron-forge
electron-forge init my-app template=react
cd my-app
npm run start 

Структура каталогов выглядит следующим образом

.compilercдаelectron-compileконфигурационный файл и.babelrcаналогичный

electron-compileэто правило преобразования, поддерживающее компиляцию js и css в приложении

electron-react-boilerplate

Если вам не нужны какие-либо инструменты и вы хотите просто построить из шаблона, шаблон react-electron можно прочитать.

electron-react-boilerplateдвойнойpackage.jsonПроект конфигурации, каталог выглядит следующим образом

electron-vue

electron-vueВ полной мере используйте vue-cli в качестве инструмента для формирования шаблонов, а также веб-пакет, электронный упаковщик или электронный сборщик с vue-loader, а также некоторые из наиболее часто используемых плагинов, таких как vue-router, vuex и т. д.

Структура каталогов выглядит следующим образом

учебник китайского языка

больше шаблонов

больше шаблоновПожалуйста, посетите

Пакет

Как упаковать наши разработанные приложения в.appили.exeИсполняемый файл, содержащий важные ссылки на упаковку, используется здесьelectron-quick-startупаковка проекта

В настоящее время существует два основных инструмента упаковки.electron-packagerа такжеelectron-builder

Упакованный установочный пакет Windows для Mac необходимо загрузитьwine

brew install wine

Если отсутствуют компоненты, загрузите их в соответствии с сообщением об ошибке.

electron-packager

electron-packagerУпакуйте свой электрон в исполняемые файлы (.app, .exe и т. д.)

воплощать в жизньnpm i electron-packager -Dустановить

electron-packager .быстрая упаковка

Детали упаковки

electron-packager <sourcedir> <appname> --platform=<platform> --arch=<arch> --out=out --icon=assets/app.ico --asar --overwrite --ignore=.git
  • каталог входа в проект sourcedir в соответствии с package.json
  • имя пакета имя приложения
  • платформа сборки платформы содержитdarwin, linux, mas, win32 all
  • архитектура сборки арки содержитia32,x64,armv7l,arm64
  • вне упакованный адрес
  • значок пакета значков
  • Генерирует ли asar app.asar или собственный исходный код
  • перезаписать перезаписывает последний пакет
  • игнорировать файлы, которые не должны быть упакованы

Скачивание бинарного пакета для первого пакета займет много времени, а перейти к кешу потом будет намного быстрее.

Упакованный каталог

вelectron-quick-startможно открыть напрямую

адрес кеша

  • Mac ~/Library/Caches/electron/
  • Windows $LOCALAPPDATA/electron/Cache or ~/AppData/Local/electron/Cache/
  • Linux $XDG_CACHE_HOME or ~/.cache/electron/

electron-builder

electron-builderЭто комплексное решение.Для электронных приложений под MacOS, Windows и Linux оно может предоставлять функции, связанные с упаковкой и сборкой. В то же время он также предоставляет встроенную поддержку «автоматического обновления».

npm i electron-builder -Dскачать

electron-builderПакет

Следующим образом

К тому же собираться в первый раз придется долго, не волнуйтесь, просто ждите хороших новостей.

будет упакован по умолчанию вdistкаталог, включая следующие

macфайл имеет运行时文件Режим по умолчанию упакован с использованием asar

electron-builder --dirБудут генерироваться только файлы пакетов, полезные для тестирования

яма яма

В первый раз, когда вы упаковываете, это будет медленнее.Если вы и я должны деньги и уходим напрямую, когда вы упаковываете его снова, поздравляю, что-то пошло не так. Сообщение об ошибке выглядит следующим образом

  • electron-builder version=20.28.2
  • loaded configuration file=package.json ("build" field)
  • description is missed in the package.json appPackageFile=/Users/shisan/Documents/self/you-app/package.json
  • writing effective config file=dist/builder-effective-config.yaml
  • no native production dependencies
  • packaging       platform=darwin arch=x64 electron=2.0.7 appOutDir=dist/mac
  • cannot unpack electron zip file, will be re-downloaded error=zip: not a valid zip file
  ⨯ zip: not a valid zip file

Error: /Users/shisan/Documents/self/you-app/node_modules/app-builder-bin/mac/app-builder exited with code 1
    at ChildProcess.childProcess.once.code (/Users/shisan/Documents/self/you-app/node_modules/builder-util/src/util.ts:254:14)
    at Object.onceWrapper (events.js:272:13)
    at ChildProcess.emit (events.js:180:13)
    at maybeClose (internal/child_process.js:936:16)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:220:5)
From previous event:
    at unpack (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/out/electron/ElectronFramework.js:191:18)
    at Object.prepareApplicationStageDirectory (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/electron/ElectronFramework.ts:148:50)
    at /Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/platformPackager.ts:179:21
    at Generator.next (<anonymous>)
From previous event:
    at MacPackager.doPack (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/platformPackager.ts:166:165)
    at /Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/macPackager.ts:88:63
    at Generator.next (<anonymous>)
From previous event:
    at MacPackager.pack (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/macPackager.ts:80:95)
    at /Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/packager.ts:376:24
    at Generator.next (<anonymous>)
    at xfs.stat (/Users/shisan/Documents/self/you-app/node_modules/fs-extra-p/node_modules/fs-extra/lib/mkdirs/mkdirs.js:56:16)
    at /Users/shisan/Documents/self/you-app/node_modules/graceful-fs/polyfills.js:287:18
    at FSReqWrap.oncomplete (fs.js:171:5)
From previous event:
    at Packager.doBuild (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/packager.ts:344:39)
    at /Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/packager.ts:314:57
    at Generator.next (<anonymous>)
    at /Users/shisan/Documents/self/you-app/node_modules/graceful-fs/graceful-fs.js:99:16
    at /Users/shisan/Documents/self/you-app/node_modules/graceful-fs/graceful-fs.js:43:10
    at FSReqWrap.oncomplete (fs.js:153:20)
From previous event:
    at Packager._build (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/packager.ts:285:133)
    at /Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/packager.ts:281:23
    at Generator.next (<anonymous>)
From previous event:
    at Packager.build (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/packager.ts:238:14)
    at build (/Users/shisan/Documents/self/you-app/node_modules/app-builder-lib/src/index.ts:58:28)
    at build (/Users/shisan/Documents/self/you-app/node_modules/electron-builder/src/builder.ts:227:10)
    at then (/Users/shisan/Documents/self/you-app/node_modules/electron-builder/src/cli/cli.ts:42:48)
    at runCallback (timers.js:763:18)
    at tryOnImmediate (timers.js:734:5)
    at processImmediate (timers.js:716:5)
From previous event:
    at Object.args [as handler] (/Users/shisan/Documents/self/you-app/node_modules/electron-builder/src/cli/cli.ts:42:48)
    at Object.runCommand (/Users/shisan/Documents/self/you-app/node_modules/yargs/lib/command.js:237:44)
    at Object.parseArgs [as _parseArgs] (/Users/shisan/Documents/self/you-app/node_modules/yargs/yargs.js:1085:24)
    at Object.get [as argv] (/Users/shisan/Documents/self/you-app/node_modules/yargs/yargs.js:1000:21)
    at Object.<anonymous> (/Users/shisan/Documents/self/you-app/node_modules/electron-builder/src/cli/cli.ts:25:28)
    at Module._compile (internal/modules/cjs/loader.js:654:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:665:10)
    at Module.load (internal/modules/cjs/loader.js:566:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:506:12)
    at Function.Module._load (internal/modules/cjs/loader.js:498:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:695:10)
    at startup (internal/bootstrap/node.js:201:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:516:3)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! you-app@1.0.0 dist: `electron-builder --mac --x64`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the you-app@1.0.0 dist script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/shisan/.npm/_logs/2018-08-22T06_28_55_102Z-debug.log
✖  Error building interactive interface

Проблема в том, что при загрузке пакета .zip операция прерывается, при дальнейшем выполнении пакета будет выдаваться ошибка, если файл (или неполный файл) не может быть найден, а кеш нужно очищается вручную. Путь кэша находится по адресу~/Library/Caches/electron/

Общие параметры

electron-builderКонфигурационный файл написан наpackage.jsonсерединаbuildв поле

"build": {
    "appId": "com.example.app", // 应用程序id 
    "productName": "测试", // 应用名称 
    "directories": {
        "buildResources": "build", // 构建资源路径默认为build
        "output": "dist" // 输出目录 默认为dist
    },
    "mac": {
        "category": "public.app-category.developer-tools", // 应用程序类别
        "target": ["dmg", "zip"],  // 目标包类型 
        "icon": "build/icon.icns" // 图标的路径
    },
    "dmg": {
        "background": "build/background.tiff or build/background.png", // 背景图像的路径
        "title": "标题",
        "icon": "build/icon.icns" // 图标路径
    },
    "win": {
        "target": ["nsis","zip"] // 目标包类型 
    }
}

категория приложения

больше параметров

Используя электронный пакет или электронный сборщик для упаковки, нет необходимости вручную упаковывать asar, эти два инструмента были интегрированы, следующее содержимое предназначено только для понимания.

asar

Введение

asarпредставляет собой формат архива, похожий на tar, который объединяет несколько файлов в один файл. Electron может читать из него произвольное содержимое файла, не распаковывая файл целиком.

использовать

Выше мы видим, что с помощьюelectron-packageПри упаковке можно добавить--asarпараметр, его функция состоит в том, чтобы упаковать наш исходный код в формат asar, если он не используется, это наш исходный код.

все еще используюelectron-quick-startшаблон, использоватьelectron-packageупаковать

Выбираем приложение в лакированном каталоге.显示包内容

Откройте путь один за другимContents -> Resources -> app

Вы можете увидеть наш исходный файл

использоватьelectron-package . --asarДля упаковки проверьте еще раз, что исходные файлы в приложении были упакованы вasarподшивать

Общие команды

  • Пакет
asar pack|p <dir> <ouput>

Такие какasar ./ app.asar

  • распаковать
asar extract|e <archive> <output>

Такие какasar e app.asar ./

На самом деле, даже если используется метод упаковки asar, наш исходный код все еще открыт, и его все равно можно легко расшифровать с помощью распаковки asar.Использование webpack для сжатия и обфускации кода — это королевский способ.

автоматическое обновление

Мы используемelectron-builderа такжеelectron-updaterзавершить автоматическое обновление приложения,не в электронеautoUpdater

обработать

Создать сертификат

Независимо от того, какой метод используется для автоматического обновления, подпись кода необходима, мы используем ее для создания локального сертификата для тестирования автоматического обновления.

Найти доступ к связке ключей в другом

Выбрать钥匙串访问 -> 证书助理 -> 创建证书, создать новый сертификат

Сделайте громкое имя, выберите тип сертификата代码签名, затем нажмите Создать

Найдите его в связке ключей после его создания

Щелкните правой кнопкой мыши, выберите «Изменить параметры доверия» и установите значение доверия始终信任

подпись кода

  • нет подписи кода

  • подпись кода

Установить переменные среды

воплощать в жизньsudo vi ~/.bash_profile, добавить переменную

export CSC_NAME="electron_update"

воплощать в жизньsource ~/.bash_profileперезагрузить файл переменных

воплощать в жизньecho $CSC_NAMEПроверьте, действует ли переменная, если нет, выполните приведенную выше команду, чтобы перезагрузить файл.

После многократной перезагрузки переменная по-прежнему не может быть получена, просто выйдите из терминала и снова войдите в терминал.

код упаковки

использоватьelectron-builderУпаковка, проектное использованиеelectron-quick-start

Сначала мы добавляем упакованныйbuildконфигурация, вpackage.jsonдобавлено в

"build": {
    "appId": "org.electron.com",
    "publish": [
      {
        "provider": "generic",
        "url": "http://172.28.86.36:8080/" 
      }
    ],
    "productName": "我的",
    "directories": {
      "output": "dist"
    },
    "mac": {
      "target": [
        "dmg",
        "zip"
      ]
    },
    "win": {
      "target": [
        "nsis",
        "zip"
      ]
    },
    "dmg": {
      "backgroundColor": "red",
      "title": "made",
      "contents": [
        {
          "x": 400,
          "y": 128,
          "type": "link",
          "path": "/Applications"
        }
      ]
    }
}

Ранее мы говорилиbuildЗначение каждого параметра в поле здесь не повторяется, а добавляется сюдаpublishполе, это информация для настройки нашего автоматического обновления, url — это адрес сервера.

сервер, который мы можем использоватьhttp-serverмодуль для быстрой сборки статического сервера

После выполнения пакета вывод

В основном смотреть наlatest-mac.ymlдокумент

можно увидетьversionполе, используемое для указания версии текущего приложения, откуда это поле?

да это нашеpackage.jsonв файлеversionполе

автоматическое обновление

Напишите следующий код в основном процессе

const {app, BrowserWindow, ipcMain} = require('electron')

const { autoUpdater } = require('electron-updater')

// 本地服务器地址
const feedURL = `http://172.28.82.40:8080/`

let mainWindow

function createWindow () { // 创建窗口
  mainWindow = new BrowserWindow({width: 800, height: 600})
  mainWindow.loadFile('index.html')

  mainWindow.on('closed', function () {
    mainWindow = null
  })
}

app.on('ready', createWindow)

app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', function () {
  if (mainWindow === null) {
    createWindow()
  }
})

// 监听自定义update事件
ipcMain.on('update', (e, arg) => {
  checkForUpdate()
})

const checkForUpdate = () => {
  // 设置检查更新的 url,并且初始化自动更新
  autoUpdater.setFeedURL(feedURL)

 // 监听错误 
  autoUpdater.on('error', message => {
    sendUpdateMessage('err', message)
  })
 // 当开始检查更新的时候触发
  autoUpdater.on('checking-for-update', message => {
    sendUpdateMessage('checking-for-update', message);
  })
 // 
  autoUpdater.on('download-progress', function(progressObj) {
    sendUpdateMessage('downloadProgress', progressObj);
  });
  // 更新下载完成事件
  autoUpdater.on('update-downloaded', function(event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {
      
      ipcMain.on('updateNow', (e, arg) => {
          autoUpdater.quitAndInstall();
      });
      sendUpdateMessage('isUpdateNow');
  });
 // 向服务端查询现在是否有可用的更新
  autoUpdater.checkForUpdates();
}

// 发送消息触发message事件
function sendUpdateMessage(message, data) {
  mainWindow.webContents.send('message', { message, data });
}

Затем измените код нашего процесса рендеринга

const {ipcRenderer} = require ('electron');
const button = document.querySelector('#button')


const ul = document.querySelector('ul')
button.onclick = () => {
  ipcRenderer.send('update')
}

ipcRenderer.on('message', (event, {message,data }) => {
  let li = document.createElement('li')
  li.innerHTML = message + " <br>data:" + JSON.stringify(data) +"<hr>";
  ul.appendChild(li)
  if (message === 'isUpdateNow') {
    if (confirm('是否现在更新?')) {
        ipcRenderer.send('updateNow');
    }
  }
})

код страницы

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    <h1>当前版本是1.0.3</h1>

    <ul>
      <li>生命周期过程展示</li>
    </ul>

    <button id="button">点击我</button>
    <script>
      // You can also require other files to run in this process
      require('./renderer.js')
    </script>
  </body>
</html>

Здесь событие нажатия кнопки используется для запуска операции обновления.

пакет напрямую, установите это1.0.3версия.

потомpackage.jsonв файлеversionполе изменено на1.0.5, измените index.html на1.0.5, упаковать.

Создайте папку в любом месте, напримерtest

Переместите упакованные файлы вtestв, выполнитьhttp-server ./, служба сборки

Когда мы нажимаем кнопку, мы можем обновить приложение, как показано ниже.

После нажатия «ОК» подождите некоторое время и откройте последнюю версию приложения после завершения обновления.

Вышеизложенное завершает автоматическое обновление файла electronic.

наконец

Пожалуйста, нажмите на все коды в этой статьеgithubпонять больше

демонстрация, связанная с распознаванием символов, заимствованная (chao) выученная (xi)Jarttoизelectron-ocr, ссылка ниже.

Ссылаться на

Общие параметры команды электронно-упаковщика

Решение проблемы подписи кода установочного пакета Electron для Mac

Электрон дяди Сунана

electron-ocr

Electron 打包Mac安装包代码签名问题解决方案Подпись, упомянутая в статье, должна быть приобретена с помощью учетной записи разработчика Apple.