Знакомство с Electron

Официальная страница проекта Electron.

Изначально Electron был разработан для редактора Atom компанией GitHub.

Electron (ранее известный как Atom Shell) позволяет нам создавать кроссплатформенные приложения, используя HTML, CSS и JavaScript. Что является большим плюсом для команд, которые занимаются веб-разработкой. Отпадает надобность искать новых разработчиков для создания десктопных версий уже существующих проектов.

Electron являет собой прекомпилированый бинарник и библиотеки, нужные для работы приложения и доступа к native API операционной системы. Он включает в себя Node.js, направленный на работу в десктопной среде, и минимальную версию браузера Chromium, контролируемого JavaScript.

Таким образом это не что иное как среда в которой будет выполнятся наше веб приложение.

На текущий момент Electron v0.35.0 включает в себя:

  • Node: 4.1.1
  • Chromium: 45.0.2454.85
  • V8: 4.5.103.294

Альтернативой для Electron является проект NW.js (ранее известный как node-webkit). О различиях можно почитать здесь.

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

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

Я предполагаю, что вы будете использовать ваш основной текстовый редактор (или IDE), и у вас установлен Node.js/npm. Я также надеюсь, что у вас есть знания HTML/CSS/JavaScript (знания Node.js не помешали бы, но не является обязательными) так что я могу не беспокоится о вашем понимании создания веб-страниц. Если же таких знаний нет, то вы, наверное, будете чувствовать себя несколько потерянными, и я рекомендую вам вначале изучить основы веб-разработки.

Итак, как же работает Electron.

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

Electron использует Chromium для отображения веб-страниц, мульти-процессорная архитектура Chromium тоже используется. Каждая веб-страница в Electron запускается в своем собственном процессе, который называется рендер процессом (renderer process).

В обычном браузере веб-страницы запускаются в закрытом окружении (так называемой песочнице) и не имеют доступ к нативным ресурсам. Пользователи Electron, однако, имеют возможность использовать Node.js API на веб-страницах, имея доступ к взаимодействию с операционной системой на низком уровне.

Исходя из того, что мы уже знаем, для создания самого простого приложения нам нужно всего три файла:

package.json
main.js
index.html

Напишем простое приложение Hello world

Наше первое приложение будет выводит информацию о версиях тех частей, которые входят в Electron.

package.json в нашем случае будет выглядеть так:

{
  "name"    : "electron-simple-app",
  "version" : "0.0.1",
  "main"    : "main.js"
}

«name»: «electron-simple-app» — это имя для вашего приложения;
«version»: «0.0.1» — это его версия, соответственно;
«main»: «main.js» — и основной скрипт.

Если поле main не будет указано в pakage.json, то по умолчанию Electron будет пытаться загрузить index.js файл.

В main.js мы должны создать окно нашего приложения и обрабатывать системные события, вот так будет выглядеть основной скрипт нашего приложения:

const electron = require('electron');
const app = electron.app;  // Модуль контролирующей жизненный цикл нашего приложения.
const BrowserWindow = electron.BrowserWindow;  // Модуль создающий браузерное окно.

// Опционально возможность отправки отчета о ошибках на сервер проекта Electron.
electron.crashReporter.start();

// Определение глобальной ссылки , если мы не определим, окно
// окно будет закрыто автоматически когда JavaScript объект будет очищен сборщиком мусора.
var mainWindow = null;

// Проверяем что все окна закрыты и закрываем приложение.
app.on('window-all-closed', function() {
  // В OS X обычное поведение приложений и их menu bar
  //  оставаться активными до тех пор пока пользователь закроет их явно комбинацией клавиш Cmd + Q
  if (process.platform != 'darwin') {
    app.quit();
  }
});

// Этот метод будет вызван когда Electron закончит инициализацию 
// и будет готов к созданию браузерных окон.
app.on('ready', function() {
  // Создаем окно браузера.
  mainWindow = new BrowserWindow({width: 800, height: 600});

  // и загружаем файл index.html нашего веб приложения.
  mainWindow.loadURL('file://' + __dirname + '/index.html');

  // Открываем DevTools.
  mainWindow.webContents.openDevTools();

  // Этот метод будет выполнен когда генерируется событие закрытия окна.
  mainWindow.on('closed', function() {
	// Удаляем ссылку на окно, если ваше приложение будет поддерживать несколько     
        // окон вы будете хранить их в массиве, это время 
        // когда нужно удалить соответствующий элемент.
    mainWindow = null;
  });
});

index.html — это веб-страница которую мы хотим отобразить:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    Мы используем Node <script>document.write(process.versions.node)</script>,
    Chrome <script>document.write(process.versions.chrome)</script>,
    и Electron <script>document.write(process.versions.electron)</script>.
  </body>
</html>

Репозиторий с кодом — https://github.com/DangelZM/electron-simple-app.

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

Для запуска приложения нам понадобится модуль electron-prebuilt.

Его мы можем с помощью npm поставить глобально или локально в наше приложение.

В случае глобальной установки для запуска приложения мы выполняем в корне нашего приложения команду:

electron .

В случае локальной установки выполняем:

./node_modules/.bin/electron .

В подготовленном мной репозитории для запуска приложения вам нужно установить зависимости:

npm install 

и запустить скрипт с помощью npm:

npm start

Пример запуска созданного приложения можно посмотреть на видео ниже:

Комментарии (26)


  1. dannyzubarev
    01.12.2015 15:30
    +1

    Прощу прощения за снобизм, но это все-таки не GitHub Electron, а просто Electron. Ранее был известен как Atom Shell.


    1. sokal32
      01.12.2015 15:41
      +2

      Formerly known as Atom Shell. Made with love by GitHub.


    1. DangelZM
      01.12.2015 15:42
      +1

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


  1. sokal32
    01.12.2015 15:40
    +5

    Дельная статья, збазибо


  1. beaverBox
    01.12.2015 15:48
    +2

    Если говорим о стандалоне прикладах, то наверное следует дополнить статью про билдер (пакер) в эти самые приложения.

    $ npm i electron-packager --save-dev
    

    // package.json
    "scripts": {
      "build": "electron-packager . MyTestApp --ignore=node_modules/electron*" //пакуем в приложение и избавляемся от лишних зависимостей
    }
    

    И, собственно, пакуем:
    $ npm run build
    


    1. DangelZM
      01.12.2015 16:01
      +1

      Спасибо за дополнение, думаю об этом буду писать отдельную статью.


    1. Antelle
      01.12.2015 16:34
      +1

      И ещё electron-builder, чтобы инсталлятор сделать.


      1. DangelZM
        01.12.2015 16:49
        +1

        Спасибо, добавлю и это в следующую статью


  1. baka_cirno
    01.12.2015 18:08
    +2

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

    Это и плюс, и минус. В качестве UI можно налепить что угодно, но очень сложно сделать так, чтобы это потом выглядело и работало как настольное приложение, а не как веб-страница в отдельном окне. Очень мало толковых вариантов для создания именно настольного UI. И разработчики Atom не спешат релизить те компоненты, которые они сами используют.
    Кто хочет писать настольные приложения на JavaScript, советую глянуть на react native desktop. Он пока нестабильный, но активно пилится.


    1. kosmonaFFFt
      02.12.2015 07:02

      ИМХО ExtJS компоненты очень похоже на десктоп выглядят. Я как то с ними баловался в десктомпном приложении (только использоват QtWebkit) — выглядело прилично.


  1. arusakov
    01.12.2015 19:58
    +2

    Укажите ссылку на первоисточник, у вас же перевод официального туториала на русский язык.


    1. arusakov
      01.12.2015 20:12

      И не нужно плодить сущности — вот официальный репозиторий (atom/electron-quick-start) для быстрого старта с абсолютно идентичным кодом.


      1. DangelZM
        01.12.2015 22:13

        Сомневаюсь в идентичности репозиториев, diff вам в помощь. По поводу первоисточника в написании статьи я использовал 4 источника включая мысли от себя. И рад, что есть люди которым этот материал оказался полезен.


  1. Methos
    01.12.2015 21:09
    -2

    file://?

    Очень хорошо. Хакеры уже ждут вас и вашу файловую систему.


    1. Kolonist
      01.12.2015 21:44
      +8

      Это же локальное приложение, оно и так имеет доступ к файловой системе.


      1. Methos
        01.12.2015 21:55
        -3

        Подробнее здесь habrahabr.ru/company/dsec/blog/272017


        1. Kolonist
          01.12.2015 22:05
          +8

          Вы не поняли. Это не виджет с изолированной областью файловой системы, это обычное десктопное приложение, разработчик которого и так имеет полный доступ к файловой системе машины, на которой запускается программа. Т.е. если не «file://», то «fs.». Это же как программа на C, C#, JavaSE, Delphi — и так есть полный доступ ко всему, это предусмотренное поведение.


          1. DangelZM
            01.12.2015 22:17
            -2

            Согласен с вашим мнением.


  1. AMar4enko
    02.12.2015 04:17

    Расскажите лучше, как собирать пакет с приложением, использующим нативные плагины.
    Делал утилиту для просмотра точек на карте Google Maps, точки грузил из SQLite. Для SQLite расширение собирается через node-gyp, вот я, помню, попрыгал. Слава богу нужно было только под одну платформу.


    1. DangelZM
      02.12.2015 10:07

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


  1. IIIEB4YK
    02.12.2015 06:54

    Если в Electron завёрнута удалённая веб-страница с X-Frame-Options: DENY, как с этим бороться? Конкретный пример с Myrrord: github.com/mikethedj4/Myrrord/issues/1


    1. DangelZM
      02.12.2015 10:11
      +1

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


  1. aramby
    04.12.2015 01:50

    Доброго времени суток) есть у этого заморского чуда, возможность задать максимальные размеры окна (max-width, max-height)?


    1. dannyzubarev
      04.12.2015 02:29
      +1

      Конечно :) Параметры `maxWidth` и `maxHeight` у BrowserWindow для установки максимальной ширины и высоты окна соответственно.

      https://github.com/atom/electron/blob/master/docs/api/browser-window.md#new-browserwindowoptions


  1. aramby
    04.12.2015 19:00
    -1

    Посоны выручайте, Electron с jQuery не хочет работать… В браузере все норм, в Electron'е devTools выдает:

    Uncaught ReferenceError: jQuery is not defined(anonymous function) @ index.html:11
    


    1. DangelZM
      04.12.2015 19:06
      +1

      Решаю проблему так

      window.$ = window.jQuery = require('../bower_components/jquery/dist/jquery.min.js');