14.0.0
The release 14.0.0 is used for major refactorings and API changes. The replication or the storage layer have only been touched marginally.
Notice that only the major changes are listed here. All minor changes can be found in the changelog.
Removing deprecated features​
The PouchDB RxStorage was deprecated in 13 and has now finally been removed, see here.
Also the old replication-couchdb
plugin was removed. Instead we had the replication-couchdb-new
plugin which was now renamed to replication-couchdb
.
API changes​
RxDocument objects are now immutable​
At the previous version of RxDB, RxDocuments mutate themself when they receive ChangeEvents from the database. For example when you have a document where name = 'foo'
and some update changes the state to name = 'bar'
in the database, then the previous JavaScript object changed its own property to the have doc.name === 'bar'
.
This feature was great when you use a RxDocument with some change-detection like in angular or vue templates. You can use document properties directly in the template and all updates will be reflected in the view, without having to use observables or subscriptions.
However this behavior is also confusing many times. When the state in the database is changed, it is not clear at which exact point of time the objects attribute changes. Also the self mutating behavior created some problem with vue- and react-devtools because of how they clone objects.
In RxDB v14, all RxDocuments are immutable. When you subscribe to a query and the same document is returned in the results, this will always be a new JavaScript object.
Also RxDocument.$
now emits RxDocument
instances instead of the plain document data.
Refactor findByIds()
​
In the past, the functions findByIds
and findByIds$
directly returned the result set. This was confusing, instead they now return a RxQuery
object that works exactly like any other database query.
const results = await myRxCollection.findByIds(['foo', 'bar']).exec();
const results$ = await myRxCollection.findByIds(['foo', 'bar']).$;
Rename to RxDocument update/modify functions​
Related issue #4180.
In the past the naming of the document mutation methods is confusing.
For example update()
works completely different to atomicUpdate()
and so on.
The naming of all functions was unified and all methods do now have an incremental and a non-incremental version (previously known as atomic
):
- RENAME
atomicUpdate()
toincrementalModify()
- RENAME
atomicPatch()
toincrementalPatch()
- RENAME
atomicUpsert()
toincrementalUpsert()
- ADD
RxDocument().incrementalUpdate()
- ADD
RxDocument.incrementalRemove()
- ADD non-incremental
RxDocument
methodspatch()
andmodify()
Replication is started with a pure function​
In the past, to start a replication, the replication plugin was added to RxDB and a method on the RxCollection was called like myRxCollection.syncGraphQL()
.
This caused many problems with tree shaking bailouts and having the correct typings.
So instead of having class method on the RxCollection, the replications are now started like:
import { replicateCouchDB } from 'rxdb/plugins/replication-couchdb';
const replicationState = replicateCouchDB({ /* ... */ });
Storage plugins are prefixed with storage-
​
For better naming, all storage plugins have been prefixed with storage-
so the imports have been changed:
// Instead of
import { getRxStorageDexie } from 'rxdb/plugins/dexie';
// it is now
import { getRxStorageDexie } from 'rxdb/plugins/storage-dexie';
Encryption plugin was renamed to encryption-crypto-js
​
To make it possible to have alternative encryption plugins, the encryption
plugin was renamed to encryption-crypto-js
.
// Instead of
import { wrappedKeyEncryptionStorage } from 'rxdb/plugins/encryption';
// it is now
import { wrappedKeyEncryptionCryptoJsStorage } from 'rxdb/plugins/encryption-crypto-js';
Rewrite the worker
plugin​
In the past, the worker plugin was based on the threads library. It was completely rewritten and uses the plain JavaScript API together with the remote storage plugin. BUT notice that the worker plugin has moved into the RxDB Premium 👑 package.
Performance improvements​
Do not use hash for revisions​
In the past, the _rev
field of a RxDocument dat was filled with a hash of the documents data. This was not the best solution because:
- Hashing in JavaScript is slow, not running hashes on insert improves performance by about 33%
- When 2 clients do the exact same write to the document, it is not clear from comparing the document states because they will have the exact same hash which makes some conflict resolution strategies impossible to implement.
Instead we now use just use the RxDatabase.token together with the revision height.
Batch up incremental operations​
When making multiple writes to different (or the same) document, in the past RxDB made one write call to the storage. When doing fast writes, like when you writhe the current mouse position to a document, the writes could have queued up to the point where the users recognizes performance lag. In RxDB v14, pending document updates are batched up into single storage writes for better performance.
Improved tree shaking​
Many changes have been made to improve tree shakability of RxDB which results in smaller bundle sizes and a faster application startup.
Refactor the document cache​
The whole RxDocument cache was refactored. It now runs based on the WeakRef API and automatically cleans up cached documents that are no longer referenced. This reduces the use memory and makes RxDB more suitable for being used in Node.js on the server side.
Notice that the WeakRef API is only featured in modern browsers so RxDB will no longer run on ie11.
No longer transpile some modern JavaScript features​
To reduce the bundle size and improve performance, the following JavaScript features will no longer be transpiled because they are natively supported in modern browsers anyway:
- async/await
- Arrow functions
- for...of
- shorthand properties
- Spread operator
- destructuring
- default parameters
- object spread
All these optimizations together reduced the test-bundle size from 74148
bytes down to 36007
bytes.
Other changes​
- ADD
push/pull.initialCheckpoint
to start a replication from a given checkpoint. - The following plugins are out of beta mode:
Bugfixes​
- CHANGE (memory RxStorage) do not clean up database state on closing of the storage, only on
remove()
. - FIX CouchDB replication: Use correct default fetch method.
- FIX schema hashing should respect the sort order #4005
- FIX replication does not provide a
._rev
to the storage write when a conflict is resolved. - FIX(remote storage) ensure caching works properly even on parallel create-calls
- FIX(replication) Composite Primary Keys broken on replicated collections #4190
- FIX(sqlite) $in Query not working SQLite #4278
- FIX CouchDB push is throwing error because of missing revision #4299
- ADD dev-mode shows a
console.warn()
to ensure people do not use it in production. - Remove the usage of
Buffer
. We now useBlob
everywhere. - FIX import of socket.io #4307
- FIX Id length limit reached with composite key #4315
- FIX
$regex
query not working on remote storage. - FIX SQLite must store attachments data as Blob instead of base64 string to reduce the database size.
- FIX CouchDB replication conflict handling
- CHANGE Encryption plugin was renamed to
encryption-crypto-js
- FIX replication state meta data must also be encrypted.
Migration from 13.x.x to 14.0.0​
The way RxDB hashes and normalizes a schema has changed. To migrate stored data between the RxDB versions, therefore you have to increase your schema version by 1
and add a migration strategy.
For some storages, the stored data of the previous RxDB versions is not compatible with RxDB 14.0.0
. So if you want to keep that data, you have to migrate it in a way. For most use cases you might want to just drop the data from the client and re-sync it again from the backend. To keep the data locally, you might want to use the storage migration plugin.
You can help!​
There are many things that can be done by you to improve RxDB:
- Check the BACKLOG for features that would be great to have.
- Check the breaking backlog for breaking changes that must be implemented in the future but where I did not have the time yet.
- Check the TODOs in the code. There are many small improvements that can be done for performance and build size.
- Review the code and add tests. I am only a single human with a laptop. My code is not perfect and much small improvements can be done when people review the code and help me to clarify undefined behaviors.
- Update the example projects many of them are outdated and need updates.