Angular 13 package/library throws error "moment is not a function" when imported into a Angular 13 project
Asked Answered
I

3

9

Im upgrading a private angular library/package (my-lib) so i can migrate all other projects, but when imported into a project one of the services uses moment and throws an error: "ERROR TypeError: moment is not a function"

The library works in dev mode and the build and publish are ok and even when imported into a project all components and resources load fine and no errors are displayed, dependencies are download but seeams that some of the 3rd party dependencies are not known by "my-lib" after imported.

Even in the project i can import moment and use it but "my-lib" in node_modules dont see that package.

some of the files in "my-lib"

service.ts

import * as moment_ from 'moment';

const moment = moment_;
...

moment(value).format('YYYY-MM-DD')  ----> line that throws the error

already tried

import moment from 'moment';

and the "allowSyntheticDefaultImports" flag in tsconfig

package.json

"dependencies": {
    ...
    "moment": "~2.29.1",
    ...
},
"devDependencies": {
    "@angular-builders/custom-webpack": "~13.0.0",
    "@angular-devkit/build-angular": "~13.1.1",
    "@angular-eslint/builder": "~13.0.1",
    "@angular-eslint/eslint-plugin": "~13.0.1",
    "@angular-eslint/eslint-plugin-template": "~13.0.1",
    "@angular-eslint/schematics": "~13.0.1",
    "@angular-eslint/template-parser": "~13.0.1",
    "@angular/animations": "~13.1.0",
    "@angular/cli": "~13.1.1",
    "@angular/common": "~13.1.0",
    "@angular/compiler": "~13.1.0",
    "@angular/compiler-cli": "~13.1.0",
    "@angular/core": "~13.1.0",
    "@angular/forms": "~13.1.0",
    "@angular/language-service": "~13.1.0",
    "@angular/platform-browser": "~13.1.0",
    "@angular/platform-browser-dynamic": "~13.1.0",
    "@angular/router": "~13.1.0",
    "eslint": "^8.2.0",
    "ng-packagr": "~13.1.1",
    "rxjs": "~7.4.0",
    "ts-node": "~10.4.0",
    "tslib": "^2.3.0",
    "typescript": "~4.5.2",
    "zone.js": "~0.11.4"
  }

tsconfig.ts

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "noImplicitReturns": true,
    "strictNullChecks": false,
    "noImplicitAny": false,
    "noFallthroughCasesInSwitch": true,
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "es2020",
    "module": "es2020",
    "typeRoots": [
      "node_modules/@types"
    ],
    "types": [
      "node",
      "cypress",
      "cypress-xpath",
      "cypress-wait-until"
    ],
    "lib": [
      "es2020",
      "dom"
    ]
  },
  "angularCompilerOptions": {
    "compilationMode": "partial",
    "enableResourceInlining": true,
    "enableI18nLegacyMessageIdFormat": false,
    "strictInjectionParameters": true,
    "strictInputAccessModifiers": true,
    "strictTemplates": true,
    "types": [
      "node",
      "cypress",
      "cypress-xpath",
      "cypress-wait-until"
    ]
  }
}

ng-package.json

{
  "$schema": "./node_modules/ng-packagr/package.schema.json",
  "lib": {
    "entryFile": "./src/my-lib/public_api.ts",
    "cssUrl": "inline"
  },
  "allowedNonPeerDependencies": ["."]
}

this is a update from angular 9 to 13 and probably im missing something but cannot find examples or documentation that explains the change in behavior.

ps: The "require" function has the same behavior

const a = require('assets/test.png');   --> throws error require is not a function when my-lib is imported into a project and tries to run the this line

If you need more details or have some suggestions i will apreciate.

Thanks in advance

Incensory answered 8/2, 2022 at 17:37 Comment(0)
E
14

I had this issue trying to run moment in stackblitz. Setting "esModuleInterop":true in compilerOptions and using the import moment from 'moment' syntax fixed it for me. Let me know if that works.

Enabling esmoduleInterop also enables allowSyntheticDefaultImports.

More info: https://www.typescriptlang.org/tsconfig#esModuleInterop

Earhart answered 8/2, 2022 at 18:11 Comment(4)
imgur.com/gMY1pXq error when build the library with the import moment from 'moment' and "esModuleInterop":true in compilerOptionsAlysiaalyson
Make sure you don't have allowSyntheticDefaultImports set to false. Maybe just add it and set it to true for good measure.Earhart
i did. i think my lib project is dirty i will try to start from scratch and see if it works. thanks for the help.Alysiaalyson
i did a new library project and with the options you said it works now. Thanks for the helpAlysiaalyson
H
2

Since I don't have enough rep at the moment to write a comment I wanted to emphasize what Chris Hamilton said in the comments which helped me solve the problem:

Make sure you don't have allowSyntheticDefaultImports set to false. Maybe just add it and set it to true for good measure.

I had the same issues when upgrading a library to Angular 13. Already fixed up the imports (import moment from 'moment'), added the "esModuleInterop":true to compilerOptions of the base projects main.ts but it didnt' work. I additionally had to add "allowSyntheticDefaultImports": true for it to work although it had not been previously set to false. Apparently in some cases it needs to be there in addition to "esModuleInterop":true.

Harry answered 20/6, 2022 at 7:11 Comment(0)
C
1

Not able to comment either due to rep, but Chris's answer, saved us some headaches (we upgraded from Angular 11 --> 14)... One other thing for us we had to do and noticed, was we use ng-packagr for our components as they are used by another app as a dependency...in that case, we had to pass a config (that didn't use full ivy compilation mode) via ng-packagr -c that set allowSyntheticDefaultImports to true, as esModuleInterop didn't seem to also set this property for ng-packagr only.

Cusick answered 10/8, 2022 at 16:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.