Skip to content

fix(@angular/build): declare tslib in the built library package - #34217

Open
thekhegay wants to merge 2 commits into
angular:mainfrom
thekhegay:fix/library-tslib-dependency
Open

thekhegay wants to merge 2 commits into
angular:mainfrom
thekhegay:fix/library-tslib-dependency

Conversation

@thekhegay

Copy link
Copy Markdown
Contributor

PR Checklist

PR Type

  • Bugfix

What is the current behavior?

Issue Number: #34131

Library builds force importHelpers, and bare specifiers are externalized, so an emitted bundle can carry a live import ... from 'tslib'. generatePackageManifests only passes dependencies through from the source manifest and never creates it, so a library that does not declare tslib itself produces a package with no dependencies field at all. On ng-zorro-antd 34 of 105 bundles import tslib. With a hoisted node_modules it resolves anyway; on a strict layout the consumer gets ERR_MODULE_NOT_FOUND ... 'tslib'.

What is the new behavior?

The built package declares tslib when the library does not, taking the range from @angular/compiler resolved against the workspace. That is the same source ng-packagr reads, so the two builders agree.

A tslib the library already declares, in dependencies or in peerDependencies, is left exactly as it is. When @angular/compiler cannot be resolved nothing is added and the output keeps the dependencies the library declared.

The range is resolved in normalizeOptions, where the builder already reads the filesystem, so generatePackageManifests stays pure and the four new cases are plain unit tests.

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

ng-packagr also moves a peerDependencies.tslib into dependencies with a warning. That is not done here: it is a separate behaviour change and this function has no logger.

I could not run the builder tests locally, so CI is the first run of them.

A library compiles with importHelpers, so a bundle can carry a live
'import ... from tslib' while the library's own manifest declares nothing
and the built package gets no dependencies field at all. On a hoisted
node_modules it resolves anyway; on a strict layout the consumer gets
ERR_MODULE_NOT_FOUND at runtime.

The range comes from @angular/compiler, resolved from the workspace, which
is what ng-packagr reads. A tslib the library already declares, in either
dependencies or peerDependencies, is left alone.

Fixes angular#34131

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request automatically adds the tslib dependency to a library's generated package.json if it is not already declared, resolving the version range from @angular/compiler in the workspace. The feedback recommends extending this check to also ignore tslib if it is already defined in optionalDependencies, and adding a corresponding unit test to verify this behavior.

Comment thread packages/angular/build/src/builders/library/pipeline/package-manifests.ts Outdated
@clydin

clydin commented Oct 1, 2026

Copy link
Copy Markdown
Member

tslib is rarely needed anymore now that the output is ES2022. Usage of custom decorators (outside of the Angular ones) and explicit resource management are effectively the only cases.

Since most libraries won't need tslib, it could instead be conditionally added by checking bundler metadata to determine if tslib has been imported by any output chunks.

* which is what ng-packagr reads too. A missing or unreadable manifest is not an error: the
* output then keeps exactly the dependencies the library declared itself.
*/
function resolveAngularTslibRange(workspaceRoot: string): string | undefined {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since tslib is both backward and forward compatible, using the latest version of the library should be sufficient here.
There's also no guarantee that tslib will even be present in @angular/compiler or that it is resolvable from the workspace root.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants