React Native에서 사용하기 위해 PouchDB 해킹
24591 단어 couchdbreactnativepouchdb
업데이트(2021/02/12)
React Native용 PouchDB@7 생성
마츠야마 타쿠야 · 2월 12일 · 4분 읽기
#pouchdb
#reactnative
안녕하세요, 여기 있습니다.
CouchDB와 데이터를 동기화해야 하는 React Native 앱을 개발 중입니다.
PouchDB 브라우저용 JavaScript로 작성된 CouchDB와 동기화할 수 있는 잘 설계된 데이터베이스는 React Native에서도 사용할 수 있습니다.
RN에서 작동하도록 react-native-sqlite-2 및 pouchdb-adapter-react-native-sqlite을 빌드했습니다.
그러나 여전히 작동하려면 몇 가지 문제가 있습니다.
예를 들어, RN이 아직
FileReader.readAsArrayBuffer
를 지원하지 않기 때문에 storing attachments에 큰 문제가 있습니다.요즘 pouchdb-react-native 프로젝트가 활동하지 않는 것 같습니다.
그래서 저는 PouchDB가 RN에서 완벽하게 실행될 수 있도록 노력했고 성공적으로 해냈습니다. 여기 내가 한 일이 있습니다.
RN에서 PouchDB를 실행하는 방법
먼저 RN에서 PouchDB를 사용하는 방법을 보여드리고자 합니다.
공식 PouchDB 핵심 모듈을 기반으로 해킹한 일부 패키지를 만들었습니다.
다음은 a working demo app 입니다.
Inkdrop이라는 프로덕션 앱에서 사용할 계획입니다.
뎁 설치
PouchDB 핵심 패키지를 설치하십시오.
npm i pouchdb-adapter-http pouchdb-mapreduce
React Native용으로 해킹된 패키지를 설치합니다.
npm i @craftzdog/pouchdb-core-react-native @craftzdog/pouchdb-replication-react-native
다음으로 SQLite3 엔진 모듈을 설치합니다.
npm i pouchdb-adapter-react-native-sqlite react-native-sqlite-2
react-native link react-native-sqlite-2
그런 다음 PouchDB에 필요한 기능을 폴리필하기 위해 일부 패키지를 설치하십시오.
npm i base-64 events
폴리필 만들기
PouchDB에 필요한 일부 기능을 폴리필하기 위해 js 파일을 만드십시오.
import {decode, encode} from 'base-64'
if (!global.btoa) {
global.btoa = encode;
}
if (!global.atob) {
global.atob = decode;
}
// Avoid using node dependent modules
process.browser = true
index.js
의 첫 번째 줄에서 가져옵니다.파우치DB 로드
pouchdb.js
를 다음과 같이 만듭니다.import PouchDB from '@craftzdog/pouchdb-core-react-native'
import HttpPouch from 'pouchdb-adapter-http'
import replication from '@craftzdog/pouchdb-replication-react-native'
import mapreduce from 'pouchdb-mapreduce'
import SQLite from 'react-native-sqlite-2'
import SQLiteAdapterFactory from 'pouchdb-adapter-react-native-sqlite'
const SQLiteAdapter = SQLiteAdapterFactory(SQLite)
export default PouchDB
.plugin(HttpPouch)
.plugin(replication)
.plugin(mapreduce)
.plugin(SQLiteAdapter)
pouchdb-find
와 같은 다른 플러그인이 필요한 경우 추가하면 됩니다.PouchDB 사용
그런 다음 평소와 같이 사용하십시오.
import PouchDB from './pouchdb'
function loadDB () {
return new PouchDB('mydb.db', { adapter: 'react-native-sqlite' })
}
내가 PouchDB를 해킹한 방법
React Native에서 작동하게 하려면 PouchDB 코어 모듈에서 호출
FileReader.readAsArrayBuffer
을 피해야 합니다.즉,
Blob
대신 항상 Base64에서 첨부 파일을 처리합니다.a few lines of code hacks 으로 할 수 있습니다.
readAsArrayBuffer가 호출되는 위치
PouchDB는
readAsArrayBuffer
를 호출해야 하는 모든 문서에 대해 MD5 다이제스트를 계산하려고 시도합니다.pouchdb-binary-utils/lib/index-browser.js
에서:72 function readAsBinaryString(blob, callback) {
73 if (typeof FileReader === 'undefined') {
74 // fix for Firefox in a web worker
75 // https://bugzilla.mozilla.org/show_bug.cgi?id=901097
76 return callback(arrayBufferToBinaryString(
77 new FileReaderSync().readAsArrayBuffer(blob)));
78 }
79
80 var reader = new FileReader();
81 var hasBinaryString = typeof reader.readAsBinaryString === 'function';
82 reader.onloadend = function (e) {
83 var result = e.target.result || '';
84 if (hasBinaryString) {
85 return callback(result);
86 }
87 callback(arrayBufferToBinaryString(result));
88 };
89 if (hasBinaryString) {
90 reader.readAsBinaryString(blob);
91 } else {
92 reader.readAsArrayBuffer(blob);
93 }
94 }
이 함수는
pouchdb-md5/lib/index-browser.js
에서 호출됩니다.24 function appendBlob(buffer, blob, start, end, callback) {
25 if (start > 0 || end < blob.size) {
26 // only slice blob if we really need to
27 blob = sliceBlob(blob, start, end);
28 }
29 pouchdbBinaryUtils.readAsArrayBuffer(blob, function (arrayBuffer) {
30 buffer.append(arrayBuffer);
31 callback();
32 });
33 }
글쎄, 그것을 피하는 방법?
첨부 파일 저장
다음과 같이
binary
에서 getAttachment
메서드의 pouchdb-core/src/adapter.js
옵션을 비활성화합니다.714 if (res.doc._attachments && res.doc._attachments[attachmentId]
715 opts.ctx = res.ctx;
716 // force it to read attachments in base64
717 opts.binary = false;
718 self._getAttachment(docId, attachmentId,
719 res.doc._attachments[attachmentId], opts, callback);
720 } else {
이 변경으로 인해 항상 base64로 인코딩된 첨부 파일을 받게 됩니다.
풀 복제
다음과 같이
pouchdb-replication/lib/index.js
의 원격 데이터베이스에서 첨부 파일을 가져올 때 Blob을 base64로 변환해야 합니다.function getDocAttachmentsFromTargetOrSource(target, src, doc) {
var doCheckForLocalAttachments = pouchdbUtils.isRemote(src) && !pouchdbUtils.isRemote(target);
var filenames = Object.keys(doc._attachments);
function convertBlobToBase64(attachments) {
return Promise.all(attachments.map(function (blob) {
if (typeof blob === 'string') {
return blob
} else {
return new Promise(function (resolve, reject) {
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function() {
const uri = reader.result;
const pos = uri.indexOf(',')
const base64 = uri.substr(pos + 1)
resolve(base64)
}
});
}
}));
}
if (!doCheckForLocalAttachments) {
return getDocAttachments(src, doc)
.then(convertBlobToBase64);
}
return target.get(doc._id).then(function (localDoc) {
return Promise.all(filenames.map(function (filename) {
if (fileHasChanged(localDoc, doc, filename)) {
return src.getAttachment(doc._id, filename);
}
return target.getAttachment(localDoc._id, filename);
}))
.then(convertBlobToBase64);
}).catch(function (error) {
/* istanbul ignore if */
if (error.status !== 404) {
throw error;
}
return getDocAttachments(src, doc)
.then(convertBlobToBase64);
});
}
그것은 효과가 있었다!
그래서
@craftzdog/pouchdb-core-react-native
와 @craftzdog/pouchdb-replication-react-native
를 모두 만들었습니다.문제가 발견되면 끌어오기 요청을 환영합니다here.
Reference
이 문제에 관하여(React Native에서 사용하기 위해 PouchDB 해킹), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/craftzdog/hacking-pouchdb-to-use-on-react-native-1gjh텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)