在 Electron 渲染器进程中将 nedb 持久化到磁盘(Webpack/Electron/nedb 配置问题)
Persist nedb to disk in Electron renderer process (Webpack/Electron/nedb configuration problem)
问题
我正在尝试使用名为 nedb in an Electron renderer process. It uses the browser
field in its package.json
的纯 JS 数据库来交换基于浏览器的存储系统。这导致我的数据库实际上没有保存到文件中。
背景
我正在使用 Next.js 作为我的视图框架,其 Webpack 配置为 "target": "electron-renderer"
用于渲染线程。这显然会导致 Webpack 处理这些浏览器指令,即使渲染器进程应该可以访问浏览器和 Node API。这种行为并没有真正记录下来,所以我不知道如何覆盖它。
我试过的
我已经确认,如果我在 node_modules/nedb/package.json
的本地副本上手动编辑掉 browser
字段,问题就会消失。
作为临时解决方法,我指出了我自己的 nedb
分支可以做到这一点。但这并不令人满意。
其他研究
奇怪的是,这似乎不是 electron-vue 的问题,其文档 explicitly demonstrate use of nedb
from a renderer process. That framework does, indeed, appear to use "target": "electron-renderer"
in its Webpack config.
是否有解决此问题的方法,也许是通过 Webpack 配置?
您不需要 运行 渲染器进程上的数据库,您可以 运行 其他您想要的数据库,例如 sql、sqlite,mongodb,等等,在主进程上。
如果您不介意切换数据库,请按以下方法实现。在Electron 中存在一个class 叫作ipcMain 和ipcRenderer,这个classes 用来使renderer 进程和主进程通信。您可以 send/receive 使用 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
})
这不是您想要的,但它是一种解决方法。
想了解更多,建议你去:
正如您在问题中所述,根据 nedb
包中的 Github issue 问题的根本原因是 webpack 的文件解析过程读取 package.browser
键以便当 target
构建为 browser
或其他一些会导致其检查 package.browser
属性.
的值时,将特定文件路径别名到不同的位置
electron-vue
出现在 sidestep the webpack bundling issue by treating all NPM dependencies as externals
中,这样它们就不会被拉入应用程序包中,而是应该通过其他方式在 global
上定义。您可以类似地将 nedb
指定为您的 webpack 配置中的外部,并通过脚本标签将 Node 版本拉入您的应用程序,或者通过其他方式在 global
上定义对它的引用。
另一种解决方案是创建一个 webpack 解析器插件来覆盖 "./lib/customUtils.js"
和 "./lib/storage.js"
的问题要求如何得到解决,绕过检查 package.browser 别名的解析步骤那些文件路径。
请参阅 how to pass a custom resolver plugin in your Webpack config. See the wepback/enhanced-resolve
documentation for additional details on how plugins are defined 的 webpack 文档及其工作原理。
本质上,插件是一个带有 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]
}
}
问题
我正在尝试使用名为 nedb in an Electron renderer process. It uses the browser
field in its package.json
的纯 JS 数据库来交换基于浏览器的存储系统。这导致我的数据库实际上没有保存到文件中。
背景
我正在使用 Next.js 作为我的视图框架,其 Webpack 配置为 "target": "electron-renderer"
用于渲染线程。这显然会导致 Webpack 处理这些浏览器指令,即使渲染器进程应该可以访问浏览器和 Node API。这种行为并没有真正记录下来,所以我不知道如何覆盖它。
我试过的
我已经确认,如果我在 node_modules/nedb/package.json
的本地副本上手动编辑掉 browser
字段,问题就会消失。
作为临时解决方法,我指出了我自己的 nedb
分支可以做到这一点。但这并不令人满意。
其他研究
奇怪的是,这似乎不是 electron-vue 的问题,其文档 explicitly demonstrate use of nedb
from a renderer process. That framework does, indeed, appear to use "target": "electron-renderer"
in its Webpack config.
是否有解决此问题的方法,也许是通过 Webpack 配置?
您不需要 运行 渲染器进程上的数据库,您可以 运行 其他您想要的数据库,例如 sql、sqlite,mongodb,等等,在主进程上。
如果您不介意切换数据库,请按以下方法实现。在Electron 中存在一个class 叫作ipcMain 和ipcRenderer,这个classes 用来使renderer 进程和主进程通信。您可以 send/receive 使用 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
})
这不是您想要的,但它是一种解决方法。
想了解更多,建议你去:
正如您在问题中所述,根据 nedb
包中的 Github issue 问题的根本原因是 webpack 的文件解析过程读取 package.browser
键以便当 target
构建为 browser
或其他一些会导致其检查 package.browser
属性.
electron-vue
出现在 sidestep the webpack bundling issue by treating all NPM dependencies as externals
中,这样它们就不会被拉入应用程序包中,而是应该通过其他方式在 global
上定义。您可以类似地将 nedb
指定为您的 webpack 配置中的外部,并通过脚本标签将 Node 版本拉入您的应用程序,或者通过其他方式在 global
上定义对它的引用。
另一种解决方案是创建一个 webpack 解析器插件来覆盖 "./lib/customUtils.js"
和 "./lib/storage.js"
的问题要求如何得到解决,绕过检查 package.browser 别名的解析步骤那些文件路径。
请参阅 how to pass a custom resolver plugin in your Webpack config. See the wepback/enhanced-resolve
documentation for additional details on how plugins are defined 的 webpack 文档及其工作原理。
本质上,插件是一个带有 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]
}
}