I'm building an Angular (2+) component library using jvandemo/generator-angular2-library as a starter, which uses Rollup as a module builder. The component I am creating in the library uses MomentJS.
I've had various build issues with the inclusion of MomentJS.
I first used import moment from 'moment';
to import moment into the component, but that produces the following error at build;
[17:26:28] Starting 'ngc'...
Error at /Users/chris/angular-library/.tmp/components/my-library/my-component.component.ts:6:8: Module '"/Users/chris/my-library/node_modules/moment/moment"' has no default export.
I found this SO question that said to use import * as moment from 'moment';
however with that I get;
'moment' is imported by build/components/my-component.component.js, but could not be resolved – treating it as an external dependency
events.js:182
throw er; // Unhandled 'error' event
^
Error: Cannot call a namespace ('moment')
at error (/Users/chris/angular-library/node_modules/rollup/dist/rollup.js:185:14)
As far as I can tell these are the only two options and I can't get either to work, what am I missing?
Edit
I've added this issue to the library's Github repo that contains minimalistic replication steps
Moment. js is used for parsing, validating, manipulating, and displaying dates and times in JavaScript. In this guide, we are adding Moment. js to Angular (application platform).
moment. js is a lightweight JavaScript date library for parsing, validating, manipulating, and formatting dates. Two simple steps require to add moment js in Angular 8 applications.
The error is very clear and specific
Error: Cannot call a namespace ('moment') at error (/Users/chris/angular-library/node_modules/rollup/dist/rollup.js:185:14)
This is per the ES Module Specification.
That means the following is an invalid way to import moment, or anything you intend to call, because a module namespace object, such as that created by * as ns
may not be called.
import * as moment from 'moment';
The correct form is the form that ngc
is raising an error on
import moment from 'moment';
Firstly to make this work, you need to specify the --allowSyntheticDefaultImports
flag.
tsconfig.json
{
"compilerOptions": {
"allowSyntheticDefaultImports": true
}
}
Assuming that ngc
will recognize the option, you still have an additional problem to work out.
The flag above is for users of tools such as SystemJS or Webpack which perform the synthesis, allowing such code to typecheck.
As of TypeScript 2.7, you can now specify the --esModuleInterop
flag to have the language provide the synthesis as part of the transpilation process.
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"esModuleInterop": true
}
}
Note that if you are using a version of TypeScript prior to 2.7 and if you are compiling to CommonJS, AMD, or UMD modules (e.g. with --module commonjs
) the correct import syntax is rather
import moment = require('moment');
The import = require
syntax is a TypeScript specific construct, now largely unnecessary. It exists to acquire both the type and the value of the module exports of an AMD, CommonJS, or UMD module. The "and" is important because a const
, var
, or let = require
invocation only creates a name in the value space not in the type space.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With