Quill: Cannot require in node.js v6.9

Created on 15 Dec 2016  ·  5Comments  ·  Source: quilljs/quill

I'm trying to require and use Quill in a node.js project and having trouble with it. Here's what's happening:

Steps for Reproduction

  1. install it
  2. require it

Expected behavior:

returns the Quill object

Actual behavior:

throws an exception

Platforms:

Version:

Example:

$ npm install quill
[email protected] /Users/patrickminton/src/exm-admin-tool
├── UNMET PEER DEPENDENCY [email protected]
└── [email protected] 

$ node
> var Quill = require('quill')
ReferenceError: document is not defined
    at Object.<anonymous> (/Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:2330:22)
    at __webpack_require__ (/Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:36:30)
    at Object.<anonymous> (/Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:1656:2)
    at __webpack_require__ (/Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:36:30)
    at Object.<anonymous> (/Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:76:15)
    at __webpack_require__ (/Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:36:30)
    at Object.defineProperty.value (/Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:7726:14)
    at __webpack_require__ (/Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:36:30)
    at Object.<anonymous> (/Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:63:19)
    at __webpack_require__ (/Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:36:30)

I used testdom to eliminate the document problem, but it still barfs:

$ node
> require('testdom')('<html><body></body></html>', {})
undefined
> var Quill = require('quill')
ReferenceError: Node is not defined
    at Object.defineProperty.value (/Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:6560:27)
    at __webpack_require__ (/Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:36:30)
    at Object.<anonymous> (/Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:112:19)
    at __webpack_require__ (/Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:36:30)
    at Object.defineProperty.value (/Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:7726:14)
    at __webpack_require__ (/Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:36:30)
    at Object.<anonymous> (/Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:63:19)
    at __webpack_require__ (/Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:36:30)
    at /Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:56:18
    at /Users/patrickminton/src/exm-admin-tool/node_modules/quill/dist/quill.js:59:10

My node/npm:

$ node -v
v6.9.0

 $ npm -v
3.10.8

Any ideas? Am I using it wrong?

Most helpful comment

The key to this is exposing Node as global variable as well.

@bilbosan was using testdom which is a wrapper around jsdom - it automatically sets document as global variable, which solved his first error.

Here is a full example using a more recent version of jsdom

import { JSDOM } from 'jsdom';

const dom = new JSDOM('');
global.window = dom.window;
global.document = dom.window.document;
global.Node = dom.window.Node;

// ...

run this code before any other and it will work fine.

I guess one thing Quill could potentially do to play a little nicer is not to depend on a global Node. Most people who run a test setup like the one above will not expose Node - but they are very very likely to expose window - so if Quill is accessing Node from window.Node I for example wouldn't have run into this problem.

All 5 comments

Quill assumes it is being used in a real browser since that is its target platform. It uses Node for building assets and NPM as a package manager but it is not a back end tool. That's not to say you cannot use it in headless test environments and users have been successful in doing so but that is not officially supported and it does not seem like testdom is doing well enough pretending to be a browser.

Then what is the npm install command for?

Pretty much every application people build nowadays uses Browserify or Webpack to build things before the browser renders it, and if you can't even require() it, then how can you use it?

You can absolutely require Quill for the purposes of building with Webpack or Browserify. You just can't run Quill in the Node.js REPL.

The key to this is exposing Node as global variable as well.

@bilbosan was using testdom which is a wrapper around jsdom - it automatically sets document as global variable, which solved his first error.

Here is a full example using a more recent version of jsdom

import { JSDOM } from 'jsdom';

const dom = new JSDOM('');
global.window = dom.window;
global.document = dom.window.document;
global.Node = dom.window.Node;

// ...

run this code before any other and it will work fine.

I guess one thing Quill could potentially do to play a little nicer is not to depend on a global Node. Most people who run a test setup like the one above will not expose Node - but they are very very likely to expose window - so if Quill is accessing Node from window.Node I for example wouldn't have run into this problem.

The previous code snippet doesn't work any more.
Here's a complete working example with node 10.23.0, jsdom 16.4.0 and quill 1.3.7:

const jsdom = require('jsdom');
const { JSDOM } = jsdom;

const dom = new JSDOM('<div id="editor"></div>');

dom.window.document.getSelection = function() { return { getRangeAt: function() { } }; };
dom.window.document.execCommand = function (command, showUI, value) { try { return document.execCommand(command, showUI, value); } catch(e) {} return false; };

global.window = dom.window;
global.document = dom.window.document;
global.Node = dom.window.Node;
global.navigator = global.window.navigator;
global.Text = dom.window.Text;
global.HTMLElement = window.HTMLElement;
global.MutationObserver = dom.window.MutationObserver;

let Quill = require('quill');
var quill = new Quill('#editor');
quill.setContents([
  { insert: 'Hello ' },
  { insert: 'World!', attributes: { bold: true } },
  { insert: '\n' }
]);
console.log(quill.getText());

Inspired from this and this.

Hope it helps!

Was this page helpful?
0 / 5 - 0 ratings