我的目标
创建一个 React JS WEB APP,它可以通过Service Workers离线工作,并且可以在没有任何后端的情况下查询 SQlite 文件。我正在运行 Linux 操作系统。
问题
我正在为 React Js Web 应用程序上的 SQlite 使用而苦苦挣扎。我正在使用create-react-app并尝试查询 SQlite 数据库。
从 sqlite3 开始
我不能将sqlite3完全安装为 npm 包,因为它需要一个名为aws-sdk的依赖项,并且在安装此包后,它会输出以下内容:
/node_modules/sqlite3/node_modules/node-pre-gyp/lib/util/compile.js
Module not found: Can't resolve 'npm' in '/home/user/Documents/snv3/node_modules/sqlite3/node_modules/node-pre-gyp/lib/util'
./node_modules/sqlite3/node_modules/node-pre-gyp/lib/util/nw-pre-gyp/index.html 1:0
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
> <!doctype html>
| <html>
| <head>
然后......我继续寻找另一个支持sqlite的库,比如better-sqlite3
Better-Sqlite3
导入better-sqlite3后,这是我的浏览器屏幕上的输出:
TypeError: Class is undefined
exports.wrap
node_modules/babel-loader/lib/index.js??ref--6-oneOf-2!/home/user/Documents/projectFolder/node_modules/better-sqlite3/lib/util.js:14
11 | };
12 |
13 | exports.wrap = function (Class, methodName, wrapper) {
> 14 | var originalMethod = Class.prototype[methodName];
15 |
16 | if (typeof originalMethod !== 'function') {
17 | throw new TypeError("Missing method ".concat(methodName));
我不知道这应该是什么意思。库的故障排除部分没有任何内容,因此无法调试。
Kripken 的 Sql.js
让我们尝试一些内置的 Javascript 和轻量级的东西。
哦,不,我的内存堆刚刚在试图编译它时爆炸了:
Starting the development server...
<--- Last few GCs --->
tart of marking 2696 ms) (average mu = 0.196, current mu = 0.078) alloca[19981:0x317f660] 30702 ms: Mark-sweep 1387.3 (1425.7) -> 1382.8 (1424.7) MB, 2779.6 / 0.0 ms (+ 0.1 msin 91 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 2806 ms) (average mu = 0.104, current mu = 0.010) allocati[19981:0x317f660] 33503 ms: Mark-sweep 1386.7 (1424.7) -> 1385.2 (1425.7) MB, 2780.3 / 0.0 ms (average mu = 0.056, current mu = 0.007) allocation failure scavenge might not succeed
<--- JS stacktrace --->
==== JS stack trace =========================================
0: ExitFrame [pc: 0x30bcb58041bd]
Security context: 0x346742d1e789 <JSObject>
1: get [0x146f266b8549] [/home/user/Documents/projectFolder/node_modules/@babel/traverse/lib/path/index.js:~99] [pc=0x30bcb6347fd5](this=0x2c6f95aa7759 <JSFunction NodePath (sfi =0x3a532511d061)>,/* anonymous */=0xb1cce8a8af9 <Object map = 0x3450d4054639>)
2: /* anonymous */(aka /* anonymous */) [0xb1cce8a8899] [/home/user/Documents/projectFolder/node_modul...
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
1: 0x8b8210 node::Abort() [/usr/local/bin/node]
2: 0x8b825c [/usr/local/bin/node]
3: 0xac1d1e v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
4: 0xac1f38 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]
5: 0xeb11f2 [/usr/local/bin/node]
6: 0xebd14a v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/usr/local/bin/node]
7: 0xebdab4 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/usr/local/bin/node]
8: 0xec03e5 v8::internal::Heap::AllocateRawWithRetry(int, v8::internal::AllocationSpace, v8::internal::AllocationAlignment) [/usr/local/bin/node]
9: 0xe888c4 v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationSpace) [/usr/local/bin/node]
10: 0x112a2ae v8::internal::Runtime_AllocateInNewSpace(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/local/bin/node]
11: 0x30bcb58041bd
Aborted (core dumped)
好吧,忘记 sqlite 库,让我们试试 PouchDB!
当前解决方案
PouchDB
所以,在所有这些混乱之后,我已经放弃了使用 SQlite 库并尝试了一些离线友好的东西:Pouch DB。我坚信可以将 SQlite 文件加载到 Pouch。
所以我问了这个问题:在 React App 中加载带有或不带有 PouchDB 的预构建 SQlite 数据库的正确方法是什么
不,这是一个 noSQL 数据库,这是不可能的……
然后我不得不将我所有的 SQlite 数据库转换为 .json 文件,这一切都是手动完成的......
接下来,让我们创建数据库并从 .json 文件中导入数据。
编辑1:
我的 SQlite 文件每张表有接近 5k 的注册表。因此,我从 SQlite 表转换的每个 .json 文件都有 5 k 个对象或文档,如您所愿。其中有 19 个 .json 文件,每个代表一个表。
AAAAND ...我需要在 .json 文件(表)之间进行更改以进行查询,但是在文件转换之后,没有 _rev 属性,所以每次我使用 bulkDocs 加载注册表时,表之间都会发生冲突,因为他们缺少 _rev 属性。
这是我的数据库服务的代码:
import PouchDB from 'pouchdb';
import PDBFind from 'pouchdb-find';
import PDBSilverLining from 'pouchdb-silverlining';
import TableEnumerator from '../utils/tableEnumerator';
import {
Example_Table_Name
} from '../../db'
PouchDB.plugin(PDBFind);
PouchDB.plugin(PDBSilverLining);
class DbService {
constructor() {
this._db = new PouchDB('database');
}
static async dbLoad (table) {
const dbInstance = new DbService()._db
try {
const respose = await dbInstance.bulkDocs(TableEnumerator(table))
} catch(e) {
console.error(e)
}
}
static query(query) {
const dbInstance = new DbService()._db
return dbInstance.sql(query)
}
}
export default DbService;
文档示例:
表格1:
{ "_id": "table1_010101012",
"Procedure": "XXXXX",
"field4": "",
"field5": "2B",
*insert here some more irrelevant data* }
表 2:
{ "_id": "table2_0555444777",
"Procedure": "YYYYYYYYYYY",
"field4": "",
"field5": "2B",
*insert here some more irrelevant data* }
在第一次 (dbLoad(Table1)) 调用中,所有文档都被加载,_rev 属性在第一个表中创建。
当我使用 Table2.json 进行另一个调用 (dbLoad(Table2)) 时,它们会发生冲突,因为新文件缺少 _rev 属性,并且当 Pouch 创建此属性时,它们是相同的!
编辑2:
我试图将我的代码修改为:
import PDBLoad from 'pouchdb-load';
PouchDB.plugin(PDBLoad);
static async dbLoad (table) {
const db = new PouchDB(table);
try {
db.get('_local/preloaded').then(function (doc) {
}).catch(function (err) {
if (err.name !== 'not_found') {
throw err;
}
// we got a 404, so the local docuent doesn't exist. so let's preload!
return db.load('table_name.json').then(function () {
// create the local document to note that we've preloaded
return db.put({_id: '_local/preloaded'});
});
}).then(function () {
console.log({include_docs: true})
return db.allDocs({include_docs: true});
})
} catch(e) {
console.error(e)
}
}
.json 文件位于加载函数的同一目录中,但它不加载数据。
所以我坚持使用 bulkDocs 版本。
问题
对于很长的帖子,我很抱歉,在所有的上下文化之后,出现了问题:
- 是否有可能在 React Web App 环境 中设置sqlite库?
- 并且没有任何后端?
- 在我的 .json 表之间切换的推荐方式是什么?
- 我应该删除存储的前一个并加载下一个吗?
- 或手动加载每个表,然后使用袋转储cli?
我希望一切都得到很好的解释,我很乐意澄清您可能遇到的任何问题。
感谢您的时间!
可能的答案
好的,所以我能够通过创建这样的代码来解决我的问题。
import PouchDB from 'pouchdb';
import PDBFind from 'pouchdb-find';
import PDBSilverLining from 'pouchdb-silverlining';
import TableEnumerator from '../utils/tableEnumerator';
PouchDB.plugin(PDBFind);
PouchDB.plugin(PDBSilverLining);
class DbService {
static async dbLoad (table) {
const db = new PouchDB(table);
try {
await db.bulkDocs(TableEnumerator(table))
} catch(e) {
console.error(e)
}
return db
}
static async query(query, dbReference) {
return dbReference.sql(query)
}
}
export default DbService;
其中 switch 语句是表的名称并返回表文档,用于在 IndexedDB 上插入。对于每个 .json 文件,我正在创建一个新的数据库,然后进行查询,因为我正在使用 React,我正在将数据库的引用保存在组件状态上。
我认为每次我在表之间更改时都缺乏优化,我正在调用使用 bulkDocs 的函数。也许我应该检查表是否已插入 IndexedDB。