Nolan Lawson

By: Nolan Lawson
Published: 12 December 2016

PouchDB 6.1.0 adds a new feature, {latest: true}, as well as several bug fixes and performance improvements. For a full changelog since 6.0.0, including several patch releases up to 6.0.7, please see the releases page.

latest: true

CouchDB has an option on the document endpoint called latest=true, which will fetch the latest revision of a document in the case where the requested revision has been updated.

For instance, let's say we have a document:

{_id: 'foo', _rev: '1-x'}

And we update it, so its revision increments:

{_id: 'foo', _rev: '2-y'}

Now, if were were to fetch it using db.get('foo', {rev: '1-x'}), that would give us the old revision. However, by doing db.get('foo', {rev: '1-x', latest: true}), we'll get the 2-y revision instead.

This might seem like a niche use case, but this parameter is used by the CouchDB replicator to avoid race conditions where a document is updated right at the moment that it's being synced. This feature has now been added to PouchDB's replication algorithm, meaning that with 6.1.0 onward, replication should be much more robust.

Many thanks to Will Holley for implementing both {latest: true} and the replication fixes! See this PR for more details.

Better fetch() implementation

When using PouchDB inside of a Service Worker, the XMLHttpRequest API is unavailable and hence PouchDB uses the new fetch API instead. However, this implementation was not previously tested, and feedback from HospitalRun.io developer John Kleinschmidt suggested that PouchDB's fetch()-based implementation was less robust than its XHR-based implementation.

In 6.1.0, we have added CI testing for the fetch() implementation and also fixed all outstanding bugs such that it passes the test suite at 100%. Therefore the new fetch() implementation is now just as reliable as the XHR implementation, improving PouchDB's Service Worker support.

In a future release, PouchDB will drop the XHR implementation entirely and use fetch() only, with a polyfill for non-fetch() browsers.

Better warnings

When using plugins, we found that folks would often make a mistake like this:

PouchDB.plugin('pouchdb-find');

Whereas the proper form is:

PouchDB.plugin(require('pouchdb-find'));

Before 6.1.0 this error message was hard to diagnose. As of 6.1.0, though, this will now provide a more helpful error:

Invalid plugin: got "pouchdb-find", expected an object or a function

We also found it common to forget to include a content_type when inserting attachments, which can lead to hard-to-debug errors later on. Now, an attachment without a content_type will emit a warning:

Attachment foo.txt on document mydoc is missing content_type

Thanks to Andy Morris for the content_type fix!

Remove peerDependency on pouchdb-core

Because of the way PouchDB is structured, it's possible to use PouchDB plugins without technically including the pouchdb-core package. The reason for this is that packages like pouchdb, pouchdb-browser, and pouchdb-node are aggressively bundled to improve the installation, download, and execution time. So rather than explicitly depend on pouchdb-core, they inline it.

Previously, this would generate a warning during npm install:

npm WARN pouchdb-adapter-memory@6.0.7 requires a peer of pouchdb-core@6.0.7 but none was installed.

This warning has been removed in 6.1.0 because it caused confusion more often than it helped.

Unfortunately npm offers no way to emit a peerDependency warning only if any one of possible peers (e.g. pouchdb-core, pouchdb, pouchdb-browser, or pouchdb-node) are not installed or have the wrong version, so we removed the peerDependency entirely.

If you're wondering how to correctly use PouchDB plugins with core PouchDB packages, the answer is fairly simple: first-party plugins should always have the same version as the other core PouchDB packages. These packages are published at the same time with the same versions, so you just need to be sure to keep them synchronized. For instance:

{
  "dependencies": {
     "pouchdb-core": "6.1.0",
     "pouchdb-promise": "6.1.0",
     "pouchdb-replication": "6.1.0",
     "pouchdb-adapter-memory": "6.1.0",
  }
}

If these versions do not exactly match (e.g. "6.1.0" and "6.0.7") then PouchDB will no longer warn you, however the behavior is undefined and could lead to bugs.

Note that third-party dependencies (such as pouchdb-find, worker-pouch, and pouchdb-server) have their own versioning schemes and therefore do not need to be kept in sync.

Smaller code, fewer dependencies

Like any codebase, PouchDB's has accumulated some cruft over time. As part of an effort to simplify the codebase, PouchDB 6.1.0 now has one less dependency (es6-promise-pool, replaced with a smaller custom implementation) and actually has a slightly smaller bundle size than 6.0.7 (45337 bytes min+gz to 45299).

Furthermore, PouchDB's internal timer system has been vastly simplified, relying on the built-in browser setTimeout() rather than process.nextTick() (thus avoiding a rather large Browserify/Webpack dependency), as well as eliminating timeouts entirely where they were found to be unnecessary. This will actually result in a performance boost to most PouchDB operations in terms of latency, since PouchDB is no longer yielding to the event loop so frequently.

However, the tradeoff is that this change may also give fewer opportunities for the browser to accept input, hence possibly leading to blocked UIs or slower scrolling. In such cases, if you do experience a sluggish UI on account of PouchDB, we recommend moving PouchDB into a web worker or using worker-pouch to avoid blocking the browser UI.

Full changelog

New features

  • #5857 - add latest:true

Bug fixes and performance improvements

  • #5857 - use latest:true during replication
  • #5904 - more helpful error message for invalid plugin
  • #5736 - warn about attachments without content_type
  • #5925 - remove peerDependency on pouchdb-core
  • #5922 - transitive default
  • #5930 #5898 - simplify timeouts
  • #5934 - simplify parseAdapter
  • #5905 - remove es6-promise-pool
  • #5899 - simplify PouchError code
  • #5902 - fix fetch() implementation
  • #5886 - fix bulkGet() with reserved _id
  • #5855 - fix JSON.parse() overflows
  • #5883 - retrieve appropriate _revisions when there are duplicate rev hashes
  • #5832 - return correct revision after doc update
  • #5479 - ensure sync events are called the correct number of times
  • #5812 - fix memory leaks in pouchdb-core
  • #5793 - fixes for Couchbase Sync Gateway
  • #5988 - remove unsafe new Buffer() usages

Get in touch

As always, we welcome feedback from the community and would love to hear what you think of this release as well as PouchDB's future direction. Please don't hesitate to file issues or get in touch. And of course, a big thanks to all of our new and existing contributors!