pouchdb / pouchdb

:kangaroo: - PouchDB is a pocket-sized database.
https://pouchdb.com/
Apache License 2.0
16.93k stars 1.47k forks source link

Module build for browser breaks when built with vite #8266

Closed gbirke closed 3 years ago

gbirke commented 3 years ago

Issue

When including PouchDB in vite projects, vite removes all Node modules when building for the browser. During the bundling phase, vite outputs externalized node built-in "events" to empty module and in the browser I get the error Module "events" has been externalized for browser compatibility and cannot be accessed in client code.

The workaround explained in #8130 does not work any more.

My suggestion for a solution would be to add the node-polyfills rollup plugin when building the browser es6 module. This will replace the "events" builtin with functionally identical code. I could try to provide a patch.

Info

Reproduce

Create a new vite app and add the line import PouchDB from 'pouchdb-browser' to the file main.js

npm init vite-app testApp
cd testApp
npm i && npm i pouchdb-browser
npm run dev
troncoso commented 3 years ago

@gbirke Do you have any work around for this at all? I'm running into the same issue

jbjorge commented 3 years ago

@gbirke Are you by any chance using vite@2.0.0-beta.xx?

I just updated my own vite to 2x, so I'll dig into finding a workaround on the vite side now :+1:

jbjorge commented 3 years ago

Here is my setup that I got working with vite@2.0.0-beta.52 (the current version is .53, but is totally broken). My apologies if it's not relevant for this issue.

// package.json (left out irrelevant packages)
"dependencies": {
    "events": "^3.2.0",
    "pouchdb-browser": "^7.2.2",
    "process": "^0.11.10",
    "vue": "^3.0.5",
    "vue-router": "^4.0.3"
  },
  "devDependencies": {
    "@rollup/plugin-node-resolve": "^9.0.0",
    "@vitejs/plugin-vue": "^1.1.2",
    "@vue/compiler-sfc": "^3.0.5",
    "eslint-plugin-vue": "^6.2.2",
    "vite": "^2.0.0-beta.52"
  }
// vite.config.js
import pluginVue from '@vitejs/plugin-vue';

export default {
    hostname: '127.0.0.1',
    optimizeDeps: {
        allowNodeBuiltins: ['pouchdb-browser', 'pouchdb-utils', 'base64id', 'mime-types'],
        include: ['pouchdb-live-find/dist/index.es.js']
    }
    plugins: [pluginVue()],
}
// main.js as the first line
import process from 'process/browser';
window.process = process;

window.global = window;

I didn't run into the issue with events being undefined, but that was solved for me in #8130.

Edit: Added window.global = window; to main.js

github-actions[bot] commented 3 years ago

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days

dheimoz commented 3 years ago

Hello @jbjorge are you having the same issues with the latest version?

jbjorge commented 3 years ago

@dheimoz Seems like it is easier with the latest version of vite (2.1.5). I only needed the shims for process and global (this might be because of packages I use, so might not be relevant for others).

window.process = window.process || {};
window.global = window;
dheimoz commented 3 years ago

Thank you very much for the response @jbjorge. Working with Vite and Pouch seems to be the greatest experience ever. Will definitely try in the nearest future.

Off topic I wonder if you are in the Discord channel of Vite: https://chat.vitejs.dev/

Your user experience is worthy. Thanks.

jbjorge commented 3 years ago

@dheimoz No problem, hopefully someone will find this thread helpful. I've been working on a side project for over a year now with couchdb/pouchdb/vue/vite and apart from some bundling issues with vite (in this thread), it has been a breeze.

dheimoz commented 3 years ago

Great @jbjorge please let me know if you need any assistance. I love Couchdb - Cloudant, Pouchdb and Vue. They are my main tools.

As you stated, hope the author of the issue could find the information you have shared useful.

muhdfaiz commented 3 years ago

Does anyone know the solution to fix this issue?. I'm still having this issue and I'm using vite version 2.5.7

dheimoz commented 3 years ago

@muhdfaiz could you be more specific? I have been using Pouchdb with Vite for a project and following the suggestions provided by @jbjorge everything worked out.

muhdfaiz commented 3 years ago

@dheimoz I'm using electron with vite. Writing using typescript.

Electron version: 13.4.0 Vite version: 2.5.7

Uncaught TypeError: Failed to resolve module specifier "events". Relative references must start with either "/", "./", or "../".

Try @jbjorge solution but still didn't work. Solution like below

window.process = window.process || {}; window.global = window;

It only happen when I run the app that was build/compile. If run using dev server(watch mode) no issue.

hcker2000 commented 2 years ago

Getting the same issue as @muhdfaiz any work around?

jbjorge commented 2 years ago

I haven't worked with electron for quite a while, but for my most recent (small) project I used vite-plugin-html to work around the problem along with adding two lines in index.html

In vite.config.ts

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import injectHtml from 'vite-plugin-html';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    injectHtml({
      inject: {
        data: {
          injectEnv: '<script type="module">window.process = window.process || { env: { NODE_ENV: import.meta.env.DEV } }</script>'
        }
      }
    })
  ],
  build: {
    outDir: './dist',
    emptyOutDir: true
  }
})

In index.html's tag

<!DOCTYPE html>
<html lang="en">
<head>
    <%- injectEnv %>
    <script>window.process = window.process || { env: { NODE_ENV: 'production' } }</script>
</head>
</html>

The reason why there's two definitions of window.process is because of a difference in how it's built/bundled depending on if you're running dev or build. Hope this works for your case @hcker2000

spiffytech commented 2 years ago

I got this working with two steps:

  1. Alias global to window in vite.config.js:
export default {
  define: {
    global: "window",
  },
};

2: npm install events

No other config necessary.

youwch commented 2 years ago

I got this working with two steps:

  1. Alias global to window in vite.config.js:
export default {
  define: {
    global: "window",
  },
};

2: npm install events

No other config necessary.

I have the same problem, your answer works, thx.

fredguth commented 2 years ago

For anyone looking for how to add pouchdb in a sveltekit app, just add vite config in svelte.config.js:

import adapter from '@sveltejs/adapter-auto';
import preprocess from 'svelte-preprocess';

/** @type {import('@sveltejs/kit').Config} */
const config = {
    // Consult https://github.com/sveltejs/svelte-preprocess
    // for more information about preprocessors
    preprocess: preprocess(),

    kit: {
        adapter: adapter(),
        vite: {
            define: {
                global: 'window',
                process: { env: {} }
            }
        }
    }
};

export default config;
AlexErrant commented 2 years ago

Javascript noob here.

The docs for vite's define state:

Because it's implemented as straightforward text replacements without any syntax analysis, we recommend using define for CONSTANTS only.

For example, process.env.FOO and __APP_VERSION__ are good fits. But process or global should not be put into this option. Variables can be shimmed or polyfilled instead.

Am I correct in thinking that the above advises against the following?

export default {
  define: {
    global: "window",
  },
};
sureshvv commented 2 years ago

https://github.com/pouchdb-community/pouchdb-quick-search/issues/106

aeharding commented 1 month ago

This is still an issue.

I ended up fixing with https://www.npmjs.com/package/vite-plugin-node-polyfills