-
Notifications
You must be signed in to change notification settings - Fork 24.8k
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
Generate extra imports in local compilation mode for bundling purposes #53543
Conversation
6f13197
to
4350666
Compare
1791630
to
c7b20e7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leaving some comments here if we end up going with this approach. One thing I want us to consider is using the existing "aliasing" logic that is also used for full compilation. This would feel more natural and maybe avoid lots of extra code. Have you spent some time thinking about this? I feel like this would be better if we can get it to work somehow. We'd just need to resolve the scopes as much as possible (which is what are kind of doing with this PR already)
https://github.com/angular/angular/blob/main/packages/compiler-cli/src/ngtsc/scope/src/local.ts#L540
packages/compiler-cli/src/ngtsc/typecheck/src/type_check_file.ts
Outdated
Show resolved
Hide resolved
packages/compiler-cli/src/ngtsc/annotations/ng_module/src/handler.ts
Outdated
Show resolved
Hide resolved
c7b20e7
to
1492e71
Compare
Is this the API that generated re-exports ? We want to turn this off ideally to allow interop between local and global. I already sent you a doc for that. |
This would be even better, either re-using that logic, or disabling it completely sounds even better. |
8f802bf
to
5faa37d
Compare
packages/compiler-cli/src/ngtsc/annotations/ng_module/src/handler.ts
Outdated
Show resolved
Hide resolved
3ecb305
to
401354d
Compare
@pmvald do we actually still need this PR if we disable extra imports in global compilation? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Caretaker note: No need for public API approval since this is a compiler option and the compiler is not considered as part of the public API (and it's a new option)
…ker` in the compilation workflow (#53543) This commit includes a skeleton of how the tool `LocalCompilationExtraImportsTracker` is used in the overall compilation workflow end-to-end. First of all, a new option `generateExtraImportsInLocalMode` is added, whose presence will make `LocalCompilationExtraImportsTracker` part of the compilation process. When this option is set an instance of `LocalCompilationExtraImportsTracker` is created within the NgCompiler. Then it is passed to the Ivy transformer and plumbed all the way down and the extra imports registered in it are added to the `ImportManager` instances before the imports are added from `ImportManager` to the generated file. This required adding a new method `generateSideEffectImport` to the `ImportManager`, which is an empty method and will be implemented in the subsequent commits. This commit expected to make no change in the compilation behavior as the methods are not implemented yet. PR Close #53543
As the first step, the import manager's `generateSideEffectImport` method is implemented to enable it to store info for side effect imports. Next, the helper `addImports` is modified to be able to generate correct statement for side effect imports. These changes will be tested in the subsequent commits when these tools are used to generate an actual extra import for the generated file. PR Close #53543
…#53543) With option `generateExtraImportsInLocalMode` set in local compilation mode, the compiler generates extra side effect imports using this rule: any external module from which an identifier is imported into an NgModule will be added as side effect import to every file in the compilation unit. To illustrate this better assume the compilation unit has source files `a.ts` and `b.ts`, and: ``` // a.ts import {SomeExternalStuff} from 'path/to/some_where'; import {SomeExternalStuff2} from 'path/to/some_where2'; ... @NgModule({imports: [SomeExternalStuff]}) ``` then the extra import `import "path/to/some_where"` will be added to both `a.js` and `b.js`. Note that this is not the case for `import "path/to/some_where2"` though, since the symbol `SomeExternalStuff2` is not imported into any NgModule. The math behind this mechanism is, in local compilation mode we cannot resolve component external dependencies fully. For example if a component in `a.ts` uses an external component defined in an external file `some_external_comp.ts` then we can generate the import to this file in `a.js`. Instead, we want to generate an import to a file that "gurantees" that `a.js` is placed after `some_external_comp.js` in the bundle. Now since the component in `some_external_comp.ts` is used in `a.ts`, then there must be a chain of imports starting from the NgModule that declares the component in `a.ts` to the component in `some_external_comp.ts`. This chain means some file in the same compilation unit as `a.ts` should import some external NgModule which includes `some_external_comp.ts` in its transitive closure and import it to some NgModule. So by adding this import to `a.js` we ensure that the bundling will have the right order. PR Close #53543
This PR was merged into the repository by commit 64fa571. |
…al mode when `generateExtraImportsInLocalMode` is set (#53543) In this commit the resolve method for components is run fully when the option `generateExtraImportsInLocalMode` is set. This is because we need local component depedencies in order to generate extra imports causing by them. This requires cutting some resolve phase logics that are unnecessary in local mode, such as diagnostics. PR Close #53543
…encies in local mode (#53543) With option `generateExtraImportsInLocalMode` set, in local mode the compiler generates extra imports for each component local dependencies. Here local dependencies means all component's dependencies within the same compilation unit. To achieve this, the compiler performs a "local version" of its regular static analysis to find each component's deps, and these deps are used to generate extra side effect imports. PR Close #53543
… when cycle is introduced (#53543) At the moment the extra import generation in local compilation mode fails if these extra imports produce a cycle. To handle this, the cycle handling strategy is updated for local compilation, and following the behaviour in the full compilation mode, the compiler does not generate extra import if it leads to cycle and instead leave things to the runtime. PR Close #53543
The tracker is responsible for registering the extra imports during the analysis and resolve compiler phases, and later to be used by the transformer to get a list of extra imports to be generated for each source file. This commit only contains the API, and the actual implementation for each method will be done in subsequent commits where an application of that method is available and so tests can be written for the implementation. PR Close angular#53543
…ker` in the compilation workflow (angular#53543) This commit includes a skeleton of how the tool `LocalCompilationExtraImportsTracker` is used in the overall compilation workflow end-to-end. First of all, a new option `generateExtraImportsInLocalMode` is added, whose presence will make `LocalCompilationExtraImportsTracker` part of the compilation process. When this option is set an instance of `LocalCompilationExtraImportsTracker` is created within the NgCompiler. Then it is passed to the Ivy transformer and plumbed all the way down and the extra imports registered in it are added to the `ImportManager` instances before the imports are added from `ImportManager` to the generated file. This required adding a new method `generateSideEffectImport` to the `ImportManager`, which is an empty method and will be implemented in the subsequent commits. This commit expected to make no change in the compilation behavior as the methods are not implemented yet. PR Close angular#53543
…lar#53543) As the first step, the import manager's `generateSideEffectImport` method is implemented to enable it to store info for side effect imports. Next, the helper `addImports` is modified to be able to generate correct statement for side effect imports. These changes will be tested in the subsequent commits when these tools are used to generate an actual extra import for the generated file. PR Close angular#53543
…able (angular#53543) This is to allow testing this option using bazel PR Close angular#53543
…angular#53543) With option `generateExtraImportsInLocalMode` set in local compilation mode, the compiler generates extra side effect imports using this rule: any external module from which an identifier is imported into an NgModule will be added as side effect import to every file in the compilation unit. To illustrate this better assume the compilation unit has source files `a.ts` and `b.ts`, and: ``` // a.ts import {SomeExternalStuff} from 'path/to/some_where'; import {SomeExternalStuff2} from 'path/to/some_where2'; ... @NgModule({imports: [SomeExternalStuff]}) ``` then the extra import `import "path/to/some_where"` will be added to both `a.js` and `b.js`. Note that this is not the case for `import "path/to/some_where2"` though, since the symbol `SomeExternalStuff2` is not imported into any NgModule. The math behind this mechanism is, in local compilation mode we cannot resolve component external dependencies fully. For example if a component in `a.ts` uses an external component defined in an external file `some_external_comp.ts` then we can generate the import to this file in `a.js`. Instead, we want to generate an import to a file that "gurantees" that `a.js` is placed after `some_external_comp.js` in the bundle. Now since the component in `some_external_comp.ts` is used in `a.ts`, then there must be a chain of imports starting from the NgModule that declares the component in `a.ts` to the component in `some_external_comp.ts`. This chain means some file in the same compilation unit as `a.ts` should import some external NgModule which includes `some_external_comp.ts` in its transitive closure and import it to some NgModule. So by adding this import to `a.js` we ensure that the bundling will have the right order. PR Close angular#53543
…ngular#53543) When option `generateExtraImportsInLocalMode` is set, we need to compute component local depednecies in order to generate extra imports related to them. At the same time running the register phase in general is harmless in local compilation. So we run it anyway. PR Close angular#53543
…al mode when `generateExtraImportsInLocalMode` is set (angular#53543) In this commit the resolve method for components is run fully when the option `generateExtraImportsInLocalMode` is set. This is because we need local component depedencies in order to generate extra imports causing by them. This requires cutting some resolve phase logics that are unnecessary in local mode, such as diagnostics. PR Close angular#53543
…encies in local mode (angular#53543) With option `generateExtraImportsInLocalMode` set, in local mode the compiler generates extra imports for each component local dependencies. Here local dependencies means all component's dependencies within the same compilation unit. To achieve this, the compiler performs a "local version" of its regular static analysis to find each component's deps, and these deps are used to generate extra side effect imports. PR Close angular#53543
… when cycle is introduced (angular#53543) At the moment the extra import generation in local compilation mode fails if these extra imports produce a cycle. To handle this, the cycle handling strategy is updated for local compilation, and following the behaviour in the full compilation mode, the compiler does not generate extra import if it leads to cycle and instead leave things to the runtime. PR Close angular#53543
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
The particular way that bundling is done in g3 requires that prod and dev sources have same or compatible import statements. Since the dev sources are compiled in local mode, then this requires local compilation to generate extra imports which imply the ones generated in full compilation mode due to resolving component's dependencies.
A new g3 specific option
generateExtraImportsInLocalMode
is added, which when is set and the compilation mode is local the compiler will generate extra imports.The extra imports are generated in a way that the the prod sources can be bundled based on these extra imports plus user written imports without issue. This requires to perform static analysis as much as possible in local mode to resolve the component dependencies that are within the same target. For this to happen it is assumed that we are using local compilation mode per target, and not when per single (which is the case in g3). For external deps, we spread all external imports that could be candidate for exposing an external dependency to all the all the files in the compilation unit.
TGP when local compilation mode is enabled for dev sources plus this change: link
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
Issue Number: N/A
What is the new behavior?
Does this PR introduce a breaking change?
Other information