| ページ一覧 | ブログ | twitter |  書式 | 書式(表) |

MyMemoWiki

差分

ナビゲーションに移動 検索に移動
3,421 バイト追加 、 2021年10月11日 (月) 12:15
編集の要約なし
| [[Node.js]] | [[JavaScript]] | [[TypeScript]] | [[npm]] | [[Flutter]] | [[React]] |
==Electron==
{{amazon|B07QPQ24BN}}
<pre>
npm -g i electron
</pre>
 
====package.json====
----
<pre>
{
"name": "electron_sample",
"version": "1.0.0",
"main": "main.js",
"scripts": {
"start": "electron .",
},
:
}
</pre>
})
</pre>
====package.json====
----
<pre>
{
"name": "electron_sample",
"version": "1.0.0",
"main": "main.js",
"scripts": {
"start": "electron .",
},
:
}
</pre>
 
====.gitignore====
----
]
}
</pre>
 
===Node ネイティブモジュール===
----
*https://www.electronjs.org/docs/tutorial/using-native-node-modules
<blockquote>
Node.jsのネイティブモジュールはElectronでサポートされていますが、Electronは特定のNode.jsのバイナリとは異なるアプリケーション・バイナリ・インターフェース(ABI)を持っているため(OpenSSLの代わりにChromiumのBoringSSLを使用するなどの違いがあるため)、使用するネイティブモジュールはElectron用に再コンパイルする必要があります。そうしないと、アプリを実行しようとしたときに、以下のクラスのエラーが発生します。
</blockquote>
<pre>
Error: The module '/path/to/native/module.node'
was compiled against a different Node.js version using
NODE_MODULE_VERSION $XYZ. This version of Node.js requires
NODE_MODULE_VERSION $ABC. Please try re-compiling or re-installing
the module (for instance, using `npm rebuild` or `npm install`).
</pre>
====モジュールのインストール方法====
----
いくつかの方法がある
=====インストールし、Electron向けにリビルド=====
<blockquote>
electron-rebuildパッケージを使ってElectron用にモジュールを再構築することができます。このモジュールは、Electronのバージョンを自動的に判断し、ヘッダーをダウンロードしてアプリ用のネイティブモジュールを再構築する手動ステップを処理することができます
</blockquote>
<pre>
npm install --save-dev electron-rebuild
 
# Every time you run "npm install", run this:
./node_modules/.bin/electron-rebuild
 
# If you have trouble on Windows, try:
.\node_modules\.bin\electron-rebuild.cmd
</pre>
===パッケージングと配布===
----
====[https://www.npmjs.com/package/electron-packager electron-packager]====
----
*https://webbibouroku.com/Blog/Article/electron#outline__3
<blockquote>
Electron Packagerは、Electronベースのアプリケーションのソースコードを、リネームされたElectron実行ファイルおよびサポートファイルとともに、配布可能なフォルダにバンドルするコマンドラインツールおよびNode.jsライブラリです。
</blockquote>
*install
**Globalインストールは非推奨
<pre>
npm install --save-dev electron-packager
</pre>
*コマンドラインからの使用
<pre>
npx electron-packager <sourcedir> <appname> --platform=<platform> --arch=<arch> [optional flags...]
</pre>
=====例([[Mac]])=====
[[File:electron_package.png|500px]]
<pre>
$ npx electron-packager .
</pre>
# プロジェクトディレクトリで $ npx electron-packager . を実行するだけ
# {{プロジェクト}}-darwin-x64 配下に出力
# Finderで確認
# 実行できる
=====例[[Windows]]=====
[[File:electron_package_win.png|500px]]
*[[Mac]]と同様の手順でOK
 
====[https://www.electronforge.io/ Electron Forge]====
----
*https://blog.ikappio.com/electron-forge-make-for-windows-from-macos/
*ビルド環境と同じパッケージをデフォルトで生成するようだ。
 =====[[Windows]]配布パッケージの作成=====
----
*[[Mac]] で [[Windows]]用のパッケージ出力には、monoなどインストールが必要なようなので、[[Windows]]同様の手順でパッケージを作成。
[[File:electron_forge_win.png|400px]]
 =====[[Ubuntu]]配布パッケージの作成=====
----
<pre>
</pre>
[[File:electron_forge_ubuntu.png|400px]]
 
==Electronの知識==
===プロセス===
alert(filePaths[0]);
}
</pre>
 
===ファイルを開く===
----
*コンテキストメニューからファイルを開くダイアログで選択したファイルを画面に表示
*main.js
<pre>
ipcMain.handle('open-context-menu', (ev, msg) => {
var win = BrowserWindow.getFocusedWindow();
let contextmenuTemplate = [
{
label: 'ファイルを開く', click() {
openFile(win);
}
}
];
const contextMenu = Menu.buildFromTemplate(contextmenuTemplate);
contextMenu.popup({window : win});
});
 
async function openFile(win) {
var result = await dialog.showOpenDialogSync(
win, {
properties: ['openFile'],
filters: [
{name:'text', extensions: ['txt'] },
{name:'all', extensions: ['*'] },
]
});
if (result.canceld) {
return;
}
var filePath = result[0];
var content = fs.readFileSync(filePath).toString();
win.webContents.send('open-file', content);
}
</pre>
*preload.js
<pre>
contextBridge.exposeInMainWorld(
"api",
{
openContextMenu: (type) => {
return ipcRenderer.invoke('open-context-menu', type);
},
on: (channel, callback) => {
ipcRenderer.on(channel, (event, argv)=>callback(event, argv))
}
}
);
</pre>
*index.html
<pre>
window.addEventListener('contextmenu', openContextMenu, false);
 
window.api.on('open-file', (event, content)=>{
document.getElementById('open_file').value = content;
});
</pre>
 
===ファイルを保存===
----
*main.js
<pre>
const { ipcMain, app, BrowserWindow, Menu, MenuItem, dialog } = require('electron');
const fs = require('fs');
 
ipcMain.handle('open-context-menu', (ev, msg) => {
var win = BrowserWindow.getFocusedWindow();
let contextmenuTemplate = [
{
label: 'ファイルを保存', click() {
saveFile(win);
}
},
];
 
async function saveFile(win) {
var result = await dialog.showSaveDialogSync(
win, {
properties: ['']
});
if (result.canceld) {
return;
}
var filePath = result;
var data = await win.webContents.executeJavaScript('window.document.getElementById("open_file").value');
fs.writeFileSync(filePath, data);
}
</pre>
*index.html
<pre>
<textarea id="open_file" rows="10" cols="80"></textarea>
:
function openContextMenu(e) {
e.preventDefault();
window.api.openContextMenu("hoge");
}
window.addEventListener('contextmenu', openContextMenu, false);
</pre>
 
===httpを用いてデータを取得===
----
*Node の https パッケージでは使い勝手が割るので、superagent を導入
<pre>
$ npm install --save superagent
</pre>
*index.html
<pre>
<textarea id="open_file" rows="10" cols="80"></textarea>
<input type="text" id="getHttpDataUrl" value="https://www.typea.info/blog/index.php/feed/" />
<input type="button" id="btnGetHttpData" value="get http data" />
:
async function getHttpData() {
var data = await window.api.getHttpData(document.getElementById('getHttpDataUrl').value);
document.getElementById("open_file").value = data;
}
document.getElementById("btnGetHttpData").addEventListener('click', getHttpData);
</pre>
*preload.js
<pre>
contextBridge.exposeInMainWorld(
"api",
{
getHttpData: (url) => {
return ipcRenderer.invoke('get-http-data', url);
},
}
);
</pre>
*main.js
<pre>
ipcMain.handle('get-http-data', async (ev, url) =>{
// https://www.typea.info/blog/index.php/2017/08/19/react_react_router_redux-saga_ajax/
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // 開発用証明書エラー無視
var response = await request.get(url).query().buffer();
console.log(response);
return response.res.text;
});
</pre>
*devtools-focused
*console-message
==Tips==
===ファイルを開く===
----
*コンテキストメニューからファイルを開くダイアログで選択したファイルを画面に表示
*main.js
<pre>
ipcMain.handle('open-context-menu', (ev, msg) => {
var win = BrowserWindow.getFocusedWindow();
let contextmenuTemplate = [
{
label: 'ファイルを開く', click() {
openFile(win);
}
}
];
const contextMenu = Menu.buildFromTemplate(contextmenuTemplate);
contextMenu.popup({window : win});
});
 
async function openFile(win) {
var result = await dialog.showOpenDialogSync(
win, {
properties: ['openFile'],
filters: [
{name:'text', extensions: ['txt'] },
{name:'all', extensions: ['*'] },
]
});
if (result.canceld) {
return;
}
var filePath = result[0];
var content = fs.readFileSync(filePath).toString();
win.webContents.send('open-file', content);
}
</pre>
*preload.js
<pre>
contextBridge.exposeInMainWorld(
"api",
{
openContextMenu: (type) => {
return ipcRenderer.invoke('open-context-menu', type);
},
on: (channel, callback) => {
ipcRenderer.on(channel, (event, argv)=>callback(event, argv))
}
}
);
</pre>
*index.html
<pre>
window.addEventListener('contextmenu', openContextMenu, false);
 
window.api.on('open-file', (event, content)=>{
document.getElementById('open_file').value = content;
});
</pre>
 
===ファイルを保存===
----
*main.js
<pre>
const { ipcMain, app, BrowserWindow, Menu, MenuItem, dialog } = require('electron');
const fs = require('fs');
 
ipcMain.handle('open-context-menu', (ev, msg) => {
var win = BrowserWindow.getFocusedWindow();
let contextmenuTemplate = [
{
label: 'ファイルを保存', click() {
saveFile(win);
}
},
];
 
async function saveFile(win) {
var result = await dialog.showSaveDialogSync(
win, {
properties: ['']
});
if (result.canceld) {
return;
}
var filePath = result;
var data = await win.webContents.executeJavaScript('window.document.getElementById("open_file").value');
fs.writeFileSync(filePath, data);
}
</pre>
*index.html
<pre>
<textarea id="open_file" rows="10" cols="80"></textarea>
:
function openContextMenu(e) {
e.preventDefault();
window.api.openContextMenu("hoge");
}
window.addEventListener('contextmenu', openContextMenu, false);
</pre>
 
===httpを用いてデータを取得===
----
[[File:electron_http_get.png|400px]]
*Node の https パッケージでは使い勝手が割るので、superagent を導入
<pre>
$ npm install --save superagent
</pre>
*index.html
<pre>
<textarea id="open_file" rows="10" cols="80"></textarea>
<input type="text" id="getHttpDataUrl" value="https://www.typea.info/blog/index.php/feed/" />
<input type="button" id="btnGetHttpData" value="get http data" />
:
async function getHttpData() {
var data = await window.api.getHttpData(document.getElementById('getHttpDataUrl').value);
document.getElementById("open_file").value = data;
}
document.getElementById("btnGetHttpData").addEventListener('click', getHttpData);
</pre>
*preload.js
<pre>
contextBridge.exposeInMainWorld(
"api",
{
getHttpData: (url) => {
return ipcRenderer.invoke('get-http-data', url);
},
}
);
</pre>
*main.js
<pre>
ipcMain.handle('get-http-data', async (ev, url) =>{
// https://www.typea.info/blog/index.php/2017/08/19/react_react_router_redux-saga_ajax/
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // 開発用証明書エラー無視
var response = await request.get(url).query().buffer();
console.log(response);
return response.res.text;
});
</pre>
===sqlite===
----
*https://www.virment.com/use-sqlite3-electron-vue-js/
[[File:electron_sqlite3.png|400px]]
<pre>
$ npm install --save-dev electron-rebuild
$ npm install --save sqlite3
$ ./node_modules/.bin/electron-rebuild -f -w sqlite3
</pre>
 
*main.js
<pre>
const sqlite3 = require('sqlite3');
:
var db = new sqlite3.Database(filePath);
db.serialize(() => {
db.run("create table if not exists test(id int primary key, value text)");
});
db.close();
</pre>

案内メニュー