Моя цель
Создание React JS WEB-приложения , который может работать в автономном режиме через Сервисные работники и может запрашивать файл SQlite без каких-либобэкенд .Я использую ОС Linux.
Проблема
Я борюсь с использованием SQlite в веб-приложении React Js.Я использую create-реагировать-приложение и пытаюсь запросить базу данных 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's 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.
Поэтому я задал этот вопрос: Как правильно загружать предварительно собранные базы данных SQlite с PouchDB или без него в React?Приложение
Нет, это база данных noSQL, это невозможно ...
Затем мне пришлось преобразовать всю базу данных SQlite в файлы .json, все это сделал вручную...
Далее, давайте создадим базу данных и импортируем данные из файлов .json.
Редактировать 1:
В моем файле SQlite есть что-тоблизко к 5k regstries каждой таблицы.Таким образом, каждый файл .json, который я конвертировал из таблицы SQlite, имеет 5 тыс. Объектов или документов на ваш выбор.И есть 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 создаются в первой таблице.
Когда я делаю другой вызов (dbLoad (Table2)), используя Table2.json, они конфликтуют, потому что в новом файле отсутствует атрибут _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.
Вопросы
Извините за очень длинный пост, и после всей контекстуализации возникают вопросы:
- Можно ли настроить библиотеки sqlite в среде React Web App?
- И без какого-либо бэкэнда?
- Какой рекомендуемый способ переключения между моими таблицами .json?
- Должен ли я удалить предыдущую сохраненную и загрузить следующую?
- Или загрузить каждую таблицу вручную и затем выгрузить их, используя pouch-dump-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.