pouchdb: PouchDB with Nuxt 3: Uncaught ReferenceError: global is not defined

Issue

Getting Uncaught ReferenceError: global is not defined with the line: var Mutation = global.MutationObserver || global.WebKitMutationObserver; in file node_modules/immediate/lib/mutation.js when using Nuxt 3.

Not sure I provided enough details… I also created a SO question for RxDB when used with PouchDB.

My main goal is to use RxDB, but I need a way to make PouchDB works first.

Info

  • Environment: Browser, Nuxt 3 RC 3
  • Platform: FF
  • Adapter: idb
  • Server: CouchDB

Reproduce

  1. npx nuxi init
  2. npm install pouchdb
  3. plugin/pouchdb.ts:
import PouchDB from "pouchdb"

export default defineNuxtPlugin(async nuxtApp => {

    var db = new PouchDB('dbname');

    db.put({
        _id: 'dave@gmail.com',
        name: 'David',
        age: 69
    });

    db.changes().on('change', function () {
        console.log('Ch-Ch-Changes');
    });

    return {
        provide: {
            db: () => db
        }
    }
});

I tried adding the following to nuxt.config.ts

build: {
		transpile: [
			'pouchdb-browser',
			'pouchdb-utils',

		],
	},

I’m far from an expert with transpiling and webpack and such. I saw some polyfill with webpack for the global error here.

I tried adding it with Nuxt 3 but either Nuxt didn’t add it or this isn’t the right fix for my issue…

	app: {
		head: {
			script: [
				{
					children: `window.process = window.process || { env: { NODE_DEBUG: undefined, DEBUG: undefined } }; window.global = window;`
				}
			]
		}
	},

Nuxt config API here

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 1
  • Comments: 18 (2 by maintainers)

Most upvoted comments

Any chance we will have a normally working library that can be imported as any other ES-module libraries as import PouchDB from 'pouchdb';?

They can’t fix this issue. It happens everywhere.

I had this same issue using Vite to build a SPA with PouchDB. (Using either pouchdb or pouchdb-browser v8).

For me, @Sjoerd82 define: { global: "window" } was not enough. I was able to solve it my using this complex vite.config.ts to shim for global and cjs stuff.

It seems that the problem is PouchDB’s use of immediate which uses global. It would be nice if there was another alternative so that we could use PouchDB without friction in modern build pipelines.

Here is a workaround:

  • nuxt: 3.0.0-rc.8
  • pouchdb: 7.3.0
  • pouchdb-find: 7.3.0
  1. Use pouchdb package. pouchdb-browser can’t work because Nuxt / vite SSR would still load packages on the server side, even we only use them on client pages.
  2. Add the polyfill script by modifying App.vue as following:
<template>
  <div>
    <Head>
      <Script
        children="if (window.global === undefined) { window.global = window; }"
      >
      </Script>
    </Head>
    <NuxtPage />
  </div>
</template>
  1. Initialize DB in a “client” plugin (If not, duplicated DBs are initialized on both server and client sides, and it may not what we expect):

plugins/initAppDb.client.ts

import PouchDB from "pouchdb";
import PouchDBFind from "pouchdb-find";
PouchDB.plugin(PouchDBFind);

export default defineNuxtPlugin(async () => {
  const appDb = new PouchDB("myAppDb");
  await appDb.createIndex({
    index: {
      fields: ["type", "title"],
      ddoc: "index-article-title",
    },
  });
  return {
    provide: { appDb },
  };
});
  1. Use the plugin in pages
<script setup lang="ts">
  const { $appDb } = useNuxtApp();
  //...
</script>

I got it working by adding define: { global: "window" } to vite.config.ts and installing events dependency (npm i events) as suggested in https://github.com/pouchdb/pouchdb/issues/8607#issuecomment-1446127547. Edit: I’m using Ionic+Vite and adding define: { global: "window" } causes errors on Ionic components when launching the vite build command. To fix this I removed it and added <script>window.global = window</script> to index.html instead.

Ahh RIP. Similar dance on my side, one error fixed and two appears.

I wish it was easier to use CouchDB. I want to use it so badly with RxJS/RxDB, but Postgres/Prisma right now looked like my only option. I’ll figure out some logic to download the needed data for offline use. I’ll keep a close eye on CouchDB/Cloudant development, though.

But your idea of using axios is intriguing. I need to use server side API anyway, axios could be used there to fetch data and verify ACL/PASETO anyway. Since I’m not far in the project it could be done. idk

@VladimirCores perhaps this will work (it requires NO special configuration in vite.config.js): https://www.npmjs.com/package/pouchdb-browser

I ran a quick test under vite+svelte and it seems to work, though I only had a minute to type this up, sorry.

The following is a random bit of code from the script section of a svelte app, showing initialization, plugin use, and some debugging data.

update: you will need the following in your HTML template:

<script>
  var global = (global === undefined) ? window : global;
</script>

Svelte Code

import { onMount } from 'svelte';
import PouchDB from 'pouchdb-browser';
import pouchdbFind from 'pouchdb-find';

PouchDB.plugin(pouchdbFind);
const db = new PouchDB('kittens');
 
db.changes().on('change', function(x) {
  console.log('Ch-Ch-Changes',x);
});

onMount(async () => {

  try {
    const result = await db.bulkDocs([
      {_id: 'a', type: 'node', name: 'Application' },
      {_id: 'z', type: 'node', name: 'Utils' },
      {_id: 'b', type: 'node', name: 'Library' },
      {_id: 'c', type: 'node', name: 'Program' },
      {_id: 'x', type: 'node', name: 'Get Date' },
      {_id: 'y', type: 'node', name: 'Load Thing' },
      {_id: 'e1', type:'edge',  source: 'a', target: 'b' },
      {_id: 'e2', type:'edge',  source: 'a', target: 'z' },
      {_id: 'e3', type:'edge',  source: 'b', target: 'c' },
      {_id: 'e4', type:'edge',  source: 'c', target: 'x' },
      {_id: 'e5', type:'edge',  source: 'c', target: 'y' },
    ]);
  } catch (err) {
    console.log(err);
  }

  await db.viewCleanup()
  const indexes = await db.getIndexes();
  console.log(indexes);

const nodes = (await db.query(function (doc, emit) { emit(doc.type); }, {key: 'node', include_docs:true }))
.rows.map(row=>row.doc)
.map(doc=>({data:{id:doc._id, ...doc}}));

const edges = (await db.query(function (doc, emit) { emit(doc.type); }, {key: 'edge', include_docs:true }))
.rows.map(row=>row.doc)
.map(doc=>({data:{id:doc._id, ...doc}}));

const data ={
nodes,
edges,
}

console.log(data);
});

Snippet from package.json, I am using:

    "pouchdb-browser": "^7.3.0",
    "pouchdb-find": "^7.3.0",

Oh ok, thanks for your reply. Quite funny, libraries designed for client-side database sync stuff not working with recent tech, PWA and the like 😕

I hope someone eventually finds a solution, in the meantime I’ll write everything server side with CouchDB Nano and refactor everything later. Or maybe plain pgsql since it’s server-side no matter what, idk.

Fixed by #8849

I you are using nuxt3 and you are getting the error from pouchdb , you can solve this by:

  1. Install events
  2. in nuxt.config.ts add this -> vite: { define: { global: ‘window’ }, },

thats it , you are good to go

FWIW I used a polyfill to resolve this particular global issue here: https://github.com/colearendt/js-issue-20220729

However, I then ran into #8535, which I don’t have a solution for 🙈 I’m probably just going to use axios to make the requests I need in the short term since I’m leaning on CouchDB anyways.