Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
tadmi opened this issue Sep 29, 2021 · 28 comments
Labels

Comments

@tadmi
Copy link
Contributor

tadmi commented Sep 29, 2021

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)
@dolanmiu
Copy link
Owner

Try 7.1.0 I have fixed the issue there I think

@tadmi
Copy link
Contributor Author

tadmi commented Sep 30, 2021

problem remains on version 7.1.0

@dolanmiu dolanmiu reopened this Sep 30, 2021
@dolanmiu dolanmiu added the bug label Sep 30, 2021
@tadmi
Copy link
Contributor Author

tadmi commented Sep 30, 2021

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;

@dolanmiu
Copy link
Owner

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
Copy link
Owner

dolanmiu commented Sep 30, 2021

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

@tadmi
Copy link
Contributor Author

tadmi commented Oct 2, 2021

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).

@dolanmiu
Copy link
Owner

dolanmiu commented Oct 3, 2021

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

@tadmi
Copy link
Contributor Author

tadmi commented Oct 4, 2021

link on StackBlitz

Type in Terminal (catch error on 2):

  1. node common
  2. node es.mjs

@dolanmiu
Copy link
Owner

dolanmiu commented Oct 5, 2021

How does it work in v6, do you know?

Does this mean v6 is both commonjs and esm?

@dolanmiu
Copy link
Owner

dolanmiu commented Oct 5, 2021

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 dolanmiu reopened this Oct 5, 2021
@tadmi
Copy link
Contributor Author

tadmi commented Oct 5, 2021

there was no such problem on version 6.0.3

@tadmi
Copy link
Contributor Author

tadmi commented Oct 5, 2021

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

@dolanmiu
Copy link
Owner

dolanmiu commented Oct 6, 2021

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

@smolendawid
Copy link

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

@tadmi tadmi changed the title docx 7.0.0: does not work example of basic usage when using ES modules format docx 7: does not work example of basic usage when using ES modules format in Node.js Nov 19, 2021
@dolanmiu
Copy link
Owner

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

@rodrigonzalz
Copy link

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

@adamjralph
Copy link

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)

@khill-fbmc
Copy link
Contributor

khill-fbmc commented Jun 30, 2022

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
Copy link
Contributor

You still get the nice hinting too
image

@pablohirafuji
Copy link

pablohirafuji commented Jul 4, 2022

You can import like this:

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

@tadmi
Copy link
Contributor Author

tadmi commented Mar 11, 2023

@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",
}

...

@dolanmiu
Copy link
Owner

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

@tadmi
Copy link
Contributor Author

tadmi commented Mar 19, 2023

Need to test

@tadmi
Copy link
Contributor Author

tadmi commented Mar 24, 2023

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

Does not work

@dolanmiu
Copy link
Owner

Ah I see. Yes, this would be a requirement

@tadmi
Copy link
Contributor Author

tadmi commented Mar 25, 2023

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.

@xpuu
Copy link

xpuu commented Jun 11, 2023

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?

@LubosD
Copy link

LubosD commented Jul 20, 2023

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

9 participants