docx icon indicating copy to clipboard operation
docx copied to clipboard

docx 7: does not work example of basic usage when using ES modules format in Node.js

Open tadmi opened this issue 4 years ago • 21 comments

Example of Basic Usage does not work on docx v7 (works on v6.0.3)

import * as fs from "fs";
import { Document, Packer, Paragraph, TextRun } from "docx";

// Documents contain sections, you can have multiple sections per document, go here to learn more about sections
// This simple example will only contain one section
const doc = new Document({
    sections: [{
        properties: {},
        children: [
            new Paragraph({
                children: [
                    new TextRun("Hello World"),
                    new TextRun({
                        text: "Foo Bar",
                        bold: true,
                    }),
                    new TextRun({
                        text: "\tGithub is the best",
                        bold: true,
                    }),
                ],
            }),
        ],
    }],
});

// Used to export the file into a .docx file
Packer.toBuffer(doc).then((buffer) => {
    fs.writeFileSync("My Document.docx", buffer);
});

// Done! A file called 'My Document.docx' will be in your file system.

import { Document, Packer, Paragraph, TextRun } from 'docx'; ^^^^^^ SyntaxError: Named export 'Packer' not found. The requested module 'docx' is a CommonJS module, which may not support all module.exports as named exports. CommonJS modules can always be imported via the default export, for example using:

import pkg from 'docx'; const { Document, Packer, Paragraph, TextRun } = pkg;

at ModuleJob._instantiate (internal/modules/esm/module_job.js:124:21)
at async ModuleJob.run (internal/modules/esm/module_job.js:179:5)
at async Loader.import (internal/modules/esm/loader.js:178:24)
at async Object.loadESM (internal/process/esm_loader.js:68:5)

tadmi avatar Sep 29 '21 18:09 tadmi

Try 7.1.0 I have fixed the issue there I think

dolanmiu avatar Sep 29 '21 19:09 dolanmiu

problem remains on version 7.1.0

tadmi avatar Sep 30 '21 05:09 tadmi

on v 7.1.1 error:

import { Document, Packer, Paragraph, TextRun } from 'docx'; ^^^^^^^^ SyntaxError: Named export 'Document' not found. The requested module 'docx' is a CommonJS module, which may not support all module.exports as named exports. CommonJS modules can always be imported via the default export, for example using:

import pkg from 'docx'; const { Document, Packer, Paragraph, TextRun } = pkg;

tadmi avatar Sep 30 '21 16:09 tadmi

Strange I republished this as a ES6 module, and I tried this on Angular with npm link, and it worked fine

I will investigate later

dolanmiu avatar Sep 30 '21 19:09 dolanmiu

It works for me just fine, I am using 7.1.1 right now in Angular, downloaded fresh from npm

Could you double check?

Screenshot 2021-09-30 at 22 40 50

dolanmiu avatar Sep 30 '21 21:09 dolanmiu

Using Docx v7.1.1 I run code from Example of basic usage on nodejs in VS code without frameworks:

import * as fs from 'fs';
import { Document, Packer, Paragraph, TextRun } from 'docx';

// Documents contain sections, you can have multiple sections per document, go here to learn more about sections
// This simple example will only contain one section
const doc = new Document({
  sections: [
    {
      properties: {},
      children: [
        new Paragraph({
          children: [
            new TextRun('Hello World'),
            new TextRun({
              text: 'Foo Bar',
              bold: true,
            }),
            new TextRun({
              text: '\tGithub is the best',
              bold: true,
            }),
          ],
        }),
      ],
    },
  ],
});

// Used to export the file into a .docx file
Packer.toBuffer(doc).then((buffer) => {
  fs.writeFileSync('My Document.docx', buffer);
});

// Done! A file called 'My Document.docx' will be in your file system.

and catch the error:

import { Document, Packer, Paragraph, TextRun } from 'docx'; ^^^^^^^^ SyntaxError: Named export 'Document' not found. The requested module 'docx' is a CommonJS module, which may not support all module.exports as named exports. CommonJS modules can always be imported via the default export, for example using:

import pkg from 'docx'; const { Document, Packer, Paragraph, TextRun } = pkg;

at ModuleJob._instantiate (node:internal/modules/esm/module_job:124:21)
at async ModuleJob.run (node:internal/modules/esm/module_job:179:5)
at async Loader.import (node:internal/modules/esm/loader:178:24)
at async Object.loadESM (node:internal/process/esm_loader:68:5)
at async handleMainPromise (node:internal/modules/run_main:63:12)

package.json

{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "docx": "^7.1.1"
  }
}

it looks like somewhere in the source code Docx.js starting from version 7.0.0 mixed up ES6 modules (import, export) with CommonJS (require/module.exports).

tadmi avatar Oct 02 '21 18:10 tadmi

can you reproduce it on CodePen or StackBlitz? I can't seem to find the problem for me

dolanmiu avatar Oct 03 '21 16:10 dolanmiu

link on StackBlitz

Type in Terminal (catch error on 2):

  1. node common
  2. node es.mjs

tadmi avatar Oct 04 '21 08:10 tadmi

How does it work in v6, do you know?

Does this mean v6 is both commonjs and esm?

dolanmiu avatar Oct 05 '21 00:10 dolanmiu

I have been researching, and it all points to this:

https://www.sensedeep.com/blog/posts/2021/how-to-create-single-source-npm-module.html

I wasn't doing any Hybrid magic before, so I am unsure why it needs to be done now?

dolanmiu avatar Oct 05 '21 09:10 dolanmiu

there was no such problem on version 6.0.3

tadmi avatar Oct 05 '21 10:10 tadmi

maybe the problem arose because of the move from Webpack 3 to Webpack 5

tadmi avatar Oct 05 '21 10:10 tadmi

maybe yes, maybe Webpack 3 did a hybrid but Webpack 5 dropped it?

When I get time, ill turn it hybrid commonJS and ESM

If you want to pick up this task, you could create a PR too

dolanmiu avatar Oct 06 '21 11:10 dolanmiu

@dolanmiu any progress in that? Sorry, I'm not skilled enough to try to solve it on my own

smolendawid avatar Nov 19 '21 08:11 smolendawid

@smolendawid I'm not too well versed in webpack either actually, i am using out of the box content

dolanmiu avatar Nov 21 '21 06:11 dolanmiu

Wanted to updated to 7.2, but I am facing this issue too

rodrigonzalz avatar Dec 16 '21 06:12 rodrigonzalz

Getting the same error with 7.3.0 after pasting and trying to run "Basic Usage"

import { Document, Packer, Paragraph, TextRun } from "docx" ^^^^^^^^ SyntaxError: Named export 'Document' not found. The requested module 'docx' is a CommonJS module, which may not support all module.exports as named exports. CommonJS modules can always be imported via the default export, for example using:

import pkg from 'docx'; const { Document, Packer, Paragraph, TextRun } = pkg;

at ModuleJob._instantiate (node:internal/modules/esm/module_job:127:21)
at async ModuleJob.run (node:internal/modules/esm/module_job:191:5)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:337:24)
at async loadESM (node:internal/process/esm_loader:88:5)
at async handleMainPromise (node:internal/modules/run_main:61:12)

adamjralph avatar Jun 12 '22 02:06 adamjralph

Can you do this?

import { Document as DocxDocument } from "docx";
export const document = options => new DocxDocument(options);

I am on 7.3.0 and have no issues doing the above

My theory is that there is ambiguity between the DOM Document and docx Document

khill-fbmc avatar Jun 30 '22 15:06 khill-fbmc

You still get the nice hinting too image

khill-fbmc avatar Jun 30 '22 16:06 khill-fbmc

You can import like this:

import docx from "docx";
const {Document, Packer, Paragraph, TextRun} = docx;

pablohirafuji avatar Jul 04 '22 23:07 pablohirafuji

@dolanmiu, ESM and CommonJS works if build with changed webpack.config.ts:

...

const configuration = { ...

output: { path: path.resolve("build"), filename: "index.js", ~~libraryTarget: "umd",~~ library: ~~"docx"~~ { type: "commonjs-static" }, globalObject: "globalThis", }

...

tadmi avatar Mar 11 '23 16:03 tadmi

But would this work as an iife? Like a standard <script src="..."></script> tag?

dolanmiu avatar Mar 19 '23 19:03 dolanmiu

Need to test

tadmi avatar Mar 19 '23 19:03 tadmi

But would this work as an iife? Like a standard <script src="..."></script> tag?

Does not work

tadmi avatar Mar 24 '23 15:03 tadmi

Ah I see. Yes, this would be a requirement

dolanmiu avatar Mar 25 '23 01:03 dolanmiu

As variant to build 2 entry points:

changes in a webpack.config.ts:

const configuration = { ... entry: { index: { import: "./src/index.ts", library: { name: "docx", type: "umd" } }, node: { import: "./src/index.ts", library: { type: "commonjs-static" } }, },

output: { path: path.resolve("build"), filename: "[name].js", // libraryTarget: "umd", // library: "docx", globalObject: "globalThis", }, ...

image

Who need docx.js in node.js through the ESM:

import { Document, Packer, Paragraph, Tab, TextRun, } from './node_modules/docx/build/node.js';

The only thing I don't know is how to automatically duplicate index.d.ts with the name node.d.ts for types.

tadmi avatar Mar 25 '23 06:03 tadmi

Version 8.0.4 and Basic usage example still doesn't work in Node with ESM. Is it possible to at least update a documentation accordingly?

xpuu avatar Jun 11 '23 11:06 xpuu

Doesn't work for me with Angular. Neither the old way, nor the above suggestions:

Error: export 'default' (imported as 'docx') was not found in 'docx' (module has no exports)

LubosD avatar Jul 20 '23 09:07 LubosD