create-react-appを使用して単純なreactアプリを作成し、それを電子と正常に統合しました。 アクションクリエーターファイル内に電子をインポートしようとするまで、すべてがうまく機能していました。 下の行を削除すると、アプリは正常に動作します。 問題は、ipcRendererを使用して反応側から電子メインプロセスに通信できないことです。
この行により、アプリがクラッシュします。
import { ipcRenderer } from 'electron';
次のエラーが発生します。
TypeError:fs.existsSyncは関数ではありません
(無名関数)
node_modules / electronic / index.js:6
3 |
4 | var pathFile = path.join(__dirname, 'path.txt')
5 |
> 6 | if (fs.existsSync(pathFile)) {
7 | module.exports = path.join(__dirname, fs.readFileSync(pathFile, 'utf-8'))
8 | } else {
9 | throw new Error('Electron failed to install correctly, please delete node_modules/electron and try installing again')
私はグーグルでこれが電子を輸入しようとするときの一般的な問題であることを知りました。
助けてくれてありがとう
CRAは、標準のモジュール読み込み(fsを含む)を台無しにするwebpackを使用します。
webpackのElectronモードを調べて、CRAから排出することをお勧めします
GitHubの問題は、機能のリクエストとバグレポートに関するものです。Electronの使用に関する質問は、コミュニティまたはSlackChannelに送信する必要があります。
@MarshallOfSound私の間違い。
それが誰かを助けることができるならば、私は問題#7300で解決策を見つけました。
const { ipcRenderer } = window.require('electron');
これはElectronアプリを実行するときに機能することに注意してください。ただし、ブラウザー内でReactコードをテストするだけの場合は、クラッシュします(window.requireは、Electronのようにブラウザーで定義されていません)。
app.quit()にアクセスする場合は、次を使用できます。
const {app} = window.require( 'electron')。remote;
多分それは誰かを助けます...
@CiriousJokerこれらは解決策です、ありがとう!
まだwindow.require is not a function
ます。 Electron with React Starter Kit(https://github.com/kriasoft/react-starter-kit)を使用しています。 これを除いて、すべてがうまく機能しています。
ElectronアプリをWebからロードするように設定したため、アプリはローカルで実行されていません。
https://gist.github.com/holgersindbaek/68f6db82f507967a51ca75c527faeff6
私がやろうとしているのは、私のReactファイルの1つでipcRenderer
を呼び出すことです。 ただし、アプリがWebから読み込まれている場合でも、それが可能かどうかはわかりません。 助言がありますか?
@holgersindbaek
あなたと同じ船で...あなたは解決策を見つけましたか?
いいえ。ブラウザからipcRendererをロードすることはできないと確信しています。
ブラウザでReactアプリを実行している場合、それは機能しません。 Electron内で実行すると、問題ないはずです。
@Amthieuアドバイスありがとうございます。 Reactプロジェクト(React Starter Kitに基づく)をElectronで実行する方法についてはまだ疑問があります。 任意のアドバイスをいただければ幸いです。
https://discuss.atom.io/t/getting-electron-to-work-with-react-starter-kit/48594
そうです、私には解決策があります。
1)次のコードでpreload.js file
を作成します。
window.ipcRenderer = require('electron').ipcRenderer;
2) webPreferences
介してこのファイルをmain.jsにプリロードします:
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false,
preload: __dirname + '/preload.js'
}
});
3)これで、reactアプリからアクセスできるようになります。 たとえば、これは機能します:
componentDidMount() {
if (isElectron()) {
console.log(window.ipcRenderer);
window.ipcRenderer.on('pong', (event, arg) => {
this.setState({ipc: true})
})
window.ipcRenderer.send('ping')
}
}
注-これを使用する: isElectron()
関数のhttps://github.com/cheton/is-electron
@HemalRステップ3は次のようになります(現在):
componentDidMount() {
if (window.isElectron) {
console.log(window.ipcRenderer);
window.ipcRenderer.on('pong', (event, arg) => {
this.setState({ipc: true})
})
window.ipcRenderer.send('ping')
}
}
注: window.isElectron
は関数ではありません。
@ nparsons08
謝罪-isElectronを取得している場所に追加する必要があり、次のリンクを使用してコード例を編集しました: https :
@holgersindbaek
今解決策はありますか
私にとっては、 nodeIntegration
がtrue
場合にのみ機能します。
webPreferences: {
nodeIntegration: true,
preload: __dirname + '/preload.js'
}
@HemalRソリューションで
今、FROM電子をReactに送る方法は?
で試した
電子側
ipcMain.emit("pong", "Hello!");
しかし、Reactリスナーからは何も受信されませんでした
window.ipcRenderer.on("pong", (event, arg) => {
console.log("PONG");
});
ipcMain.emit()を使用するのは正しいですか、それとも他のものを使用する必要がありますか?
わかりました、私は(電子メインプロセスで)使用する必要があることがわかりました
mainWindow.webContents.send("pong", "Hello!");
皆さんありがとうございます!
私は上記のすべてを無駄に試しました。 私のために働いたのは巨大なハックでした。 ファイル./node_modules/electron/index.js
を変更し、パスをelectron.exe
ハードコーディングします
例えば
function getElectronPath() {
return 'D:\\Repos\\MyProject\\node_modules\\electron\\dist\\electron.exe';
}
module.exports = getElectronPath();
うわー、私はIPCendererを私のReactコンポーネントで動作させることができませんでした。 上記のすべての方法を試しました。 ちなみに、それが機能するために使用できるヒントはありましたか? ありがとう
うーん...私のelectronアプリは、上記のソリューションを使用しても問題なく動作しますが、数か月間更新していません(更新する必要はありません)。
これが機能しなくなるような重大な変更があるのだろうか? たぶんあなたたちはあなたの電子バージョンを投稿することができますか?
@cyclonstepあなたが得ていた特定のエラーはありますか? コードスニペットまたはいくつかのログなしで助けるのは難しい...
束ねるのに小包を使っています。
Window.requireも私のためにそれを解決しました(また、何が解決しなかったかを示しています):
'vue / dist /vue.min'からVueをインポートします
'./App'からアプリをインポートします// 悪い? 'electron'から{ipcRenderer}をインポートします
// 悪い? const {ipcRenderer} = require( 'electron')
// 良い:
const {ipcRenderer} = window.require( 'electron')
(同じファイルのさらに下にあるのは、電子の「ポンデモ
おそらく注目に値する:それを間違えたとしても、バンドルサイズはエレクトロンサイズ全体などで大きくなることはありません(電子を必要としない場合と比較してください。これはこれまでのところ、レンダリング側の電子インポートのみです)が、約20kbしかありません、それ自体はいくつかのシム/ラッパーコードのようで、 node_modules/electron-download/node_modules/debug/dist/debug.js
:242:ff ..から来ています。
2: [function (require, module, exports) { // shim for using process in browser var process = module.exports = {}; // cached from whatever global is present so that test runners that stub it
とにかく、物事は上記のように機能します。
ノードバージョン10.2.0
Chromeバージョン66.0.3359.181
Electronバージョン3.0.2
window.require
がメインスクリプトでエラーwindow is not defined
で機能していなかったため、 const electron = eval('require')("electron")
に切り替えました。 これが誰かを助けることを願っています。 webpackを使用していて、問題はwebpackがコンパイル時にrequireステートメントを評価していたことでした。
@MarshallOfSound私の間違い。
それが誰かを助けることができるならば、私は問題#7300で解決策を見つけました。
const { ipcRenderer } = window.require('electron');
これはElectronアプリを実行するときに機能することに注意してください。ただし、ブラウザー内でReactコードをテストするだけの場合は、クラッシュします(window.requireは、Electronのようにブラウザーで定義されていません)。
そしてtypescriptの場合:
import {IpcRenderer} from 'electron';
declare global {
interface Window {
require: (module: 'electron') => {
ipcRenderer: IpcRenderer
};
}
}
const { ipcRenderer } = window.require('electron');
@moshfeuあなたのソリューションは素晴らしい働きをします。 ReactプロジェクトでIpcRendererを使用するのにWebpackやBrowserfyは必要ありません。 どうもありがとうございました:D
タイプスクリプトの場合、上記の@HemalRの例を使用しますが、 nodeIntegration: true
ません: https :
そうです、私には解決策があります。
- 次のコードで
preload.js file
を作成します。window.ipcRenderer = require('electron').ipcRenderer;
webPreferences
介してこのファイルをmain.jsにプリロードします:mainWindow = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: false, preload: __dirname + '/preload.js' } });
- これで、reactアプリからアクセスできるようになります。 たとえば、これは機能します:
componentDidMount() { if (isElectron()) { console.log(window.ipcRenderer); window.ipcRenderer.on('pong', (event, arg) => { this.setState({ipc: true}) }) window.ipcRenderer.send('ping') } }
注-これを使用する:
isElectron()
関数のhttps://github.com/cheton/is-electron
と組み合わせ
https://github.com/electron/electron/issues/9920#issuecomment -447157348
私はこれを使用しました:
import { IpcRenderer } from 'electron';
declare global {
interface Window {
ipcRenderer: IpcRenderer
}
}
export const { ipcRenderer } = window;
それが誰かを助けてくれることを願っています! stenciljsで動作し、反応と角度を想像します
webpackの設定にターゲット「electron-renderer」を追加するだけです。
デフォルトのエクスポート{
..。
ターゲット:「エレクトロンレンダラー」
..。
}
こんにちは、私はCRA + Electronを使用しています。 そして、ターゲット「electron-renderer」によってプロジェクトを構築します。 ビルドフォルダにファイルをロードしている間はうまく機能しますが、URL localhost:3000
を開発してロードするとエラーが発生します。 その理由は、reactコンポーネントでノードAPIと電子APIを使用しているためだと思います。 誰かが解決策を持っていますか? ありがとう。
TypeError: fs.existsSync is not a function
ええ、 fs
apiはブラウザで利用できません。 私が状況を正しく理解している場合は、 react-scripts start
(CRAのnpm start
のデフォルトスクリプト)を使用してアプリを実行します。
これを行う正しい方法は、 electron .
を実行することです。 あなたはそれをドキュメントで見ることができます: https :
それがあなたのために働くならばLMK。 また、私のアプリでどのように機能するかを確認できます-https://github.com/moshfeu/y2mp3 (CRAで作成されていないことに注意して
こんにちは、私はCRA + Electronを使用しています。 そして、ターゲット「electron-renderer」によってプロジェクトを構築します。 ビルドフォルダにファイルをロードしている間はうまく機能しますが、URL
localhost:3000
を開発してロードするとエラーが発生します。 その理由は、reactコンポーネントでノードAPIと電子APIを使用しているためだと思います。 誰かが解決策を持っていますか? ありがとう。
TypeError: fs.existsSync is not a function
webpackの設定にターゲット「electron-renderer」を追加するだけです。
デフォルトのエクスポート{
..。
ターゲット:「エレクトロンレンダラー」
..。
}
それは私にとってもうまくいきます。
これが私のツールバージョンです:
electron-renderer
は、この電子の問題を解決するためだけのものだと思います。 window.required
ような有線構文を使用する必要はなく、入力もできなくなりました。
私の場合、ターゲットの設定に取り組みました:webpackとnodeIntegrationの「electron-rendering」:BrowserWindowオプションでtrue
今日の最後のバージョンのwebpack + electronic + reactを使用しています
TypeScript anElectronでcreate-react-appを実行しています。 私はセットアップのためにこれらの非常に良い指示に従いました。 しかし、それから私もこのエラーに遭遇しました。 私のために働く解決策は、このスレッドで言われていることの合計です:
"electron-renderer"
をtarget
として使用するようにします。 これにはrescripts
とrescript-env
を使用します。package.json
"rescripts": [
"env"
],
.rescriptsrc.js
module.exports = [require.resolve( "./ webpack.config.js")];
webpack.config.js
:
module.exports = config => {
config.target = "electron-renderer";
return config;
};
new BrowserWindow({
webPreferences: {
nodeIntegration: true
}
});
src/typings.d.ts
を追加します:declare var window: Window;
interface Window {
require: any;
}
そしてついにあなたのアプリでtheeeen
App.tsx
const { remote } = window.require("electron");
console.log(remote.getCurrentWindow());
@LukasBombach
これも機能するはずです:
declare var window: Window;
interface Window {
require: NodeRequire
}
次に、必要な定数を入力します
ありがとう!
他の人に役立つ場合に備えて、Vueに使用した手順は次のとおりです。
ブラウザウィンドウを作成するときにノード統合をWeb設定に追加して、レンダラープロセスでノード統合が有効になっていることを確認します。
new BrowserWindow({
webPreferences: {
nodeIntegration: true,
},
})
````
Configure webpack to package your application for electron renderer by adding a target to your `vue.config.js` (or wherever you set your vue settings).
```js
module.exports = {
configureWebpack: {
target: 'electron-renderer',
},
}
アプリケーション内に必要なものをインポートします。 次のように、シェルモジュールをコンポーネントにインポートしています。
import { shell } from 'electron'
まだ同じ問題を抱えている人に。 これは私がこれまでに見つけた最良の解決策です
`` `js
new BrowserWindow({
webPreferences:{
nodeIntegration:true
}
});
多くの人があなたのアプリにfs
またはipcRenderer
をインポートすることについて質問しているので、このコメントが注目されることを願っています。 これは電子アプリの一般的なニーズですが、多くの人がそれを正しく理解しておらず、時代遅れのパターンを使用していることがわかりました。 tl; dr-ノードモジュール(つまりfs
)または電子モジュール(つまりipcRenderer
)を正しい方法でインポートしないと、セキュリティの脆弱性があります。 自分だけのためにアプリを使用している場合は、おそらく安全ですが、アプリを共有または販売したい場合は、事前に読んでおく必要があります。
ソリューションに入る前に、そもそもなぜこれを行っているのかを理解することが重要です。 Electronアプリを使用すると、ノードモジュールをアプリに含めることができます。これにより、驚くべきパワーが得られますが、セキュリティ上の懸念があります。 アプリでネイティブOS(ノードなど)の機能を使用できるようにしたいのですが、悪用されたくないのです。
コメントで@raddevusによって提起された
nodeIntegration:true
オンにするだけで大丈夫です。 ただし、アプリを使用する偶発的/悪意のあるユーザーに対する保護手段として機能し、マシンにインストールされる可能性のあるマルウェアが電子アプリと相互作用して使用するのを防ぐために、nodeIntegration:false
を維持することを選択します。nodeIntegration:true
攻撃ベクトル(非常にまれですが、発生する可能性があります)!
BrowserWindowでnodeIntegration: true
を設定すると、レンダラープロセスがノードモジュールにアクセスできるようになります。 _this_を実行すると、脆弱になります。 require("fs")
とrequire("electron")
にアクセスできますが、これは、誰かがXSSの脆弱性を見つけた場合、レンダラープロセスで公開した任意のコマンドを
コンピュータ上のすべてのファイル、または本当に悪い何かを削除することを考えてください。
nodeIntegrationをtrueに設定することに加えて、アプリがwebpackを使用してアプリケーションファイルをバンドルしている可能性があります。 Webpackは特定の記号を台無しにするため、 target: 'electron-renderer'
やwebpackの外部設定などの設定でipcRenderer
)をアプリに渡すことができます。
それでも、これはアプリの設定方法以外は何も変わりません。
ipcRenderer
へのアクセスを提供するリモートモジュールを使用できます。 それは基本的に別の形の「簡単な方法」です。 だお勧めしません、プロトタイプの汚染ベクトルからの攻撃を被るのこのタイプのため、これを行うには、電子のセキュリティ勧告で。
つまり。 リモートを使用すると、誰かがjsオブジェクトのプロトタイプを変更して、マシン/アプリに大混乱をもたらす可能性があります。
@marksyzmには、完全ではありませんが、IPCを使用してipcRenderer
をレンダラープロセスに送信する、より優れたソリューションがあります。 このタイプのセットアップは、プロトタイプの汚染攻撃に対しても脆弱です。 アプリを80%使用したい場合は、この方法を使用します。おそらく、多くのリファクタリングを行う必要がないためです。
fs
/ ipcRenderer
をレンダラープロセスにインポートする正しい方法は、IPC(プロセス間通信)を使用することです。 これは、メインプロセスとレンダラープロセスの間で会話できるようにするElectronの方法です。 内訳は、次のようにアプリを表示する必要があります。
preload
プロパティがあります。 このプロパティは、 require
アクセスしてロードするjsファイルです(つまり、ipcRendererが必要になる可能性があります)contextIsolation: true
もありますが、これは、 contextBridgeを使用してipcRenderer
にアクセスできるようにします。fs
モジュールを使用できます_大まかに_これは、これらすべての手順がどのように見えるかです。
main.js
const {
app,
BrowserWindow,
ipcMain
} = require("electron");
const path = require("path");
const fs = require("fs");
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win;
async function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false, // is default value after Electron v5
contextIsolation: true, // protect against prototype pollution
enableRemoteModule: false, // turn off remote
preload: path.join(__dirname, "preload.js") // use a preload script
}
});
// Load app
win.loadFile(path.join(__dirname, "dist/index.html"));
// rest of code..
}
app.on("ready", createWindow);
ipcMain.on("toMain", (event, args) => {
fs.readFile("path/to/file", (error, data) => {
// Do something with file contents
// Send result back to renderer process
win.webContents.send("fromMain", responseObj);
});
});
preload.js
const {
contextBridge,
ipcRenderer
} = require("electron");
// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld(
"api", {
send: (channel, data) => {
// whitelist channels
let validChannels = ["toMain"];
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data);
}
},
receive: (channel, func) => {
let validChannels = ["fromMain"];
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`
ipcRenderer.on(channel, (event, ...args) => func(...args));
}
}
}
);
index.html
<!doctype html>
<html lang="en-US">
<head>
<meta charset="utf-8"/>
<title>Title</title>
</head>
<body>
<script>
window.api.receive("fromMain", (data) => {
console.log(`Received ${data} from main process`);
});
window.api.send("toMain", "some data");
</script>
</body>
</html>
少なくとも、これらの機能にはエレクトロンv7が必要だと私は信じています。
私は安全な電子アプリに関心があり、セキュリティを後付けとして考えるのではなく、セキュリティを焼き付けるための電子アプリケーションテンプレートを作成するためにsecure-electron-template
を作成しました。
上記の@reZachのコメントにpreload.jsにあり、私のAPIは
main.js
let newWindow = null;
function createWindow() {
newWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
enableRemoteModule: false,
preload: path.join(__dirname, "preload.js")
}
});
newWindow.webContents.on('did-finish-load', () => {
newWindow.webContents.send('APP_MY_INIT', { data: 'hi' });
});
}
ipcMain.on('APP_SOMETHING', (event, ...args) => {
// ...
});
ipcMain.handle('APP_SOMETHING_ELSE', (event, ...args) => {
// ...
return myVar;
});
preload.js
const { contextBridge, ipcRenderer } = require('electron');
function callIpcRenderer(method, channel, ...args) {
if (typeof channel !== 'string' || !channel.startsWith('APP_')) {
throw 'Error: IPC channel name not allowed';
}
if (['invoke', 'send'].includes(method)) {
return ipcRenderer[method](channel, ...args);
}
if ('on' === method) {
const listener = args[0];
if (!listener) throw 'Listener must be provided';
// Wrap the given listener in a new function to avoid exposing
// the `event` arg to our renderer.
const wrappedListener = (_event, ...a) => listener(...a);
ipcRenderer.on(channel, wrappedListener);
// The returned function must not return anything (and NOT
// return the value from `removeListener()`) to avoid exposing ipcRenderer.
return () => { ipcRenderer.removeListener(channel, wrappedListener); };
}
}
contextBridge.exposeInMainWorld(
'myIpcRenderer', {
invoke: (...args) => callIpcRenderer('invoke', ...args),
send: (...args) => callIpcRenderer('send', ...args),
on: (...args) => callIpcRenderer('on', ...args),
},
);
client.js
const { myIpcRenderer } = window;
const removeMyListener = myIpcRenderer.on('APP_MY_INIT', data => {
console.log(data);
myIpcRenderer.send('APP_SOMETHING', 'foo');
})
async function test() {
const result = await myIpcRenderer.invoke('APP_SOMETHING_ELSE', 'foo', 'bar');
console.log(result);
}
test();
if (/* should remove listener === true */) {
removeMyListener();
}
TypeScriptを使用している場合は、 types.d.ts
declare global {
interface Window {
myIpcRenderer: MyIpcRenderer,
}
}
export interface MyIpcRenderer {
invoke(channel: string, ...args: any[]): Promise<any>;
send(channel: string, ...args: any[]): void;
/** <strong i="22">@return</strong> A function that removes this listener. */
on(channel: string, listener: (...args: any[]) => void): () => void;
}
これをpreload.jsに入れようとすると、モジュールが見つからないというエラーが発生する理由を誰かが知っていますか?
const errorLogging = require('../renderer/utils/errorLogging');
ありがとう
@silentlightこれは電子とは関係ありませんが、会話を続けることができる独自のgithubリポジトリがありますか? ( require()
パスが正しくないようです。そのため、コードが表示されずにエラーがスローされます)。
すでにwindow.require
ソリューションがありますが、楽しみのために、私は私のものを共有します。
function magic(module){
require(module)
}
const { ipcRenderer } = magic('electron')
ESモジュールまたはCommonJS構文を使用していないため、バンドラーはモジュールをインポートしていることを識別しません。そのため、バンドルしようとしないため、エラーはスローされません。
なぜまだ誰もこれを試したことがないのだろうか😆
@ marc2332 trueですが、この魔法のラッパーによる潜在的な攻撃に直接さらされます。 それはあなたのシナリオには当てはまらないかもしれませんが、間違いなくあなたが考慮すべき懸念事項です。
@reZach正直に言うとwindow.requireがより安全である理由はわかりません。 ところで、それを行うにはもっと汚い方法があります。
const { ipcRenderer } = eval("require('electron')")
@ marc2332どちらも安全ではありません。 リモートアセットを使用している場合は、この方法でインジェクション攻撃にさらされていることに注意してください。 😄
こんにちはザック、 contextBridge
ソリューションはプロトタイプをサポートしていますか?
contextIsolation: false
使用した元のコードは、 window
関数を付加しただけです。 この関数は、返すPromise<MediaStream>
のドキュメントがcontextBridge
プロトタイプがドロップされることを言うと、私は使用したときにcontextBridge
私は空のオブジェクトを受け取ります。
プロトタイプをサポートするだけでなく、 contextIsolation: true
保証する方法はありますか?
こんにちはザック、
contextBridge
ソリューションはプロトタイプをサポートしていますか?
contextIsolation: false
使用した元のコードは、window
関数を付加しただけです。 この関数は、返すPromise<MediaStream>
のドキュメントがcontextBridge
プロトタイプがドロップされることを言うと、私は使用したときにcontextBridge
私は空のオブジェクトを受け取ります。プロトタイプをサポートするだけでなく、
contextIsolation: true
保証する方法はありますか?
いいえ、そうではありません。 チームメンバーの1人が覚えている、これは意図された動作であるというコメントを見つけようとしていましたが、見つかりませんでした。 私が言える最高のことは、Electron v8( pr 20214 )で、IPC内のオブジェクトのシリアル化に変更をもたらし(事実上、コンテキスト分離がオンの場合)、関数またはプロトタイプ。
注:関数、DOMオブジェクト、process.envやWebContentsなどの特別なNode / Electronオブジェクトなど、V8のStructured Cloneアルゴリズムでシリアル化できないオブジェクト、またはそのようなアイテムを含むオブジェクトは、古いbase :: Value-でシリアル化されます。ベースのアルゴリズム。 ただし、この動作は非推奨であり、Electron9以降で例外がスローされます。
これはおそらくあなたが聞きたかったニュースではありませんが、私が助けてくれたことを願っています。
こんにちはザック、
contextBridge
ソリューションはプロトタイプをサポートしていますか?
contextIsolation: false
使用した元のコードは、window
関数を付加しただけです。 この関数は、返すPromise<MediaStream>
のドキュメントがcontextBridge
プロトタイプがドロップされることを言うと、私は使用したときにcontextBridge
私は空のオブジェクトを受け取ります。
プロトタイプをサポートするだけでなく、contextIsolation: true
保証する方法はありますか?いいえ、そうではありません。 チームメンバーの1人が覚えている、これは意図された動作であるというコメントを見つけようとしていましたが、見つかりませんでした。 私が言える最高のことは、Electron v8( pr 20214 )で、IPC内のオブジェクトのシリアル化に変更をもたらし(事実上、コンテキスト分離がオンの場合)、関数またはプロトタイプ。
注:関数、DOMオブジェクト、process.envやWebContentsなどの特別なNode / Electronオブジェクトなど、V8のStructured Cloneアルゴリズムでシリアル化できないオブジェクト、またはそのようなアイテムを含むオブジェクトは、古いbase :: Value-でシリアル化されます。ベースのアルゴリズム。 ただし、この動作は非推奨であり、Electron9以降で例外がスローされます。
これはおそらくあなたが聞きたかったニュースではありませんが、私が助けてくれたことを願っています。
それは残念ですが、迅速な返信に感謝します。
上記の手順( @reZachと@aplumで指定)に従い、 client.js
からpreload.js
、 main.js
情報を渡します。
すべてをローカルで実行すると通信は機能しますが、 electron-builder
を実行すると、通信が切断されます。 たとえば、 setBadge()
を使用すると、ローカルで実行するとうまく機能します。 client.js
ファイルからカウントを取得し、それがcontextBridge
に渡され、次にmain.js
に渡され、 app.dock.setBadge(count)
正常に設定されていることを確認できます。 electron-builder
構築された後、Electronの通信に欠けているものはありますか?
"electron": "^8.2.3",
"electron-builder": "^22.4.0",
const { ipcMain } = electron;
app.on('ready', () => {
mainWindow = new BrowserWindow({
height: height,
width: width,
minHeight: 575,
minWidth: 900,
center: true,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
enableRemoteModule: false,
spellcheck: true,
preload: path.join(__dirname, "preload.js")
},
});
}
ipcMain.on('SEND_BADGE_COUNT', (e, count) => {
const badgeCount = count > 0 ? count : '';
app.dock.setBadge(`${badgeCount}`)
})
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld(
'setBadgeCountForElectron', {
send: (channel, data) => {
console.log(`Preload ${channel}, ${data}`)
ipcRenderer.send(channel, data)
}
}
)
const { setBadgeCountForElectron } = window;
function sendBadgeCount(count) {
!!setBadgeCountForElectron && setBadgeCountForElectron.send('SEND_BADGE_COUNT', count)
}
sendBadgeCount(count)
"name": "desktop_app",
"version": "0.1.8-beta",
"private": true,
"description": "",
"homepage": "./",
"main": "public/electron.js",
"build": {
"copyright": "Copyright © 2020 My Company",
"appId": "com.my-app.app",
"productName": "My Company",
"buildVersion": "0.0.1-beta",
"mac": {
"category": "public.app-category.utilities",
"icon": "./public/images/mac-icon.png"
},
"win": {
"icon": "./public/images/windows-icon.png"
},
"files": [
"build/**/*",
"node_modules/**/*"
],
"directories": {
"buildResources": "assets"
}
},
@SterlingChin 、私は電子チームのメンテナーではありませんが、これは電子ビルダーリポジトリに適したより良い質問かもしれません。
少し考えてみると、エレクトロンビルダーではなく、コードの問題だと思う傾向があります。
少し考えてみると、エレクトロンビルダーではなく、コードの問題だと思う傾向があります。
これをすべて期待どおりに機能させるための重要な要素が欠けていると確信しています。 ご返信ありがとうございます。 electron-builder
リポジトリで問題を開きましたが、何の牽引力も受けていません。
少し考えてみると、エレクトロンビルダーではなく、コードの問題だと思う傾向があります。
これをすべて期待どおりに機能させるための重要な要素が欠けていると確信しています。 ご返信ありがとうございます。
electron-builder
リポジトリで問題を開きましたが、何の牽引力も受けていません。
問題のあるMVPリポジトリを作成しましたか? それは時々助けになり、その過程であなたは何が起こっているのかを理解します。
@Amthieuと@CiriousJoker私はあなたを
関数addRendererTarget(config){
config.target = 'electron-renderer';
構成を返す;
}
module.exports = override(addRendererTarget); `
vuejsを使用していて、vue.config.jsにコードを追加するだけです
module.exports = {
"transpileDependencies":[
「vuetify」
]、
pluginOptions:{
electronicBuilder:{
nodeIntegration:true
}
}
}
@genilsonmmうまくいった聖なるがらくた! 私は過去3時間夢中になっています。 ありがとう!!
私のために働いたその特定の部分は
`` `javascript
pluginOptions:{
electronicBuilder:{
nodeIntegration:true
}
}、
"transpileDependencies":[
「vuetify」
]、
それは私には機能していません...しかしwindow.require( 'electron')はうまく機能しています
「window.requireは関数ではない」という問題を抱えているすべての人にとって
あなたはtuにelectronのpreoloadスクリプトを作成させました。
de electronicメインスクリプトがあるディレクトリにpreload.jsという名前のファイルを作成し、次のコードをその上に置きます。
window.require = require;
電子メインスクリプトに移動し、ウィンドウを作成するコードに次のように入力します。
win = new BrowserWindow({
幅:1280、
高さ:720、
webPreferences:{
nodeIntegration:false、
プリロード:__ dirname + '/ preload.js'
}、
})
これにより、すべての前にスクリプトをプリロードします。これにより、問題が修正されました。 私もあなたのために願っています:)
@reZachあなたの解決策は私のために働きました、しかし私は他の人々がつまずくかもしれないという間違いに気づきました(私がしたので、うわー!):
receive: (channel, func) => { let validChannels = ["fromMain"]; if (validChannels.includes(channel)) { // Deliberately strip event as it includes `sender` ipcRenderer.on(channel, (event, ...args) => fn(...args)); } }
コールバック関数を「func」として定義しますが、次に「fn」を呼び出します。これを変更すると、記述したとおりに正確に機能します。
ビッグ投稿ありがとうございます:+1:
@genilsonmm vue.config.jsを入れたら:
pluginOptions:{
electronicBuilder:{
nodeIntegration:true、
「requireが定義されていません」というエラーが表示されます:
「nodeIntegration:true」という行にコメントすると、エラーメッセージが消え、アプリが動作します。
どういう意味ですか?
@marcoippolitoこれは、webpackにバンドルされているコードがノードjsのモジュール解決方法であるrequire
を使用しようとしていることを意味していると思います。 ノード統合を無効にするとこれは利用できないため、コードを実行できません。 あなたがする必要があるのは、ターゲットブラウザにウェブパック設定を変更し(私が正しく覚えていればvar
がターゲットです)、どのコードもノードAPIを使用しておらず、エラーがなくなることを確認することです。
TypeScriptを使用している人のために、公式のNext.jsの例に良い例があります。
https://github.com/vercel/next.js/search?q=ipcRenderer&unscoped_q=ipcRenderer
preload.ts
/* eslint-disable @typescript-eslint/no-namespace */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { ipcRenderer, IpcRenderer } from 'electron'
declare global {
namespace NodeJS {
interface Global {
ipcRenderer: IpcRenderer
}
}
}
// Since we disabled nodeIntegration we can reintroduce
// needed node functionality here
process.once('loaded', () => {
global.ipcRenderer = ipcRenderer
})
index.tsx
import { useState, useEffect } from 'react'
const Home = () => {
const [input, setInput] = useState('')
const [message, setMessage] = useState(null)
useEffect(() => {
const handleMessage = (event, message) => setMessage(message)
global.ipcRenderer.on('message', handleMessage)
return () => {
global.ipcRenderer.removeListener('message', handleMessage)
}
}, [])
const handleSubmit = (event) => {
event.preventDefault()
global.ipcRenderer.send('message', input)
setMessage(null)
}
return (
<div>
<h1>Hello Electron!</h1>
</div>
)
}
export default Home
@genilsonmmうまくいった聖なるがらくた! 私は過去3時間夢中になっています。 ありがとう!!
私のために働いたその特定の部分はpluginOptions: { electronBuilder: { nodeIntegration: true } },
正解、¸记
NodeIntegrationを有効にすると、この問題も発生します。 window.requireとrequireの両方が機能しません。
+これは反応でのみ発生し、単純な電子では発生しません
最も参考になるコメント
@MarshallOfSound私の間違い。
それが誰かを助けることができるならば、私は問題#7300で解決策を見つけました。
これはElectronアプリを実行するときに機能することに注意してください。ただし、ブラウザー内でReactコードをテストするだけの場合は、クラッシュします(window.requireは、Electronのようにブラウザーで定義されていません)。