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

Instructions for overriding tsconfig.json don't seem to work #2156

Open
benelliott opened this issue Nov 15, 2021 · 12 comments
Open

Instructions for overriding tsconfig.json don't seem to work #2156

benelliott opened this issue Nov 15, 2021 · 12 comments
Labels

Comments

@benelliott
Copy link

benelliott commented Nov 15, 2021

Type of Issue

[x] Bug Report
[ ] Feature Request

Description

A bug: please describe the error that you encountered

I encountered some issues when trying to upgrade my 12.x project (which overrides some tsconfig options) to 13.x. I was unable to find a working solution for overriding some tsconfig options. I could reproduce the issue on a fresh minimal reproduction.

A feature: please describe your use case and motivation

How To Reproduce

A bug: please include instructions how to reproduce. Issues without reproduction are likely to receive no feedback.

  1. Create a fresh sample project:
mkdir ngpackagr
cd ngpackagr
npm init -y
npm i -D typescript ng-packagr
  1. Add public_api.ts at root with contents export const FOO = 'bar';
  2. Edit package.json to add ng-packagr build script:
{
  "name": "ngpackagr",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "ng-packagr -p package.json"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "ng-packagr": "^13.0.3",
    "typescript": "^4.4.4"
  },
  "ngPackage": {
    "lib": {
      "entryFile": "public_api.ts"
    }
  }
}
  1. confirm that the project builds successfully by running npm build

  2. add custom tsconfig.lib.json per these instructions, with contents

{
  "extends": "./node_modules/ng-packagr/lib/ts/conf/tsconfig.ngc.json",
  "compilerOptions": {
    "types": ["node"],
    "allowSyntheticDefaultImports": true
  }
}
  1. point ngpackagr to this config in the build script: "build": "ng-packagr -p package.json --config tsconfig.lib.json"

  2. run npm build and get error message:

Compiling with Angular sources in Ivy partial compilation mode.Error: ENOENT: no such file or directory, open '[my project dir]/node_modules/ng-packagr/lib/ts/conf/AUTOGENERATED'
    at Object.openSync (fs.js:498:3)
    at readFileSync (fs.js:394:35)
    ...

Can you reproduce the error in the integration tests in ng-packagr?
If possible, take a look at the integration/samples and try to break one of these builds!

Is the error you faced in an application importing the library
Try to break the Angular CLI app in integration/consumers/ng-cli!

Expected Behaviour

A bug: please describe what behaviour or result you expected

It should compile

A feature: do you have a first draft or an idea how to implement?

Version Information

$ node_modules/.bin/ng-packagr --version
ng-packagr: 13.0.3
@angular/*: N/A
typescript: 4.4.4
rxjs: N/A
node: 14.17.6
npm/yarn: 7.21.0

Windows 10

Please include all version numbers that might be relevant, e.g. third-party libraries

@benelliott
Copy link
Author

Hi @alan-agius4 , I was wondering if you have any tips for updating a library to Angular 13 that needs allowSyntheticDefaultImports: true in its tsconfig? It's blocking us from updating our other apps to A13 so any ideas on how to work around this issue would be much appreciated.

@alan-agius4
Copy link
Member

alan-agius4 commented Nov 24, 2021

What you can do is instead of extending the tsconfig you copy the options directly in your project.

{
  "angularCompilerOptions": {
    "compilationMode": "partial",
    "strictTemplates": true,
    "enableResourceInlining": true
  },
  "buildOnSave": false,
  "compileOnSave": false,
  "compilerOptions": {
    "target": "es2020",
    "module": "es2020",
    "moduleResolution": "node",
    "baseUrl": ".",
    "declaration": true,
    "inlineSourceMap": true,
    "inlineSources": true,
    "skipLibCheck": true,
    "emitDecoratorMetadata": false,
    "experimentalDecorators": true,
    "importHelpers": true,
    "lib": ["dom", "es2018"],
   "allowSyntheticDefaultImports": true
  },
  "exclude": ["node_modules", "dist", "**/*.shim.ts", "**/*.spec.ts"]
}

@benelliott
Copy link
Author

Thanks!

When I try those options, I get

The "path" argument must be of type string. Received undefined

@alan-agius4
Copy link
Member

I updated the tsconfig above, can you please try again?

@benelliott
Copy link
Author

That seems a lot better, thanks :)

@benelliott
Copy link
Author

benelliott commented Nov 26, 2021

Hi @alan-agius4, after using your updated tsconfig I was able to publish my library. However, I have a new problem for downstream apps and I'm not sure if it's due to a related bug, or something else entirely.

The library itself (whose code I am unfortunately unable to share) consists of multiple secondary entrypoints. One of these entrypoints uses a default import of a private dependency of the app, moment-mini-es6:

(library source code)

import moment from 'moment-mini-es6';
...
const momentCtor = dateSelection.utc ? moment.utc : moment;

The library itself also includes a demo project. If I run ng serve or ng build on the library/demo project, I can see that the CLI converts this import line into

(library demo app compiled output)

  var momentCtor = dateSelection.utc ? moment_mini_es6__WEBPACK_IMPORTED_MODULE_0__["default"].utc : moment_mini_es6__WEBPACK_IMPORTED_MODULE_0__["default"];

Now, when I distribute the library and import it in my downstream app, I can see the following in the library's fesm2020 compiled output:

(library APF compiled output)

import moment from 'moment-mini-es6';
const momentCtor = dateSelection.utc ? moment.utc : moment;

Everything up to now looks fine to me. However when I ng serve the downstream app I get the following error:

ERROR TypeError: momentCtor is not a function

If I look at the build output for the app, I see this:

(downstream app compiled output)

  const momentCtor = dateSelection.utc ? moment_mini_es6__WEBPACK_IMPORTED_MODULE_0__.utc : moment_mini_es6__WEBPACK_IMPORTED_MODULE_0__;

The problem seems to be that the CLI/Webpack is not adding the ["default"] suffix to the compiled import reference. If I set a breakpoint I can see that the import contains the right stuff at runtime, just under the default member.

Do you know if this is a configuration issue?

Thanks for your help.

===

Update: since I control moment-mini-es6, I tried altering it to build a Webpack UMD library from a TypeScript source file, making sure that the package.json module and types fields were populated correctly, but it didn't seem to change anything.

@alan-agius4
Copy link
Member

The name moment-mini-es6 is actually rather misleading since is not an ES6 module, but rather a CommonJS module and hence it's targeted to be consumed in a Node.js enviorment. This package exposes a default property exports.default. Don't confuse this with export default as these are very different.

The exports.default will allow you to write syntax like the below;

import moment from 'moment-mini-es6';

The catch is that the above will only work if it is downlevelled to CJS and can never work in full ESM scenario.

var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const moment_mini_es6_1 = __importDefault(require("moment-mini-es6"));
console.log(moment_mini_es6_1.default);

You can also try this quite easily in Node, without any bundler involved.

test.mjs

import m from 'moment-mini-es6';
console.log(m);

Run the above script

node test.mjs
{
  default: [Function: c] {
    momentProperties: [],
    suppressDeprecationWarnings: false,
    deprecationHandler: null,
    parseTwoDigitYear: [Function (anonymous)],
    createFromInputFallback: [Function (a...

@benelliott
Copy link
Author

Thanks a lot - that library was a shim I had to add a long time ago, but removing it and just calling the underlying moment-mini library's default export (with allowSyntheticDefaultImports: true) seems to work completely fine.

@shuZro

This comment has been minimized.

@benelliott

This comment has been minimized.

@alan-agius4

This comment has been minimized.

@shuZro

This comment has been minimized.

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

3 participants