Как в Electron я могу безопасно собрать свой скрипт рендерера из нескольких модулей?

Я понимаю, почему это лучшая практика не раскрывать полный API Node или Electron в процессах рендеринга. И я понимаю, как выставлять только необходимое подмножество этих API, используя сценарии предварительной загрузки.

Но чего я не понимаю, так это того, как написать логику рендерера, используя эту модель.

Мой основной скрипт BrowswerWindow должен содержать почти всю логику пользовательского интерфейса, прослушивать все события renderer.js и соответствующим образом изменять DOM страницы.

Обычно я хотел бы построить этот гигантский скрипт модульным способом, но изолированный контекст Electron означает, что Система модулей Node будет недоступна. Документы Electron предполагают, что решением может быть инструмент упаковки, такой как window или webpack. Но примеры не приведены.

(И отмечу, что в исходном коде VSCode и собственного приложения Electron Скрипка вроде бы просто пожимают плечами и включают интеграцию с Node.)

Но в идеальном случае, как это на самом деле должно работать?

Например, каждый раз, когда я хочу протестировать приложение, должен ли у меня быть скрипт для минимизации всего моего parcel контента в 3 скрипта — src, main.min.js и rederer.min.js? Поместить их, скажем, в каталог preload.min.js? Затем скопируйте мой статический контент, прежде чем запускать электрон оттуда?

Это идея, или я чего-то не понимаю?

Поиск всех неиспользуемых файлов в проекте
Поиск всех неиспользуемых файлов в проекте
Количество файлов в проекте растет по мере его развития. И если быть по-настоящему честным, их продвижение происходит в геометрической прогрессии...
Настройка шаблона Metronic с помощью Webpack и Gulp
Настройка шаблона Metronic с помощью Webpack и Gulp
Я пишу эту статью, чтобы поделиться тем, как настроить макет Metronic с помощью Sass, поскольку Metronic предоставляет так много документации, и они...
0
0
30
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам не нужно использовать веб-пакет или пакет для создания безопасного приложения Electron. Они используются для связывания вашего кода, а не для его защиты.

Трудно найти хорошую проектную документацию для Electron с лучшими практиками. Как вы уже заметили, рекомендация установить nodeIntegration на false без их реализации может сбивать с толку.

nodeIntegration можно установить на true, если вы не загружаете какой-либо удаленный контент в свой рендер. Ссылка: Не включайте интеграцию Node.js для удаленного контента. Я просто всегда устанавливаю свой false и использую свой скрипт preload.js для связи/передачи данных между основным процессом и процессом рендеринга.

Что касается того, «как написать логику рендерера с использованием этой модели», когда вы сделаете шаг назад и посмотрите на более широкую картину, она, надеюсь, станет яснее.

Вы должны думать об Electron в процессы (хотя я склонен использовать термин потоки). основной процесс и процесс рендеринга.

Как вы знаете, вы используете IPC для связи между процессами. В основных процессах и процессах рендеринга вы можете использовать события. Проблема тесной связи модулей устранена при использовании Node События с вашим основным процессом.

Теперь сценарий preload.js...

Я вижу, как многие люди пытаются получить прямой доступ к конкретным реализациям, жестко закодированным в их preload.js-скриптах. Это может стать очень сложным и очень запутанным за короткий промежуток времени.

Я придерживаюсь совсем другого подхода. Я использую только скрипт одинpreload.js для всего своего проекта. Цель моего скрипта предварительной загрузки не в том, чтобы определить/реализовать конкретные модели, а в том, чтобы использовать скрипт preload.js исключительно как канал связи. IE: имена каналов (и необязательные данные) для отправки «событий» туда и обратно между основным процессом и процессом (процессами) рендеринга. Пусть сценарии в вашем основном процессе обрабатывают конкретные реализации Electron/Node, а сценарии в вашем процессе рендеринга обрабатывают интерактивность html.

Основной процесс

Основной процесс содержит ядро ​​Electron и Node.js.

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

Чтобы облегчить работу по поиску путей, просто используйте модуль Node путь.присоединиться(...).

Используйте события Node для связи между модулями вашего приложения.

Используйте ipcMain.on(...) и ipcMain.handle(...) Electron для прослушивания событий IPC из процесса рендеринга и содержимое.отправить(...) для отправки событий IPC в ваш конкретный процесс рендеринга.

Процесс рендеринга

Процесс(ы) рендеринга содержит ваши html-представления, Javascript, чтобы сделать ваши html-представления интерактивными, и, конечно же, html-представления, связанные с CSS.

Используйте здесь модули ES6, чтобы разделить код. import в свой HTML-файл Javascript, не забывая только export о своих общедоступных функциях.

Вы можете ссылаться на все пути как на относительные пути. Любые инструменты сборки, которые вы можете использовать, должны быть в состоянии справиться с этим при правильной настройке.

Используйте ipcRender.on(...) Electron для прослушивания событий IPC от основного процесса и ipcRender.send(...) и ipcRender.invoke(...) для отправки событий IPC в основной процесс.

Чтобы легко использовать эти вышеперечисленные команды, настройте свой скрипт preload.js следующим образом.

preload.js (основной процесс)

// Import the necessary Electron components.
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;

// White-listed channels.
const ipc = {
    'render': {
        // From render to main.
        'send': [
            'message:fromRender' // Example channel name
        ],
        // From main to render.
        'receive': [
            'message:fromMain' // Example channel name
        ],
        // From render to main and back again.
        'sendReceive': [
            'message:fromRenderAndBackAgain' // Example channel name
        ]
    }
};

// Exposed protected methods in the render process.
contextBridge.exposeInMainWorld(
    // Allowed 'ipcRenderer' methods.
    'ipcRender', {
        // From render to main.
        send: (channel, args) => {
            let validChannels = ipc.render.send;
            if (validChannels.includes(channel)) {
                ipcRenderer.send(channel, args);
            }
        },
        // From main to render.
        receive: (channel, listener) => {
            let validChannels = ipc.render.receive;
            if (validChannels.includes(channel)) {
                // Deliberately strip event as it includes `sender`.
                ipcRenderer.on(channel, (event, ...args) => listener(...args));
            }
        },
        // From render to main and back again.
        invoke: (channel, args) => {
            let validChannels = ipc.render.sendReceive;
            if (validChannels.includes(channel)) {
                return ipcRenderer.invoke(channel, args);
            }
        }
    }
);

Создание названия канала белый список в скрипте preload.js обеспечивает один источник правды. Включение одного и того же (одного и единственного) скрипта preload.js в каждое созданное окно становится простым и безошибочным.

Если вам нужно, чтобы я добавил к этому ответу использование сценария preload.js в основных процессах и процессах рендеринга, просто дайте мне знать.

Ух ты! Спасибо за удивительно подробное объяснение и отличный пример общения на основе каналов! И, как я и подозревал, я действительно упустил что-то очевидное: Chromium может разрешить синтаксис ES6, что позволяет мне создавать средство визуализации для нескольких файлов. Бесконечно благодарен!

Leo Orientis 21.03.2022 21:49

Другие вопросы по теме