#javascript #webpack #electron #next.js #nedb
#javascript #веб-пакет #electron #next.js #nedb #webpack
Вопрос:
Проблема
Я пытаюсь использовать базу данных на чистом JS под названием nedb в процессе электронной визуализации. Он использует browser
поле в its package.json
для подкачки в браузерной системе хранения. Это приводит к тому, что моя база данных фактически не сохраняется в файле.
Предыстория
Я использую Next.js как моя платформа просмотра, и ее веб-пакет настроен для "target": "electron-renderer"
потока рендеринга. Что, по-видимому, заставляет Webpack обрабатывать эти директивы браузера, хотя процессы визуализации должны иметь доступ как к API браузера, так и к API узла. Это поведение на самом деле не задокументировано, поэтому я не знаю, как его переопределить.
Что я пробовал
Я подтвердил, что если я вручную отредактирую browser
поле в локальной копии node_modules/nedb/package.json
, проблема исчезнет.
В качестве временного обходного пути я указал на свой собственный форк nedb
, который делает это. Но это довольно неудовлетворительно.
Другие исследования
Любопытно, что это, похоже, не является проблемой для electron-vue, чьи документы явно демонстрируют использование nedb
процесса рендеринга. Этот фреймворк, действительно, используется "target": "electron-renderer"
в конфигурации Webpack.
Есть ли решение этой проблемы, возможно, с помощью конфигурации Webpack?
Комментарии:
1. У вас есть какой-нибудь код, на который мы можем посмотреть?
2. @customcommander Насколько я могу судить, проблема возникает, если вы создаете проект Electron, который пытается создать хранилище данных nedb из процесса рендеринга. Я думаю, проблема действительно сводится к тому, что ни Webpack, ни nedb не предвидели существование среды браузера с доступом к файлам через Node. Есть предложения о том, что было бы наиболее полезным с точки зрения примера кода? На мой взгляд, весь пример проекта кажется излишним, потому что на самом деле мы говорим о разрозненных записях конфигурации.
3. Достаточно справедливо. Я посмотрю.
Ответ №1:
Вам не нужно запускать базу данных в процессе рендеринга, вместо этого вы можете запустить другую базу данных, которую вы хотели бы, например 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
})
Это не то, что вы хотели, но это обходной путь.
Для получения дополнительной информации я предлагаю вам перейти:
Комментарии:
1. Спасибо за мысли! Я понимаю, что на самом деле не так уж хорошо запускать такие вещи, как базы данных, в основном процессе (см. medium.freecodecamp.org /… и github.com/louischatriot/nedb/issues/531#issuecomment-477769752 ). Я также стремлюсь упростить задачу с точки зрения отладки, оставаясь в одном потоке во время разработки моего прототипа. Наконец, я предпочитаю
nedb
, потому что это чистый JS.
Ответ №2:
Как вы указали в своем вопросе и в соответствии с этой проблемой Github в nedb
пакете, основная причина вашей проблемы заключается в том, что процесс разрешения файлов webpack считывает package.browser
ключ, чтобы присвоить псевдоним определенным путям к файлам в другое местоположение при target
сборке browser
, или какое-либо другое значение, которое заставит его проверять package.browser
свойство.
electron-vue
похоже, что это позволяет обойти проблему связывания webpack, рассматривая все зависимости NPM как externals
, чтобы они не попадали в пакет приложений, а вместо этого, как ожидается, определялись на global
некоторыми другими средствами. Вы могли бы аналогичным образом обозначить nedb
как внешний в своей конфигурации webpack и перенести версию узла в свое приложение с помощью тега script или определить ссылку на него global
каким-либо другим способом.
Другим решением было бы создать плагин webpack resolver для переопределения того, как проблема требует "./lib/customUtils.js"
и "./lib/storage.js"
решается, минуя этап разрешения, который проверяет package.browser на наличие псевдонимов для этих путей к файлам.
Смотрите документацию webpack о том, как передать пользовательский плагин распознавателя в вашей конфигурации Webpack. Смотрите 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 amp;amp; /storage(.js)?/.test(request.path)) {
const newRequest = Object.assign({}, request, {
path: resolver.join(
request.descriptionFileRoot,
"lib/storage.js"
)
})
callback(null, newRequest)
} else if (
isNedbImport amp;amp;
/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]
}
}