Electron: 간편한 크로스 플랫폼 데스크탑 앱
게시 됨: 2022-03-11올해 초 Github은 유명한 오픈 소스 편집기 Atom의 핵심인 Atom-Shell을 출시하고 특별한 행사를 위해 이름을 Electron 으로 변경했습니다.
Electron은 Node.js 기반 데스크톱 애플리케이션 카테고리의 다른 경쟁자들과 달리 Node.js(최신 릴리스까지 io.js)의 성능과 Chromium Engine을 결합하여 이미 잘 정립된 이 시장에 고유한 방식을 도입했습니다. 우리는 서버와 클라이언트 측 JavaScript의 최고를 제공합니다.
끊임없이 성장하는 NPM 모듈의 저장소뿐만 아니라 전체 Bower 레지스트리로 구동되는 성능이 뛰어난 데이터 기반 크로스 플랫폼 데스크톱 애플리케이션을 구축하여 모든 클라이언트 측 요구를 충족할 수 있는 세상을 상상해 보십시오.
전자를 입력합니다.
이 자습서에서는 MongoDB 개발자에게 친숙한 구문을 사용하는 경량 인메모리 데이터베이스인 Electron, Angular.js 및 Loki.js를 사용하여 간단한 암호 키체인 애플리케이션을 구축합니다.
이 응용 프로그램의 전체 소스 코드는 여기에서 사용할 수 있습니다.
이 자습서에서는 다음을 가정합니다.
- 리더의 컴퓨터에는 Node.js와 Bower가 설치되어 있습니다.
- 그들은 Node.js, Angular.js 및 MongoDB와 유사한 쿼리 구문에 익숙합니다.
상품 받기
먼저 앱을 로컬에서 테스트하려면 Electron 바이너리를 가져와야 합니다. 전역적으로 설치하여 CLI로 사용하거나 애플리케이션 경로에 로컬로 설치할 수 있습니다. 전 세계적으로 설치하는 것이 좋습니다. 그래야 우리가 개발하는 모든 앱에 대해 반복해서 설치할 필요가 없습니다.
Gulp를 사용하여 배포용 애플리케이션을 패키징하는 방법은 나중에 배울 것입니다. 이 프로세스에는 Electron 바이너리 복사가 포함되므로 애플리케이션 경로에 수동으로 설치하는 것은 거의 의미가 없습니다.
Electron CLI를 설치하기 위해 터미널에 다음 명령을 입력할 수 있습니다.
$ npm install -g electron-prebuilt
설치를 테스트하려면 electron -h
를 입력하면 Electron CLI 버전이 표시됩니다.
이 글이 작성될 당시 Electron의 버전은 0.31.2
.
프로젝트 설정
다음과 같은 기본 폴더 구조를 가정해 보겠습니다.
my-app |- cache/ |- dist/ |- src/ |-- app.js | gulpfile.js
... 여기서: - cache/ 는 앱을 빌드할 때 Electron 바이너리를 다운로드하는 데 사용됩니다. - dist/ 는 생성된 배포 파일을 포함합니다. - src/ 에는 소스 코드가 포함됩니다. - src/app.js 는 우리 애플리케이션의 진입점이 될 것입니다.
다음으로 터미널의 src/
폴더로 이동하여 앱에 대한 package.json
및 bower.json
파일을 생성합니다.
$ npm init $ bower init
이 자습서의 뒷부분에서 필요한 패키지를 설치합니다.
전자 프로세스 이해
Electron은 두 가지 유형의 프로세스를 구분합니다.
- Main Process : 애플리케이션의 진입점으로, 앱을 실행할 때마다 실행될 파일입니다. 일반적으로 이 파일은 앱의 다양한 창을 선언하며 선택적으로 Electron의 IPC 모듈을 사용하여 전역 이벤트 리스너를 정의하는 데 사용할 수 있습니다.
- 렌더러 프로세스 : 애플리케이션에서 주어진 창에 대한 컨트롤러입니다. 각 창은 자체 렌더러 프로세스를 만듭니다.
코드 명확성을 위해 각 렌더러 프로세스에 대해 별도의 파일을 사용해야 합니다. 앱의 메인 프로세스를 정의하기 위해
src/app.js
를 열고 앱을 시작하기 위한app
모듈과 앱의 다양한 창을 생성하기 위한browser-window
모듈(둘 모두 Electron 코어의 일부)을 포함합니다. 다음과 같이:
var app = require('app'), BrowserWindow = require('browser-window');
앱이 실제로 시작되면 바인딩할 수 있는 ready
이벤트가 발생합니다. 이 시점에서 앱의 기본 창을 인스턴스화할 수 있습니다.
var mainWindow = null; app.on('ready', function() { mainWindow = new BrowserWindow({ width: 1024, height: 768 }); mainWindow.loadUrl('file://' + __dirname + '/windows/main/main.html'); mainWindow.openDevTools(); });
키 포인트:
-
BrowserWindow
개체의 새 인스턴스를 만들어 새 창을 만듭니다. - 객체를 단일 인수로 사용하여 창의 기본 너비 와 높이 를 비롯한 다양한 설정을 정의할 수 있습니다.
- 창 인스턴스에는 현재 창에서 실제 HTML 파일의 내용을 로드할 수 있는
loadUrl()
메서드가 있습니다. HTML 파일은 로컬 또는 원격 일 수 있습니다. - 창 인스턴스에는 선택적
openDevTools()
메서드가 있어 디버깅 목적으로 현재 창에서 Chrome 개발자 도구의 인스턴스를 열 수 있습니다.
다음으로 코드를 약간 정리해야 합니다. src/
폴더에 windows/
폴더를 만들고 각 창에 대해 다음과 같이 하위 폴더를 만들 수 있습니다.
my-app |- src/ |-- windows/ |--- main/ |---- main.controller.js |---- main.html |---- main.view.js
... 여기서 main.controller.js
는 애플리케이션의 "서버 측" 로직을 포함하고 main.view.js
는 애플리케이션의 "클라이언트 측" 로직을 포함합니다.
main.html
파일은 단순히 HTML5 웹페이지이므로 다음과 같이 간단히 시작할 수 있습니다.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Password Keychain</title> </head> <body> <h1>Password Keychain</h1> </body> </html>
이 시점에서 앱을 실행할 준비가 되어 있어야 합니다. 테스트하기 위해 터미널의 src
폴더 루트에 다음을 입력하기만 하면 됩니다.
$ electron .
package.son 파일의
start
스크립트를 정의하여 이 프로세스를 자동화할 수 있습니다.
암호 키체인 데스크탑 앱 빌드
암호 키체인 응용 프로그램을 구축하려면 다음이 필요합니다. - 암호를 추가, 생성 및 저장하는 방법. - 암호를 복사하고 제거하는 편리한 방법입니다.
비밀번호 생성 및 저장
새 암호를 삽입하려면 간단한 형식으로 충분합니다. Electron의 여러 창 간의 통신을 보여주기 위해 "삽입" 형식을 표시할 두 번째 창을 애플리케이션에 추가하는 것으로 시작합니다. 이 창을 여러 번 열고 닫을 것이므로 필요할 때 간단히 호출할 수 있도록 메서드에 논리를 래핑해야 합니다.
function createInsertWindow() { insertWindow = new BrowserWindow({ width: 640, height: 480, show: false }); insertWindow.loadUrl('file://' + __dirname + '/windows/insert/insert.html'); insertWindow.on('closed',function() { insertWindow = null; }); }
키 포인트:
- 응용 프로그램이 시작될 때 창이 기본적으로 열리지 않도록 하려면 BrowserWindow 생성자의 options 개체에서 show 속성을 false 로 설정해야 합니다.
- 창이 닫힌 이벤트를 발생시킬 때마다 BrowserWindow 인스턴스를 파괴해야 합니다.
"삽입" 창 열기 및 닫기
아이디어는 최종 사용자가 "메인" 창에서 버튼을 클릭할 때 "삽입" 창을 트리거할 수 있다는 것입니다. 이렇게 하려면 메인 창에서 메인 프로세스로 메시지를 보내 삽입 창을 열도록 지시해야 합니다. Electron의 IPC 모듈을 사용하여 이를 달성할 수 있습니다. 실제로 IPC 모듈에는 두 가지 변형이 있습니다.
- 앱이 창에서 보낸 메시지를 구독할 수 있도록 하는 메인 프로세스용입니다.
- 하나는 렌더러 프로세스를 위한 것으로 앱이 메인 프로세스에 메시지를 보낼 수 있도록 합니다.
Electron의 통신 채널은 대부분 단방향이지만 원격 모듈을 사용하여 Renderer Process에서 Main Process의 IPC 모듈에 액세스할 수 있습니다. 또한 Main Process는 Event.sender.send() 메서드를 사용하여 이벤트가 발생한 Renderer Process에 메시지를 다시 보낼 수 있습니다.
IPC 모듈을 사용하려면 Main Process 스크립트의 다른 NPM 모듈처럼 필요합니다.
var ipc = require('ipc');
... 그런 다음 on()
메서드를 사용하여 이벤트에 바인딩합니다.
ipc.on('toggle-insert-view', function() { if(!insertWindow) { createInsertWindow(); } return (!insertWindow.isClosed() && insertWindow.isVisible()) ? insertWindow.hide() : insertWindow.show(); });
키 포인트:
- 이벤트 이름은 원하는 대로 지정할 수 있습니다. 예는 임의적입니다.
- BrowserWindow 인스턴스가 이미 생성되었는지 확인하고 생성하지 않은 경우 인스턴스화하는 것을 잊지 마십시오.
- BrowserWindow 인스턴스에는 몇 가지 유용한 메서드가 있습니다.
- isClosed() 는 창이 현재
closed
상태인지 여부에 관계없이 부울을 반환합니다. - isVisible() : 창이 현재 표시되는지 여부에 관계없이 부울을 반환합니다.
- show() / hide() : 창을 표시하거나 숨기는 편리한 메서드입니다.
- isClosed() 는 창이 현재
이제 실제로 렌더러 프로세스에서 해당 이벤트를 발생시켜야 합니다. main.view.js
라는 새 스크립트 파일을 만들고 일반 스크립트와 마찬가지로 HTML 페이지에 추가합니다.
<script src="./main.view.js"></script>
HTML
script
태그를 통해 스크립트 파일을 로드하면 클라이언트 측 컨텍스트에서 이 파일이 로드됩니다. 이것은 예를 들어 전역 변수를window.<varname>
을 통해 사용할 수 있음을 의미합니다. 서버 측 컨텍스트에서 스크립트를 로드하려면 HTML 페이지에서 직접require()
메서드를 사용할 수 있습니다.require('./main.controller.js');
.
스크립트가 클라이언트 측 컨텍스트에서 로드되더라도 Main Process에 대해 할 수 있는 것과 동일한 방식으로 Renderer Process에 대한 IPC 모듈에 계속 액세스할 수 있으며 다음과 같이 이벤트를 보낼 수 있습니다.
var ipc = require('ipc'); angular .module('Utils', []) .directive('toggleInsertView', function() { return function(scope, el) { el.bind('click', function(e) { e.preventDefault(); ipc.send('toggle-insert-view'); }); }; });
이벤트를 동기적으로 보내야 하는 경우에 사용할 수 있는 sendSync() 메서드도 있습니다.
이제 "삽입" 창을 열기 위해 해야 할 일은 일치하는 Angular 지시문이 있는 HTML 버튼을 만드는 것입니다.
<div ng-controller="MainCtrl as vm"> <button toggle-insert-view class="mdl-button"> <i class="material-icons">add</i> </button> </div>
그리고 해당 지시문을 기본 창의 Angular 컨트롤러의 종속성으로 추가합니다.
angular .module('MainWindow', ['Utils']) .controller('MainCtrl', function() { var vm = this; });
비밀번호 생성
일을 단순하게 유지하기 위해 NPM uuid
모듈을 사용하여 이 튜토리얼의 목적을 위한 비밀번호 역할을 할 고유 ID를 생성할 수 있습니다. 다른 NPM 모듈처럼 설치하고 'Utils' 스크립트에서 요구한 다음 고유 ID를 반환하는 간단한 팩토리를 생성할 수 있습니다.
var uuid = require('uuid'); angular .module('Utils', []) ... .factory('Generator', function() { return { create: function() { return uuid.v4(); } }; })
이제 삽입 뷰에 버튼을 만들고 버튼에 대한 클릭 이벤트를 수신하고 create() 메서드를 호출하는 지시문을 첨부하는 일만 남았습니다.
<!-- in insert.html --> <button generate-password class="mdl-button">generate</button>
// in Utils.js angular .module('Utils', []) ... .directive('generatePassword', ['Generator', function(Generator) { return function(scope, el) { el.bind('click', function(e) { e.preventDefault(); if(!scope.vm.formData) scope.vm.formData = {}; scope.vm.formData.password = Generator.create(); scope.$apply(); }); }; }])
비밀번호 저장
이 시점에서 비밀번호를 저장하려고 합니다. 비밀번호 항목의 데이터 구조는 매우 간단합니다.
{ "id": String "description": String, "username": String, "password": String }
따라서 선택적으로 백업을 위해 파일과 동기화할 수 있는 일종의 인메모리 데이터베이스만 있으면 됩니다. 이를 위해 Loki.js가 이상적인 후보로 보입니다. 이것은 이 애플리케이션의 목적에 필요한 것을 정확히 수행하고 그 위에 동적 보기 기능을 제공하여 MongoDB의 집계 모듈과 유사한 작업을 수행할 수 있도록 합니다.
Dynamic Views는 MongodDB의 Aggregation 모듈이 제공하는 모든 기능을 제공하지 않습니다. 자세한 내용은 설명서를 참조하십시오.
간단한 HTML 양식을 만드는 것으로 시작해 보겠습니다.
<div class="insert" ng-controller="InsertCtrl as vm"> <form name="insertForm" no-validate> <fieldset ng-disabled="!vm.loaded"> <div class="mdl-textfield"> <input class="mdl-textfield__input" type="text" ng-model="vm.formData.description" required /> <label class="mdl-textfield__label" for="description">Description...</label> </div> <div class="mdl-textfield"> <input class="mdl-textfield__input" type="text" ng-model="vm.formData.username" /> <label class="mdl-textfield__label" for="username">Username...</label> </div> <div class="mdl-textfield"> <input class="mdl-textfield__input" type="password" ng-model="vm.formData.password" required /> <label class="mdl-textfield__label" for="password">Password...</label> </div> <div class=""> <button generate-password class="mdl-button">generate</button> <button toggle-insert-view class="mdl-button">cancel</button> <button save-password class="mdl-button" ng-disabled="insertForm.$invalid">save</button> </div> </fieldset> </form> </div>
이제 양식 내용의 게시 및 저장을 처리하는 JavaScript 논리를 추가해 보겠습니다.

var loki = require('lokijs'), path = require('path'); angular .module('Utils', []) ... .service('Storage', ['$q', function($q) { this.db = new loki(path.resolve(__dirname, '../..', 'app.db')); this.collection = null; this.loaded = false; this.init = function() { var d = $q.defer(); this.reload() .then(function() { this.collection = this.db.getCollection('keychain'); d.resolve(this); }.bind(this)) .catch(function(e) { // create collection this.db.addCollection('keychain'); // save and create file this.db.saveDatabase(); this.collection = this.db.getCollection('keychain'); d.resolve(this); }.bind(this)); return d.promise; }; this.addDoc = function(data) { var d = $q.defer(); if(this.isLoaded() && this.getCollection()) { this.getCollection().insert(data); this.db.saveDatabase(); d.resolve(this.getCollection()); } else { d.reject(new Error('DB NOT READY')); } return d.promise; }; }) .directive('savePassword', ['Storage', function(Storage) { return function(scope, el) { el.bind('click', function(e) { e.preventDefault(); if(scope.vm.formData) { Storage .addDoc(scope.vm.formData) .then(function() { // reset form & close insert window scope.vm.formData = {}; ipc.send('toggle-insert-view'); }); } }); }; }])
키 포인트:
- 먼저 데이터베이스를 초기화해야 합니다. 이 프로세스에는 Loki 개체의 새 인스턴스를 만들고, 데이터베이스 파일에 대한 경로를 인수로 제공하고, 백업 파일이 존재하는지 조회하고, 필요한 경우 생성하고('Keychain' 컬렉션 포함) 다음의 내용을 로드하는 과정이 포함됩니다. 이 파일을 메모리에 저장합니다.
-
getCollection()
메서드를 사용하여 데이터베이스에서 특정 컬렉션을 검색할 수 있습니다. - 컬렉션 객체는
insert()
메서드를 포함하여 여러 메서드를 노출하여 컬렉션에 새 문서를 추가할 수 있습니다. - 데이터베이스 내용을 파일에 유지하기 위해 Loki 객체는
saveDatabase()
메서드를 노출합니다. - 문서가 저장되면 양식의 데이터를 재설정하고 Main Process에 창을 닫도록 지시하는 IPC 이벤트를 보내야 합니다.
이제 새 비밀번호를 생성하고 저장할 수 있는 간단한 양식이 생겼습니다. 이 항목을 나열하기 위해 기본 보기로 돌아가 보겠습니다.
비밀번호 나열
여기서 몇 가지 일이 일어나야 합니다.
- 컬렉션에 있는 모든 문서를 얻을 수 있어야 합니다.
- 보기를 새로 고칠 수 있도록 새 암호가 저장될 때마다 기본 보기에 알려야 합니다.
Loki 객체에서 getCollection()
메서드를 호출하여 문서 목록을 검색할 수 있습니다. 이 메서드는 해당 컬렉션에 있는 모든 문서의 단순한 배열인 data 라는 속성을 가진 객체를 반환합니다.
this.getCollection = function() { this.collection = this.db.getCollection('keychain'); return this.collection; }; this.getDocs = function() { return (this.getCollection()) ? this.getCollection().data : null; };
그런 다음 Angular 컨트롤러에서 getDocs()를 호출하고 초기화한 후 데이터베이스에 저장된 모든 비밀번호를 검색할 수 있습니다.
angular .module('MainView', ['Utils']) .controller('MainCtrl', ['Storage', function(Storage) { var vm = this; vm.keychain = null; Storage .init() .then(function(db) { vm.keychain = db.getDocs(); }); });
약간의 Angular 템플릿과 비밀번호 목록이 있습니다.
<tr ng-repeat="item in vm.keychain track by $index" class="item--{{$index}}"> <td class="mdl-data-table__cell--non-numeric">{{item.description}}</td> <td>{{item.username || 'n/a'}}</td> <td> <span ng-repeat="n in [1,2,3,4,5,6]">•</span> </td> <td> <a href="#" copy-password="{{$index}}">copy</a> <a href="#" remove-password="{{item}}">remove</a> </td> </tr>
추가된 좋은 기능은 새 암호를 삽입한 후 암호 목록을 새로 고치는 것입니다. 이를 위해 Electron의 IPC 모듈을 사용할 수 있습니다. 앞에서 언급했듯이 메인 프로세스의 IPC 모듈은 원격 모듈을 사용하여 렌더러 프로세스에서 호출되어 이를 리스너 프로세스로 전환할 수 있습니다. 다음은 main.view.js
에서 구현하는 방법에 대한 예입니다.
var remote = require('remote'), remoteIpc = remote.require('ipc'); angular .module('MainView', ['Utils']) .controller('MainCtrl', ['Storage', function(Storage) { var vm = this; vm.keychain = null; Storage .init() .then(function(db) { vm.keychain = db.getDocs(); remoteIpc.on('update-main-view', function() { Storage .reload() .then(function() { vm.keychain = db.getDocs(); }); }); }); }]);
키 포인트:
- Main Process에서 원격 IPC 모듈을 요구하려면 자체
require()
메서드를 통해 원격 모듈을 사용해야 합니다. - 그런 다음
on()
메서드를 통해 렌더러 프로세스를 이벤트 리스너로 설정하고 이러한 이벤트에 콜백 함수를 바인딩할 수 있습니다.
새 문서가 저장될 때마다 삽입 보기가 이 이벤트를 전달하는 역할을 합니다.
Storage .addDoc(scope.vm.formData) .then(function() { // refresh list in main view ipc.send('update-main-view'); // reset form & close insert window scope.vm.formData = {}; ipc.send('toggle-insert-view'); });
비밀번호 복사
일반적으로 암호를 일반 텍스트로 표시하는 것은 좋지 않습니다. 대신 최종 사용자가 특정 항목에 대한 비밀번호를 직접 복사할 수 있도록 편의 버튼을 숨기고 제공할 것입니다.
여기서 다시 Electron은 텍스트 콘텐츠뿐만 아니라 이미지 및 HTML 코드도 복사하여 붙여넣을 수 있는 쉬운 방법을 제공하는 클립보드 모듈을 제공하여 우리를 구해 줍니다.
var clipboard = require('clipboard'); angular .module('Utils', []) ... .directive('copyPassword', [function() { return function(scope, el, attrs) { el.bind('click', function(e) { e.preventDefault(); var text = (scope.vm.keychain[attrs.copyPassword]) ? scope.vm.keychain[attrs.copyPassword].password : ''; // atom's clipboard module clipboard.clear(); clipboard.writeText(text); }); }; }]);
생성된 암호는 간단한 문자열이므로 writeText()
메서드를 사용하여 암호를 시스템의 클립보드에 복사할 수 있습니다. 그런 다음 기본 보기 HTML을 업데이트하고 copy-password
지시문이 있는 복사 버튼을 추가하여 암호 배열의 인덱스를 제공할 수 있습니다.
<a href="#" copy-password="{{$index}}">copy</a>
비밀번호 제거
우리의 최종 사용자는 암호가 더 이상 사용되지 않는 경우 암호를 삭제할 수 있기를 원할 수도 있습니다. 이렇게 하려면 키체인 컬렉션에서 remove()
메서드를 호출하기만 하면 됩니다. 다음과 같이 'remove()' 메서드에 전체 문서를 제공해야 합니다.
this.removeDoc = function(doc) { return function() { var d = $q.defer(); if(this.isLoaded() && this.getCollection()) { // remove the doc from the collection & persist changes this.getCollection().remove(doc); this.db.saveDatabase(); // inform the insert view that the db content has changed ipc.send('reload-insert-view'); d.resolve(true); } else { d.reject(new Error('DB NOT READY')); } return d.promise; }.bind(this); };
Loki.js 문서에는 ID로 문서를 제거할 수도 있다고 나와 있지만 예상대로 작동하지 않는 것 같습니다.
데스크탑 메뉴 생성
Electron은 OS 데스크탑 환경과 원활하게 통합되어 앱에 "기본" 사용자 경험 모양과 느낌을 제공합니다. 따라서 Electron은 앱을 위한 복잡한 데스크탑 메뉴 구조를 만드는 데 전념하는 메뉴 모듈과 함께 번들로 제공됩니다.
메뉴 모듈은 방대한 주제이며 거의 자체 튜토리얼이 필요합니다. 이 모듈의 모든 기능을 알아보려면 Electron의 데스크탑 환경 통합 튜토리얼을 읽어보시기 바랍니다.
이 현재 자습서의 범위에 대해 사용자 지정 메뉴를 만들고 사용자 지정 명령을 추가하고 표준 종료 명령을 구현하는 방법을 볼 것입니다.
앱에 사용자 정의 메뉴 생성 및 할당
일반적으로 Electron 메뉴에 대한 JavaScript 로직은 앱의 메인 스크립트 파일에 속하며 여기에서 메인 프로세스가 정의됩니다. 그러나 별도의 파일로 추상화하고 원격 모듈을 통해 메뉴 모듈에 액세스할 수 있습니다.
var remote = require('remote'), Menu = remote.require('menu');
간단한 메뉴를 정의하려면 buildFromTemplate()
메서드를 사용해야 합니다.
var appMenu = Menu.buildFromTemplate([ { label: 'Electron', submenu: [{ label: 'Credits', click: function() { alert('Built with Electron & Loki.js.'); } }] } ]);
배열의 첫 번째 항목은 항상 "기본" 메뉴 항목으로 사용됩니다.
label
속성의 값은 기본 메뉴 항목에 대해별로 중요하지 않습니다. 개발 모드에서는 항상Electron
을 표시합니다. 나중에 빌드 단계에서 기본 메뉴 항목에 사용자 지정 이름을 할당하는 방법을 볼 것입니다.
마지막으로 setApplicationMenu()
메서드를 사용하여 이 사용자 지정 메뉴를 앱의 기본 메뉴로 할당해야 합니다.
Menu.setApplicationMenu(appMenu);
키보드 단축키 매핑
Electron은 Command+A
또는 Ctrl+Shift+Z
와 같이 실제 키보드 조합에 매핑되는 미리 정의된 문자열 세트인 "가속기"를 제공합니다.
Command
가속기는 Windows 또는 Linux에서 작동하지 않습니다. 암호 키체인 응용 프로그램의 경우 두 가지 명령을 제공하는File
메뉴 항목을 추가해야 합니다.
- 암호 생성 : Cmd(또는 Ctrl) + N 으로 삽입 보기를 엽니다.
- 종료 : Cmd(또는 Ctrl) + Q 로 앱을 완전히 종료합니다.
... { label: 'File', submenu: [ { label: 'Create Password', accelerator: 'CmdOrCtrl+N', click: function() { ipc.send('toggle-insert-view'); } }, { type: 'separator' // to create a visual separator }, { label: 'Quit', accelerator: 'CmdOrCtrl+Q', selector: 'terminate:' // OS X only!!! } ] } ...
키 포인트:
-
type
속성이separator
로 설정된 배열에 항목을 추가하여 시각적 구분 기호를 추가할 수 있습니다. -
CmdOrCtrl
가속기는 Mac 및 PC 키보드와 모두 호환됩니다. -
selector
속성은 OSX와만 호환됩니다!
앱 스타일링
다양한 코드 예제에서 mdl-
로 시작하는 클래스 이름에 대한 참조를 발견했을 것입니다. 이 튜토리얼의 목적을 위해 저는 Material Design Lite UI 프레임워크를 사용하기로 선택했지만 원하는 UI 프레임워크를 자유롭게 사용하십시오.
HTML5로 할 수 있는 모든 것은 Electron에서 할 수 있습니다. 앱 바이너리의 크기가 커지고 타사 라이브러리를 너무 많이 사용하는 경우 발생할 수 있는 결과적인 성능 문제를 염두에 두십시오.
배포용 전자 앱 패키징
Electron 앱을 만들었습니다. 보기에 좋고, Selenium과 WebDriver로 e2e 테스트를 작성했으며, 이를 전 세계에 배포할 준비가 되었습니다!
그러나 여전히 개인화하고 기본 "Electron"이 아닌 사용자 정의 이름을 지정하고 Mac 및 PC 플랫폼 모두에 대한 사용자 정의 응용 프로그램 아이콘을 제공할 수도 있습니다.
Gulp로 빌드하기
요즘에는 생각할 수 있는 모든 것을 위한 Gulp 플러그인이 있습니다. Google에 gulp electron
을 입력하기만 하면 gulp-electron 플러그인이 있을 것입니다!
이 플러그인은 이 튜토리얼의 시작 부분에서 자세히 설명된 폴더 구조가 유지되는 한 사용하기가 상당히 쉽습니다. 그렇지 않다면 물건을 조금 옮겨야 할 수도 있습니다.
이 플러그인은 다른 Gulp 플러그인처럼 설치할 수 있습니다.
$ npm install gulp-electron --save-dev
그런 다음 Gulp 작업을 다음과 같이 정의할 수 있습니다.
var gulp = require('gulp'), electron = require('gulp-electron'), info = require('./src/package.json'); gulp.task('electron', function() { gulp.src("") .pipe(electron({ src: './src', packageJson: info, release: './dist', cache: './cache', version: 'v0.31.2', packaging: true, platforms: ['win32-ia32', 'darwin-x64'], platformResources: { darwin: { CFBundleDisplayName: info.name, CFBundleIdentifier: info.bundle, CFBundleName: info.name, CFBundleVersion: info.version }, win: { "version-string": info.version, "file-version": info.version, "product-version": info.version } } })) .pipe(gulp.dest("")); });
키 포인트:
-
src/
폴더는 Gulpfile.js가 있는 폴더와 같거나 배포 폴더와 같은 폴더일 수 없습니다. -
platforms
배열을 통해 내보내려는 플랫폼을 정의할 수 있습니다. - Electron 바이너리가 다운로드될
cache
폴더를 정의해야 앱과 함께 패키징할 수 있습니다. - 앱의 package.json 파일 내용은
packageJson
속성을 통해 gulp 작업에 전달되어야 합니다. - 선택적
packaging
속성이 있어 생성된 앱의 zip 아카이브도 생성할 수 있습니다. - 각 플랫폼에 대해 정의할 수 있는 "플랫폼 리소스" 집합이 다릅니다.
앱 아이콘 추가
platformResources
속성 중 하나는 icon
속성으로, 앱에 대한 사용자 지정 아이콘을 정의할 수 있습니다.
"icon": "keychain.ico"
OS X에는
.icns
파일 확장자를 가진 아이콘이 필요합니다..png
파일을.ico
및.icns
로 무료로 변환할 수 있는 여러 온라인 도구가 있습니다.
결론
이 기사에서 우리는 Electron이 실제로 할 수 있는 일의 표면만 긁었습니다. Atom 또는 Slack과 같은 훌륭한 앱을 이 도구와 함께 사용할 수 있는 영감의 원천으로 생각하십시오.
이 튜토리얼이 유용했기를 바랍니다. 자유롭게 의견을 남기고 Electron에 대한 경험을 공유해 주세요!