HumanizeDuration.js icon indicating copy to clipboard operation
HumanizeDuration.js copied to clipboard

Issues with import into es6 project

Open RobMaskell opened this issue 5 years ago • 24 comments

I've pulled this into my project from NPM and I'm trying to import it into a webcomponent but

import { humanizeDuration } from 'humanize-duration/humanize-duration.js'; gives an error that there is not export named humanizeDuration

So I tried

import 'humanize-duration/humanize-duration.js'; but this gives an error Uncaught (in promise) TypeError: Cannot set property 'humanizeDuration' of undefined from the following line 1118 code

  humanizeDuration.humanizer = humanizer;

  if (typeof define === 'function' && define.amd) {
    define(function () {
      return humanizeDuration;
    });
  } else if (typeof module !== 'undefined' && module.exports) {
    module.exports = humanizeDuration;
  } else {
    this.humanizeDuration = humanizeDuration;
  }
})(); // eslint-disable-line semi

basically the last line of real code in the above snippet.

Any ideas how to get around it?

RobMaskell avatar May 03 '19 20:05 RobMaskell

This seems like an issue with how CommonJS imports are being rewritten with imports.

Does import humanizeDuration from 'humanize-duration work?

EvanHahn avatar May 03 '19 20:05 EvanHahn

Fair shout, I gave it a try and this was the result Uncaught (in promise) SyntaxError: The requested module '../../node_modules/humanize-duration/humanize-duration.js' does not provide an export named 'default'

RobMaskell avatar May 03 '19 21:05 RobMaskell

Are you using anything to transpile ES6 imports to be compatible with CommonJS exports?

EvanHahn avatar May 03 '19 21:05 EvanHahn

It's a polymer app, so currently just running with npm start without any transpiling, babel used for prod though

RobMaskell avatar May 03 '19 22:05 RobMaskell

Okay. Are you able to import any other CommonJS modules this way?

EvanHahn avatar May 04 '19 15:05 EvanHahn

I seem to remember having similar issues with time-elements that I also use, but I think they now have two versions and modern one and a legacy. I did try adding the script tag to index.html and while that does work in dev it breaks when the proper build script runs which is what reminded me of time-elements. I think the polymer dev server does something for imports in terms of rewriting them but I'm not sure exactly what.

RobMaskell avatar May 04 '19 16:05 RobMaskell

Could you try writing a simple CommonJS module and using it? Here's a simple one:

module.exports = function () {
  return 'Hello world!'
}

My guess is that this isn't a problem with Humanize Duration but instead a problem with some module setup.

EvanHahn avatar May 04 '19 16:05 EvanHahn

Hmmm I just found this PWA Stater Kit FAQ maybe it just needs a ESM. I'll have a play with script tags and see if I can make it work.

RobMaskell avatar May 04 '19 16:05 RobMaskell

@RobMaskell see https://github.com/EvanHahn/HumanizeDuration.js/pull/159

andrew-c-tran avatar Jul 25 '19 15:07 andrew-c-tran

Thanks @andrew-c-tran I'll check this out at the weekend when I have a little more time

RobMaskell avatar Jul 25 '19 17:07 RobMaskell

Ok I tried and changed my imports as follows

import { LitElement, html } from 'lit-element';

import * as humanizeDuration from 'humanize-duration';

import '@polymer/marked-element/marked-element.js';
import '@polymer/paper-spinner/paper-spinner-lite.js'
import '@polymer/paper-fab/paper-fab.js';
import '@polymer/iron-icons/iron-icons.js';
import '@polymer/iron-icons/device-icons.js';

I get the following error

humanize-duration.js:1185 Uncaught (in promise) TypeError: Cannot set property 'humanizeDuration' of undefined
    at humanize-duration.js:1185
    at humanize-duration.js:1187

it doesn't like the line

this.humanizeDuration = humanizeDuration;

RobMaskell avatar Jul 25 '19 21:07 RobMaskell

@RobMaskell I suspect this is an issue with your build setup. How are you bundling dependencies?

EvanHahn avatar Jul 28 '19 18:07 EvanHahn

I call npm start which runs prpl-server --root server/build which I guess is local dev web server node I suspect for serving sites without much packaging for dev purposes. It all comes from https://github.com/Polymer/pwa-starter-kit but I've had no issues with any other imports although I take your point that it's probably some interaction between this server and your code.

RobMaskell avatar Jul 28 '19 18:07 RobMaskell

It might make sense for us to start publishing an ES module version (sorta like lodash-es).

Are you aware of precedent for that? I want to make sure to maintain backwards compatibility but also want to support ES modules.

EvanHahn avatar Jul 28 '19 18:07 EvanHahn

I had the same problem back in the day with https://github.com/github/time-elements and then I think they sorted it in a new version, might be worth a look?

RobMaskell avatar Jul 28 '19 19:07 RobMaskell

Looks like they publish two exports and use the not-standard-but-used module key in package.json. Not exactly sure what this library should do yet, but wanted to comment about my findings.

EvanHahn avatar Jul 30 '19 15:07 EvanHahn

Node has an official recommendation not to publish ES modules right now. That may change in the future, but for now, I think I'm going to do nothing.

EvanHahn avatar Aug 21 '19 00:08 EvanHahn

Please do not publish any ES module packages intended for use by Node.js until this is resolved.

But it can be used on frontend without node as well...

rokerkony avatar Aug 22 '19 05:08 rokerkony

True, but I'd prefer to only ship one thing. I fear that in trying to address some use cases (eg, a browser build that wants ECMAScript modules) I could break some other cases (eg, a setup that expects CommonJS).

I think I'd like to wait for Node to have a recommendation before continuing here.

EvanHahn avatar Aug 26 '19 02:08 EvanHahn

Revisiting this, it seems like Node is still working on ES module support. Is anyone aware of the best practices here?

EvanHahn avatar Feb 20 '20 15:02 EvanHahn

Sindre Sorhus has been moving his packages to pure ESM.

dasa avatar Jul 20 '21 19:07 dasa

This kind of import works correctly when using Vite + TypeScript:

import humanizeDuration, { HumanizerOptions } from "humanize-duration"

The @types/humanize-duration package provides typings.

MMK21Hub avatar Aug 02 '22 09:08 MMK21Hub