Сохранение nedb на диск в процессе рендеринга Electron (проблема конфигурации Webpack / Electron / nedb) - PullRequest
4 голосов
/ 28 марта 2019

Проблема

Я пытаюсь использовать базу данных pure-JS с именем nedb в процессе рендеринга Electron.Он использует browser поле в его package.json для обмена в системе хранения на основе браузера.Это приводит к тому, что моя база данных фактически не сохраняется в файле.

Справочная информация

Я использую Next.js в качестве моей структуры представления, и его Webpack настроен для "target": "electron-renderer" для рендеринганить.Что, очевидно, заставляет Webpack обрабатывать эти директивы браузера, хотя процессы визуализации должны иметь доступ как к браузеру, так и к Node API.Это поведение на самом деле не задокументировано, поэтому я не знаю, как его переопределить.

Что я пробовал

Я подтвердил, что если я вручную отредактирую поле browser влокальная копия node_modules/nedb/package.json, проблема исчезает.

В качестве временного решения я указал на свой собственный форк nedb, который делает это.Но это довольно неудовлетворительно.

Другое исследование

Любопытно, что это не проблема для электрон-вю, чьи документы явно демонстрируют использование nedb из процесса рендеринга.Эта платформа действительно использует "target": "electron-renderer" в своей конфигурации Webpack .

Есть ли решение этой проблемы, возможно, с помощью конфигурации Webpack?

Ответы [ 2 ]

4 голосов
/ 01 апреля 2019

Вам не нужно запускать базу данных в процессе рендеринга, вместо этого вы можете запустить другую базу данных, такую ​​как sql, sqlite, mongodb и т. Д., В главном процессе.

Если вы не против переключения базы данных, вот как вы могли бы добиться этого. В Electron существуют классы с именами ipcMain и ipcRenderer, эти классы используются для объединения процессов рендерера и основного процесса. Вы можете отправлять / получать данные любого типа с помощью ipc.

Вот пример:

Renderer.js

const btnSave = document.getElementById('btn-save')

// Get any data from forms, etc


btn.addEventListener('click', () => {
     // ipcRender sends the data via 'receive-data-to-save-in-database' channel, you
     // you can send any type of data, and have has many args you want. In this case I 
     // sent a a empty object
     ipcRenderer.send('receive-data-to-save-in-database', {})              
})

Main.js

// ipcMain listens to channel 'receive-data-to-save-in-database'
ipcMain.on('receive-data-to-save-in-database', (event, args) => {
    // Code to save in database
    // The empty object will be received in args parameter
}) 

Это не то, что вы хотели, а обходной путь.

Для получения дополнительной информации, я предлагаю вам пойти:

ipcRenderer Docs ipcMain Docs

1 голос
/ 07 апреля 2019

Как вы указали в своем вопросе и в соответствии с этим проблема Github в пакете nedb, основная причина вашей проблемы заключается в том, что процесс разрешения файлов в веб-пакете читает ключ package.browser, чтобы присвоить псевдоним конкретному файлупути к другому местоположению, когда сборка target равна browser или другому значению, которое заставит его проверять свойство package.browser.

electron-vue, по-видимому, обходит проблему связывания веб-пакетов, обработав все зависимости NPM как externals, чтобы они не попали в комплект приложения и вместо этого, как ожидается, будут определены в global другими способами.Аналогичным образом можно указать nedb в качестве внешнего в конфигурации веб-пакета и вставить версию Node в свое приложение с помощью тега script или определить ссылку на него в global другим способом.

Другое решение будетсоздайте плагин распознавателя веб-пакетов, чтобы переопределить, как проблематично требуются для разрешения "./lib/customUtils.js" и "./lib/storage.js", минуя этап разрешения, который проверяет package.browser на наличие псевдонимов для этих путей к файлам.

См. Документацию веб-пакета для , как передать пользовательский плагин распознавателя в конфигурацию вашего веб-пакета.См. wepback/enhanced-resolve документацию для получения дополнительной информации о , как определяются плагины и как они работают.

По сути, плагин - это объект с методом apply, который принимает экземпляр resolver и выполняет какой-то этап процесса разрешения файла.В приведенном ниже примере мы проверяем, находится ли текущий разрешаемый файл в пакете nedb и является ли он одним из двух проблемных псевдонимов браузера.Если это так, мы выходим из процесса разрешения с правильными путями к файлам.В противном случае мы ничего не делаем и откладываем нормальный процесс разрешения.

// Prevents nedb from substituting browser storage when running from the
// Electron renderer thread.
const fixNedbForElectronRenderer = {
  apply(resolver) {
    resolver
      // Plug in after the description file (package.json) has been
      // identified for the import, which makes sure we're not getting
      // mixed up with a different package.
      .getHook("beforeDescribed-relative")
      .tapAsync(
        "FixNedbForElectronRenderer",
        (request, resolveContext, callback) => {
          // When a require/import matches the target files, we
          // short-circuit the Webpack resolution process by calling the
          // callback with the finalized request object -- meaning that
          // the `path` is pointing at the file that should be imported.
          const isNedbImport = request.descriptionFileData["name"] === "nedb"

          if (isNedbImport && /storage(\.js)?/.test(request.path)) {
            const newRequest = Object.assign({}, request, {
              path: resolver.join(
                request.descriptionFileRoot,
                "lib/storage.js"
              )
            })
            callback(null, newRequest)
          } else if (
            isNedbImport &&
            /customUtils(\.js)?/.test(request.path)
          ) {
            const newRequest = Object.assign({}, request, {
              path: resolver.join(
                request.descriptionFileRoot,
                "lib/customUtils.js"
              )
            })
            callback(null, newRequest)
          } else {
            // Calling `callback` with no parameters proceeds with the
            // normal resolution process.
            return callback()
          }
        }
      )
  }
}

// Register the resolver plugin in the webpack config
const config = {
  resolve: {
    plugins: [fixNedbForElectronRenderer]
  }
}
...