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

Library including CommonJS dependency fails in Angular 13 #2215

Open
iamthechad opened this issue Jan 5, 2022 · 23 comments
Open

Library including CommonJS dependency fails in Angular 13 #2215

iamthechad opened this issue Jan 5, 2022 · 23 comments
Labels

Comments

@iamthechad
Copy link

Type of Issue

[ X ] Bug Report
[ ] Feature Request

Description

We are upgrading our application that uses several libraries to Angular 13. One of the libraries depends on sockjs-client. This library now fails to load the sockjs-client module correctly after the upgrade.

How To Reproduce

Here's a sample application to show the issue: https://github.com/iamthechad/ng-lib-test

Build the library with npx ng build sample-lib, then run the application with npm start.

If the application component uses the sockjs-client module directly it works correctly. However, if the sockjs-client usage is in the library and exposed through a service, this error is shown in the console:

TypeError: (sockjs_client__WEBPACK_IMPORTED_MODULE_0___namespace_cache || (intermediate value)(intermediate value)) is not a constructor
    at TestService.createSocket (main.js:151)
    at AppComponent.ngOnInit (main.js:28)
    at callHook (vendor.js:23142)
    at callHooks (vendor.js:23111)
    at executeInitAndCheckHooks (vendor.js:23062)
    at refreshView (vendor.js:30100)
    at renderComponentOrTemplate (vendor.js:30199)
    at tickRootContext (vendor.js:31430)
    at detectChangesInRootView (vendor.js:31455)
    at RootViewRef.detectChanges (vendor.js:42027)

This behavior is not limited to sockjs-client and happens with other CommonJS modules.

Expected Behaviour

The sockjs-client module should be resolved correctly when it is used within a library.

Version Information

ng-packagr: 13.1.2
@angular/compiler: 13.1.1
rollup: 2.63.0
typescript: 4.5.4
node: 14.17.6
npm: 6.14.15
sockjs-client: 1.5.2
@iamthechad
Copy link
Author

I confirmed that this works correctly in Angular 12.

@hofsa
Copy link

hofsa commented Jan 7, 2022

I'm facing the same issue after upgrading from Angular 12 to Angular 13.

@alan-agius4
Copy link
Member

You should be able to consume CJS modules by using synthetic default imports.

https://www.typescriptlang.org/tsconfig#allowSyntheticDefaultImports

@iamthechad
Copy link
Author

That does seem to fix the issue, but it's a breaking change. Do we know if this is due to the TS version used in Angular 13, or does it have to do with how version 13 of ng-packagr builds libraries?

@alan-agius4
Copy link
Member

This change seems to be the side-effect of the updated Rollup setup.

@coolalex12
Copy link

I tried using allowSyntheticDefaultImports in the example https://github.com/iamthechad/ng-lib-test:

  1. tsconfig.json
  2. projects/sample-lib/tsconfig.lib.json
  3. projects/sample-lib/tsconfig.lib.prod.json

And I still get an error in the console

@alan-agius4
Copy link
Member

You also need to change the following import https://github.com/iamthechad/ng-lib-test/blob/5a935d43245cb1d97707331620a75ad6d4e7a1b8/projects/sample-lib/src/service/test.service.ts#L2 to a default import instead of a namespace import.

@drakenfly
Copy link

We are facing the same issue. I'll try to provide as much information as possible:

We are trying to use a javascript file into typescript and are re-exporting it for use along several components. The library manufacturer provided as the JS file as a CJS and as a UMD file.

The re-export looks like this:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CdkDirectivesModule, CdkPipesModule, CdkTranslateModule } from '@cwa/cdk';
import { PositionTableModule } from './position-table/position-table.module';

export * from './position-table/position-table.module';
export * from './position-table/position-table.component';

import * as __spider from './spider';
export const Spider = __spider;

@NgModule({
  declarations: [],
  exports: [ PositionTableModule ],
  imports: [
    CommonModule,
    CdkDirectivesModule,
    CdkPipesModule,
    CdkTranslateModule
  ]
})
export class SharedModule { }

When we are using the CommonJS-file, the dist/fesm2015/shared.mjs looks like this:

// Following line is just a copy of the original spider.js file
exports["spider-library"] = /* code of the .js file, unmodified and directly copied into the shared.mjs. It is not assigned to any variable which means it can't be used by the follow-up re-export */;

var __spider = /*#__PURE__*/Object.freeze({
    __proto__: null
});

const Spider = __spider;

When changing from a namespaced to a default import, like this:

import __spider from './spider';
export const Spider = __spider;

we get a compilation error from ng-packagr:


Building entry point '@hidden-name/shared'

✔ Compiling with Angular sources in Ivy partial compilation mode.
✖ Generating FESM2020
'default' is not exported by dist\libs\hidden-name\esm2020\shared\spider.mjs, imported by dist\libs\hidden-name\esm2020\shared\shared.module.mjs

Trying the same steps with the UMD module javascript file yields the same results :(

@themocs
Copy link

themocs commented Feb 10, 2022

I notice, in order to get this work, sockjs-client must be on both projects package.json, the library and the main app.

@krystaDev
Copy link

I have same issue, but with library "node-polyglot"
image

@antch
Copy link

antch commented Aug 8, 2022

Same issue here with Inputmask. I have allowSyntheticDefaultImports enabled in both library and application config, and using default imports I still run into this error.

In fact, using the reproduction that I posted to angular/angular#47078, the error still occurs even after changing every tsconfig*.json to make "allowSyntheticDefaultImports": true.

https://github.com/angular/angular/files/9282262/ng-lib-dependency-issue.tgz

Unfortunately, without a workaround this issue is completely blocking an upgrade to Angular 13.

@michelebombardi
Copy link

michelebombardi commented Sep 5, 2022

Same issue here with moment! Any workaround?

@themocs
Copy link

themocs commented Sep 5, 2022

I notice, in order to get this work, sockjs-client must be on both projects package.json, library and main app.

@antch @mounthorse-slns

@michelebombardi
Copy link

@m0cs I have moment, same version on both project but I still run into this error moment__WEBPACK_IMPORTED_MODULE_0__ is not a function

@michelebombardi
Copy link

michelebombardi commented Sep 5, 2022

These are my dependencies on main app:

"dependencies": {
    "@angular/animations": "14.2.0",
    "@angular/cdk": "14.2.0",
    "@angular/common": "14.2.0",
    "@angular/compiler": "14.2.0",
    "@angular/core": "14.2.0",
    "@angular/forms": "14.2.0",
    "@angular/localize": "^14.2.0",
    "@angular/platform-browser": "14.2.0",
    "@angular/platform-browser-dynamic": "14.2.0",
    "@angular/platform-server": "14.2.0",
    "@angular/router": "14.2.0",
    "@angular/service-worker": "14.2.0",
    "@ckeditor/ckeditor5-angular": "1.2.3",
    "@ckeditor/ckeditor5-build-classic": "23.0.0",
    "@ckeditor/ckeditor5-clipboard": "23.0.0",
    "@ckeditor/ckeditor5-upload": "23.0.0",
    "@ng-bootstrap/ng-bootstrap": "13.0.0",
    "@ng-maps/core": "^3.0.1",
    "@ng-maps/google": "^3.0.0",
    "@ng-maps/places": "^3.0.0",
    "@ng-select/ng-option-highlight": "0.0.7",
    "@ng-select/ng-select": "9.0.2",
    "@ngx-translate/core": "^14.0.0",
    "@ngx-translate/http-loader": "^7.0.0",
    "@popperjs/core": "2.11.6",
    "@swimlane/ngx-charts": "20.1.0",
    "angular-calendar": "0.29.0",
    "angular-calendar-scheduler": "14.1.10",
    "animate.css": "^3.6.1",
    "aspnet-prerendering": "^3.0.1",
    "bootstrap": "^5.2.0",
    "cookieconsent": "3.1.1",
    "core-js": "^3.3.3",
    "crypto-js": "^4.0.0",
    "date-fns": "2.8.1",
    "emoji-flags": "^1.3.0",
    "file-saver": "2.0.2",
    "firebase": "8.0.0",
    "font-awesome": "^4.7.0",
    "jquery": "3.4.1",
    "lodash": "^4.17.20",
    "lodash-es": "4.17.15",
    "lodash.isequal": "4.5.0",
    "moment": "2.29.4",
    "moment-es6": "1.0.0",
    "moment-duration-format": "^2.3.2",
    "ng-busy": "14.0.0",
    "ng-click-outside": "7.0.0",
    "ng2-file-upload": "2.0.0-3",
    "ngx-avatars": "^1.4.1",
    "ngx-color": "8.0.2",
    "ngx-cookieconsent": "2.2.3",
    "ngx-cookie-service": "14.0.1",
    "ngx-custom-validators": "^11.0.1",
    "ngx-filesaver": "14.0.0",
    "ngx-moment": "^6.0.2",
    "ngx-select-ex": "8.0.1",
    "ngx-summernote": "0.8.8",
    "ngx-toastr": "15.0.0",
    "oidc-client": "^1.9.1",
    "popper.js": "^1.16.0",
    "rxjs": "^7.5.6",
    "rxjs-compat": "^6.5.3",
    "signature_pad": "3.0.0-beta.3",
    "summernote": "^0.8.16",
    "tether": "^1.4.7",
    "tslib": "^2.0.0",
    "zone.js": "~0.11.4"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^14.2.1",
    "@angular/cli": "14.2.1",
    "@angular/compiler-cli": "14.2.0",
    "@angular/language-service": "14.2.0",
    "@types/bootstrap": "5.2.3",
    "@types/file-saver": "2.0.5",
    "@types/googlemaps": "3.43.3",
    "@types/jasmine": "~3.6.0",
    "@types/jasminewd2": "~2.0.8",
    "@types/jquery": "^3.3.0",
    "@types/lodash": "^4.14.164",
    "@types/node": "^12.11.1",
    "@types/w3c-web-usb": "^1.0.4",
    "@typescript-eslint/eslint-plugin": "4.16.1",
    "@typescript-eslint/parser": "4.16.1",
    "codelyzer": "^6.0.2",
    "eslint": "^7.6.0",
    "eslint-plugin-import": "^2.26.0",
    "eslint-plugin-jsdoc": "^39.3.6",
    "eslint-plugin-prefer-arrow": "latest",
    "jasmine-core": "~3.8.0",
    "jasmine-spec-reporter": "~5.0.0",
    "karma": "~6.3.4",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage-istanbul-reporter": "~3.0.2",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "typescript": "4.6.4"
  },

and these on my library (I maintain the library):

"devDependencies": {
    "@angular-devkit/build-angular": "^14.2.0",
    "@angular/animations": "14.2.0",
    "@angular/cdk": "14.2.0",
    "@angular/cli": "14.2.0",
    "@angular/common": "14.2.0",
    "@angular/compiler": "14.2.0",
    "@angular/compiler-cli": "14.2.0",
    "@angular/core": "14.2.0",
    "@angular/forms": "14.2.0",
    "@angular/language-service": "14.2.0",
    "@angular/localize": "14.2.0",
    "@angular/material": "14.2.0",
    "@angular/platform-browser": "14.2.0",
    "@angular/platform-browser-dynamic": "14.2.0",
    "@angular/router": "14.2.0",
    "@popperjs/core": "2.11.6",
    "@types/jasmine": "~3.6.0",
    "@types/jasminewd2": "~2.0.8",
    "@types/node": "^12.11.1",
    "angular-calendar": "0.29.0",
    "angular-draggable-droppable": "^6.0.0",
    "angular-resizable-element": "^5.0.0",
    "autoprefixer": "^9.0.0",
    "bootstrap": "^5.2.0",
    "codelyzer": "^6.0.0",
    "copyfiles": "^2.1.1",
    "core-js": "^3.6.1",
    "date-fns": "^2.8.1",
    "jasmine-core": "~3.8.0",
    "jasmine-spec-reporter": "~5.0.0",
    "jquery": "^3.5.0",
    "karma": "~6.3.16",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage-istanbul-reporter": "~3.0.2",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "moment": "^2.29.4",
    "moment-es6": "^1.0.0",
    "ng-packagr": "14.2.0",
    "popper.js": "^1.16.0",
    "postcss-cli": "^6.1.3",
    "postcss-flexibility": "^2.0.0",
    "protractor": "~7.0.0",
    "rxjs": "^6.5.3",
    "sass": "^1.32.5",
    "standard-version": "^8.0.1",
    "ts-node": "~8.5.4",
    "tslib": "^2.0.0",
    "tslint": "~6.1.0",
    "typescript": "4.6.4",
    "zone.js": "~0.11.4"
  },

I have activated allowSyntheticDefaultImports on both and I'm using moment-es6 (on both) to import and use moment.

The test application in the library works but if I publish it (with ng-packagr) and use it from main app I run into error:

moment__WEBPACK_IMPORTED_MODULE_0__ is not a function

I've tried almost everything and I think the issue is ng-packagr itself.
Am I wrong?

@themocs
Copy link

themocs commented Sep 5, 2022

@mounthorse-slns moment on the library side is under "dependencies", but i don't think that's the problem, neither allowSyntheticDefaultImports because you will an error from that. Maybe moment version?

@michelebombardi
Copy link

@m0cs
Before version 0.29.4 I have 0.27.0 and all works fine before angular and ng-packagr upgrade.
I’ve already tried to downgrade from 0.29.4 to 0.27.0 before posting here but unfortunately nothing is changed and I run into same error :(

Related to the first part, on library side Moment is under devDependencies, I have to put it under dependencies?

@michelebombardi
Copy link

michelebombardi commented Sep 6, 2022

I' ve solved this issue for moment library. Basically the solution is explained in angular-calendar source code (here).
So credits for this go to @mattlewis92

Hope this helps someone else.
Thank you!

@themocs
Copy link

themocs commented Sep 7, 2022

Hey @mounthorse-slns what's your case? i mean, moment is on the library project, but not in the main app?

@gmixo
Copy link

gmixo commented Sep 28, 2022

for me, in case of use moment.js, helped this approach
import moment in library code this way

import moment from 'moment/moment'; 

while in project, import looks like this

import * as moment from 'moment/moment';

@michelebombardi
Copy link

michelebombardi commented Sep 28, 2022

@m0cs my case was that moment was in both projects but with Angular 14 seems that dependencies are not bundled anymore while publishing so I put moment only on the main app and passed the dependency to the library.

@yegormk
Copy link

yegormk commented May 22, 2023

@michelebombardi HI! I am facing the same problem right now. I have watched repository you dropped earlier but I can`t understand how it solves the problem. What exactly have you done to solve this problem?

@themocs
Copy link

themocs commented May 22, 2023

I notice, in order to get this work, sockjs-client must be on both projects package.json, the library and the main app.

@yegormk did you try this? same dependency on both projects.

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

No branches or pull requests