cari

Rumah  >  Soal Jawab  >  teks badan

Menggunakan preload.js dengan betul dalam Electron: Panduan komprehensif

<p>Saya cuba menggunakan modul nod (dalam kes ini <code>fs</code>) dalam proses <code>renderer</code> <pre class="brush:php;toolbar:false;">// main_window.js const fs = memerlukan('fs') tindakan fungsi() { console.log(fs) }</pre> <p><sup>Nota: Apabila saya menekan butang dalam <code>main_window</code>, fungsi <code>action</code> </sup></p> <p>Tetapi ini menghasilkan ralat: </p> <pre class="brush:php;toolbar:false;">Uncaught ReferenceError: require tidak ditakrifkan di main_window.js:1</pre> <p>Saya dapat menyelesaikan masalah ini, seperti yang dicadangkan oleh jawapan yang diterima ini, dengan menambahkan baris ini pada <kod>main.js</code> semasa memulakan <code>main_window</code> /p> <pre class="brush:php;toolbar:false;">// main.js main_window = tetingkap Pelayar baharu({ lebar: 650, ketinggian: 550, webPreferences: { nodeIntegration: benar } })</pre> Walau bagaimanapun, menurut dokumentasi, ini bukan amalan terbaik, saya harus membuat fail <code>preload.js</code> dan memuatkan modul Node ini di dalamnya, dan kemudian dalam semua <code>renderer</ kod>Seperti ini:<p><br /></p> <p><kod>main.js</code>:</p> <pre class="brush:php;toolbar:false;">main_window = new BrowserWindow({ lebar: 650, ketinggian: 550, webPreferences: { pramuat: path.join(app.getAppPath(), 'preload.js') } })</pre> <p><kod>pramuat.js</code>:</p> <pre class="brush:php;toolbar:false;">const fs = require('fs') window.test = function() { console.log(fs) }</pre> <p><kod>main_window.js</code>:</p> <pre class="brush:php;toolbar:false;">function action() { window.test() }</pre> <p>Dan ia berkesan! </p> <hr /> <p>Sekarang soalan saya ialah, bukankah berlawanan dengan intuisi bahawa saya harus menulis kebanyakan kod untuk proses <kod>penyampai</kod> dalam <kod>pramuat.js</kod> hanya mempunyai akses kepada modul Node dalam <code>pramuat.js</code>) dan kemudian panggil sahaja fungsi dalam setiap fail <code>renderer.js</code> js</code>)? Apa yang saya tidak faham di sini? </p>
P粉197639753P粉197639753456 hari yang lalu500

membalas semua(2)saya akan balas

  • P粉615829742

    P粉6158297422023-08-28 19:14:20

    Pertimbangkan contoh ini

    Tidak semua dalam dokumentasi rasmi boleh dilaksanakan secara langsung di mana-mana dalam kod. Anda mesti perlu mempunyai pemahaman ringkas tentang persekitaran dan proses.

    Persekitaran/Proses Penerangan
    Utama API lebih dekat dengan sistem pengendalian (tahap rendah). Ini termasuk sistem fail, pop timbul pemberitahuan berasaskan sistem pengendalian, bar tugas dan banyak lagi. Ini dilaksanakan melalui gabungan API teras Electron dan Node.js
    Dipramuat Terkini Lampiran untuk mengelakkan kebocoran API berkuasa yang terdapat dalam persekitaran utama. Untuk butiran lanjut, lihat Electron v12 changelog< /a> dan Isu #23506.
    Penyampai API untuk pelayar web moden seperti DOM dan JavaScript bahagian hadapan (lanjutan). Ini dicapai melalui Chromium.

    Pengasingan konteks dan penyepaduan nod

    Adegan contextIsolation nodeIntegration Catatan
    A Tiada pramuat diperlukan. Node.js tersedia dalam Utama tetapi tidak dalam Renderer.
    B true Tiada pramuat diperlukan. Node.js tersedia dalam Main dan Renderer.
    C true Memerlukan pramuat. Node.js tersedia dalam beban utama dan pramuat, tetapi tidak dalam pemapar. Lalai. Disyorkan.
    D true true Memerlukan pramuat. Node.js tersedia dalam Utama, Pramuat dan Render.

    Bagaimana cara menggunakan pramuat dengan betul?

    Anda mesti menggunakan Komunikasi Antara Proses (IPC) Electron agar proses utama dan proses pemapar berkomunikasi.

    1. Dalam proses utama, gunakan:
    2. Dalam proses pramuat, dedahkan titik akhir yang ditentukan pengguna kepada proses pemapar.
    3. Dalam proses penyampai, gunakan titik akhir yang ditentukan pengguna awam untuk:
      • Hantar mesej kepada Utama
      • Terima mesej daripada Utama

    Contoh perlaksanaan

    Utama

    /**
     * Sending messages to Renderer
     * `window` is an object which is an instance of `BrowserWindow`
     * `data` can be a boolean, number, string, object, or array
     */
    window.webContents.send( 'custom-endpoint', data );
    
    /**
     * Receiving messages from Renderer
     */
    ipcMain.handle( 'custom-endpoint', async ( event, data ) => {
        console.log( data )
    } )
    

    Dipramuat

    const { contextBridge, ipcRenderer } = require('electron')
    
    contextBridge.exposeInMainWorld( 'api', {
        send: ( channel, data ) => ipcRenderer.invoke( channel, data ),
        handle: ( channel, callable, event, data ) => ipcRenderer.on( channel, callable( event, data ) )
    } )
    

    Penyampai

    /**
     * Sending messages to Main
     * `data` can be a boolean, number, string, object, or array
     */
    api.send( 'custom-endpoint', data )
    
    /**
     * Receiving messages from Main
     */
    api.handle( 'custom-endpoint', ( event, data ) => function( event, data ) {
        console.log( data )
    }, event);
    

    Bagaimana pula dengan menggunakan Promise?

    Kekalkan komitmen anda terhadap proses/persekitaran yang sama apabila boleh. Janji anda di utama harus kekal di utama. Komitmen anda kepada penyampai juga harus kekal pada penyampai. Jangan membuat komitmen untuk melompat dari program utama kepada pramuat kepada pemapar.

    Sistem fail

    Sebahagian besar logik perniagaan anda masih harus berada di bahagian utama atau pemapar, tetapi tidak sekali-kali dalam pramuat. Ini kerana pramuat wujud hampir secara eksklusif sebagai medium. Pramuat hendaklah sangat kecil.

    Dalam kes OP , fs fs hendaklah dilaksanakan pada bahagian induk.

    balas
    0
  • P粉323374878

    P粉3233748782023-08-28 11:18:17

    Diedit 2022


    Saya telah menerbitkan artikel yang lebih besar tentang sejarah Elektron

    (Bagaimana keselamatan telah berubah dalam keluaran Elektron) dan pertimbangan keselamatan lain yang boleh diambil oleh pembangun Elektron untuk memastikan penggunaan pramuat yang betul dalam dokumen aplikasi baharu.

    Diedit 2020

    Seperti yang ditanya oleh pengguna lain, izinkan saya menerangkan jawapan saya di bawah.

    preload.js 的正确方法是在您的应用可能需要 requireDedahkan pembalut senarai putih di sekeliling mana-mana modul menggunakan

    dalam Elektron.

    require 或通过 preload.js 中的 requireDari perspektif keselamatan, mendedahkan < a href="https://github.com/electron/ Electron/issues/9920#issuecomment-575839738" rel="noreferrer"> apa sahaja yang diambil melalui panggilan adalah berbahaya (lihat ulasan saya

    untuk penjelasan lanjut sebabnya). Ini benar terutamanya jika aplikasi anda memuatkan kandungan jauh (yang dilakukan oleh banyak aplikasi).

    Untuk melakukan ini dengan betul, anda perlu menetapkan < 上启用许多选项code>BrowserWindowrequire seperti yang saya perincikan di bawah. Menetapkan pilihan ini memaksa aplikasi Electron anda untuk berkomunikasi melalui IPC (Komunikasi Antara Proses) dan mengasingkan kedua-dua persekitaran antara satu sama lain. Menyediakan aplikasi anda seperti ini membolehkan anda mengesahkan apa sahaja di bahagian belakang yang mungkin merupakan modul memerlukan

    tanpa ia diganggu oleh pelanggan.

    Di bawah, anda akan temui contoh ringkas tentang perkara yang saya perkatakan dan penampilannya dalam apl anda. Jika anda baru, saya mungkin mengesyorkan menggunakan secure-electron-templatesecure-electron-template< /a>

    (yang saya pengarangnya) untuk menggabungkan semua amalan terbaik keselamatan ini dari mula apabila membina aplikasi elektron.

    Halaman ini

    juga mempunyai maklumat yang baik tentang seni bina yang diperlukan apabila menggunakan preload.js untuk membuat aplikasi selamat.

    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);
      });
    });
    
    pramuat.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>
    

    balas
    0
  • Batalbalas