Overview of issues that came up and needed investigation/workarounds:
Description | Workaround? |
---|---|
ng_package rule that implements Angular Package Format breaks for secondary entry-points with factories. See issue. |
โ (needs proposal) |
ng_package rule not working on windows with many rollup globals. See issue |
โ (needs fix) |
ng_module rule does not allow specification of flat module entry-point. See proposal PR to fix this |
โ (proposal; needs review) |
ng_package rule does not support ts_library targets for secondary entry-points. See PR to fix this |
โ (fix landed) |
ng_module rules generate invalid imports for injectables that rely on symbols from flat module bundles. More details below |
โ (needs fix). Very difficult to land upstream. See explanation of the problem to understand why. |
ng_module rules generate invalid imports forinjectables that leak Bazel-specific workspace paths. More details below |
โ (fix in progress; not clear whether it's possible to land) |
The ng_module
bazel rule does not include metadata files when building
a package. For example, if we build material/snack-bar
, the metadata
files of cdk/overlay
are not included.
Just the summary files of the cdk/overlay
are available. This means that
the compilation misses information about the flat module bundle of
cdk/overlay
and uses the summaries to resolve exported symbols.
Since summaries are generated on a per-file basis, there is no
concept of summaries for the dynamically generated flat module
bundle. This means that symbols across different entry-points
will be resolved to their original source file location.
This causes NGC to generate imports to deep files rather than using
the flat module entry-point (which is usually index.js
). e.g.
This is problematic because as per implementation of the Angular
package format, references to other entry-points are only
possible if done through the actual entry-point (no deep imports).
This is necessary to support the individual package.json
fields
for deeply-referenced entry-points (e.g. es2015
, main
, fesm2015
).
Note: here is an isolated reproduction that demonstrates
the issue: https://github.com/devversion/bazel-ngc-wrapped-invalid-imports
This issue does not happen within the current gulp setup because
our subsequent compilations have access to metadata files of
previous entry-points.
e.g. cdk/overlay
is compiled with a flat module bundle and
stored in dist/packages/cdk/overlay/
. Now compilations for
material/snack-bar
can just have a path mapping to dist/packages/cdk/overlay
,
and NGC will be able to properly generate imports through
the flat module bundle entry-point (as it knows that everything
is exported in the entry-point due to the flat module metadata)
It looks like ngc-wrapped
(which is the wrapper for the ng_module
rule), overwrites
the fileExists
method of the host that is passed to NGC.
Modifying the NGC_ASSETS
regular expression in ngc-wrapped
to allow .metadata.json
files to be take into account, fixes the issue. Though it unveils another issue for
the Bazel ng_module
compilations.
Disclaimer: There might be more reasons why metadata files are
not allowed in the Bazel compilations, but this is the one that appears
in thecomponents
repository if we allow metadata files.
Let's consider we fixed the metadata reading issues in ngc-wrapped (as of the
section above). Now that symbols are resolved through metadata (and not through summaries), the StaticSymbolResolver
handles the symbol resolution.
Within the compiler, there seems to be logic to discard metadata of class symbols
which are from previous compilation units:
We don't have this issue in the angular/components
repository with our Gulp setup because
it seems that the issue depends on the generateCodeForLibraries
flag.
The ng_module
rule always it sets generateCodeForLibraries
to false
, while in vanilla
ngc
the flag is enabled by default. If the flag is set to false
, the isLibraryFile
check (see snippet above) will be always true for files from other compilation units and
the metadata will be discarded. Causing the compilations to fail with exceptions like:
Here is a reproduction for that issue: https://github.com/devversion/bazel-ngc-wrapped-invalid-imports#how-to-reproduce-the-bazel-generatecodeforlibaries-issue
Paul Not setting
generateCodeForLibaries
tofalse
would solve the issue, but I
guess the reason we explicitly set it tofalse
is that otherwise compilations would
write genfiles to locations which are out of scope of the current package. Basically
it would break hermeticity of theng_module
rule. It feels wrong to me that
metadata resolution depends on thegenerateCodeForLibraries
flag. The flag is
described to only prevent generation of genfiles for libraries (which makes sense
in bazel to keep hermeticity), but apparently it does more than that.
With the section above, we handled the issue of invalid imports being generated that should
actually resolve to flat module bundle entries.
A second issue with invalid imports comes from the fact that the ng_module
rule always
uses absolute manifest paths for importing symbols that aren't known to the summary
resolver, or static symbol resolver. See the actual code for details.
This issue commonly surfaces when services inject other symbols from the same entry-point. Concrete example in the components focus-trap. The ng_module
rule leaks Bazel specific paths into the release output. This is problematic, and the actual import should be relative since it's part of the same entry-point.
The intent was to fix this for the ng_module
rule, by never using full manifest paths for generated imports within the compilation unit. See: angular#35841 for more details.