This function needs to deduplicate the paths that are found from the
paths mappings. Previously this deduplication was not linear and also
called the expensive `relative()` function many times.
This commit, suggested by @JoostK, reduces the complexity of the deduplication
by using a tree structure built from the segments of each path.
PR Close#36881
Now that `ngcc/src/ngcc_options` imports `FileWriter` type, there is a
circular dependency detected by the `ts-circular-deps:check` lint check:
```
ngcc/src/ngcc_options.ts
→ ngcc/src/writing/file_writer.ts
→ ngcc/src/packages/entry_point_bundle.ts
→ ngcc/src/ngcc_options.ts
```
This commit moves the `PathMappings` type (and related helpers) to a
separate file to avoid the circular dependency.
NOTE:
The circular dependency was only with taking types into account. There
was no circular dependency for the actual (JS) code.
PR Close#36626
In cc4b813e75 the `getBasePaths()`
function was changed to log a warning if a `basePath()` computed from
the `paths` mappings did not exist. It turns out this is a common and
accepted scenario, so we should not log warnings in this case.
Fixes#36518
PR Close#36525
Previously, a bad baseUrl or path mapping passed to an `EntryPointFinder`
could cause the original `sourceDirectory` to be superceded by a higher
directory. This could result in none of the sourceDirectory entry-points being
processed.
Now missing basePaths computed from path-mappings are discarded with
a warning. Further, if the `baseUrl` is the root directory then a warning is
given as this is most likely an error in the tsconfig.json.
Resolves#36313Resolves#36283
PR Close#36331
The previous optimizations in #35756 to the
`DirectoryWalkerEntryPointFinder` were over zealous
with regard to packages that have entry-points stored
in "container" directories in the package, where the
container directory was not an entry-point itself.
Now we will also walk such "container" folders as long
as they do not contain `.js` files, which we regard as an
indicator that the directory will not contain entry-points.
Fixes#36216
PR Close#36305
This commit simplifies the `DirectoryWalkerEntryPointFinder` inter-method
calling to make it easier to follow, and also to support controlling
walking of a directory based on its children.
PR Close#36305
Previously we only searched for package paths below the set of `basePaths`
that were computed from the `basePath` provided to ngcc and the set of
`pathMappings`.
In some scenarios, such as hoisted packages, the entry-point is not within
any of the `basePaths` identified above. For example:
```
project
packages
app
node_modules
app-lib (depends on lib1)
node_modules
lib1 (depends on lib2)
node_modules
lib2 (depends on lib3/entry-point)
lib3
entry-point
```
When CLI is compiling `app-lib` ngcc will be given
`project/packages/app/node_modules` as the `basePath.
If ngcc is asked to target `lib2`, the `targetPath` will be
`project/node_modules/lib1/node_modules/lib2`.
Since `lib2` depends upon `lib3/entry-point`, ngcc will need to compute
the package path for `project/node_modules/lib3/entry-point`.
Since `project/node_modules/lib3/entry-point` is not contained in the `basePath`
`project/packages/app/node_modules`, ngcc failed to compute the `packagePath`
correctly, instead assuming that it was the same as the entry-point path.
Now we also consider the nearest `node_modules` folder to the entry-point
path as an additional `basePath`. If one is found then we use the first
directory directly below that `node_modules` directory as the package path.
In the case of our example this extra `basePath` would be `project/node_modules`
which allows us to compute the `packagePath` of `project/node_modules/lib3`.
Fixes#35747
PR Close#36249
The `DirectoryWalkerEntryPointFinder` has to traverse the
entire node_modules library everytime it executes in order to
identify the entry-points that need to be processed. This is
very time consuming (several seconds for big projects on
Windows).
This commit changes the `DirectoryWalkerEntryPointFinder` to
use the `EntryPointManifest` to store the paths to entry-points
that were found when doing this initial node_modules traversal
in a file to be reused for subsequent calls.
This dramatically speeds up ngcc processing when it has been run once
already.
PR Close#35931
This reduces the time that `findEntryPoints` takes from 9701.143ms to 4177.278ms, by reducing the file operations done.
Reference: #35717
PR Close#35756
This commit adds a new ngcc configuration, `ignorableDeepImportMatchers`
for packages. This is a list of regular expressions matching deep imports
that can be safely ignored from that package. Deep imports that are not
ignored cause a warning to be logged.
// FW-1892
Fixes#35615
PR Close#35683
Previously if there were two path-mapped libraries that are in
different directories but the path of one started with same string
as the path of the other, we would incorrectly return the shorter
path - e.g. `dist/my-lib` and `dist/my-lib-second`. This was because
the list of `basePaths` was searched in ascending alphabetic order and
we were using `startsWith()` to match the path.
Now the `basePaths` are searched in reverse alphabetic order so the
longer path will be matched correctly.
// FW-1873
Fixes#35536
PR Close#35592
The `TargetedEntryPointFinder` must work out what the
containing package is for each entry-point that it finds.
The logic for doing this was flawed in the case that the
package was in a path-mapped directory and not in a
node_modules folder. This meant that secondary entry-points
were incorrectly setting their own path as the package
path, rather than the primary entry-point path.
Fixes#35188
PR Close#35227
To support parallel CLI builds we instruct developers to pre-process
their node_modules via ngcc at the command line.
Despite doing this ngcc was still trying to set a lock when it was being
triggered by the CLI for packages that are not going to be processed,
since they are not compiled by Angular for instance.
This commit checks whether a target package needs to be compiled
at all before attempting to set the lock.
Fixes#35000
PR Close#35057
ngcc computes a dependency graph of entry-points to ensure that
entry-points are processed in the correct order. Previously only the imports
in source files were analysed to determine the dependencies for each
entry-point.
This is not sufficient when an entry-point has a "type-only" dependency
- for example only importing an interface from another entry-point.
In this case the "type-only" import does not appear in the
source code. It only appears in the typings files. This can cause a
dependency to be missed on the entry-point.
This commit fixes this by additionally processing the imports in the
typings program, as well as the source program.
Note that these missing dependencies could cause unexpected flakes when
running ngcc in async mode on multiple processes due to the way that
ngcc caches files when they are first read from disk.
Fixes#34411
// FW-1781
PR Close#34494
When ngcc is called for a specific entry-point, it has to determine
which dependencies to transitively process. To accomplish this, ngcc
traverses the full import graph of the entry-points it encounters, for
which it uses a dependency host to find all module imports. Since
imports look different in the various bundle formats ngcc supports, a
specific dependency host is used depending on the information provided
in an entry-points `package.json` file. If there's not enough
information in the `package.json` file for ngcc to be able to determine
which dependency host to use, ngcc would fail with an error.
If, however, the entry-point is not compiled by Angular, it is not
necessary to process any of its dependencies. None of them can have
been compiled by Angular so ngcc does not need to know about them.
Therefore, this commit changes the behavior to avoid recursing into
dependencies of entry-points that are not compiled by Angular.
In particular, this fixes an issue for packages that have dependencies
on the `date-fns` package. This package has various secondary
entry-points that have a `package.json` file only containing a `typings`
field, without providing additional fields for ngcc to know which
dependency host to use. By not needing a dependency host at all, the
error is avoided.
Fixes#32302
PR Close#32303
Paths can be mapped directly to files, which was not being taken
into account when computing `basePaths` for the `EntryPointFinder`s.
Now if a `pathMapping` pattern does not exist or is a file, then we try
the containing folder instead.
Fixes#31424
PR Close#30525
Previously, ngcc had to walk the entire `node_modules` tree looking for
entry-points, even if it only needed to process a single target entry-point
and its dependencies.
This added up to a few seconds to each execution of ngcc, which is noticeable
when being run via the CLI integration.
Now, if an entry-point target is provided, only that target and its entry-points
are considered rather than the whole folder tree.
PR Close#30525