When using the `application` builder, a parallel TS/NG compilation is used that is run inside a Node.js Worker.
This Worker by default uses an Atomics-based wait loop to improve performance while waiting for messages. This
loop relies on the synchronous API `receiveMessageOnPort`. While this works well in Node.js, the web container
execution environment does not currently support passing transferable objects via `receiveMessageOnPort`. Attempting
to do so will cause a serialization error and a failed application build. To avoid this problem, the wait loop
optimization is disabled when the web container execution environment is detected. This change is only needed
for the TS/NG compilation as no other parallel operation within the build system currently uses `receiveMessageOnPort`
with transferable objects.
When using the `application` builder with SSR enabled and the `allowJs` TypeScript option,
the build would previously generate warnings about undefined imports. This was caused by
the recently introduced initialization error handling that was not accounting for the early
exit of the SSR compiler plugin's `onStart` hook. This early exit prevent the error status
checking from completing which resulted in the SSR plugin load hook assuming an error had
occurred. This in turn caused JavaScript files that were not imported into TypeScript
files to be returned as empty content to avoid the not found error message. To remedy this
situation, the error status is now also set during the SSR early exit.
When using the `application` builder, exceptions thrown by the AOT compiler will
now be converted into error diagnostics. This allows for more actionable information
to be displayed in the build output. It also prevents the typically incorrect "missing
file" error from occurring in these cases which previously occurred due to TypeScript
files not being emitted as a result of the compiler failure.
When using the `application` or `browser-esbuild` builders, a parallel TS/NG compilation will
be used by default via a Node.js Worker. However, when used inside a Web Container, the
build will fail to initialize the compilation instance due to what appears to be a defect
within Web containers involving the transfer/serialization of a MessageChannel's MessagePort
objects. To avoid this problem, the parallel compilation is disabled by default when the
build system detects it is being executed from within a Web Container. A parallel compilation
can still be forced by using the `NG_BUILD_PARALLEL_TS=1` environment variable.
Prior to this commit, the pre-bundling of dependencies was being invalidated for each build. This is because vite uses parts of the config among other things to generate a hash. In our case the config was not always consistent for the same project between different builds.
The main 2 problems areas were:
- Random `root` path
- `include` and `exclude` arrays were not always in the same order.
It appears that Vite currently, has a number of limitation/bugs when using `optimizeDeps` for SSR bundles.
Currently this causes a number of issues:
- Deps are re-optimized everytime the server is started.
- Added deps after a rebuild are not optimized.
- Breaks RxJs (Unless it is added as external). See: #26235
We should follow up with Vite and try to get this solved as this would be a nice feature to use.
Closes#26235 and #26234
Currently, externalMetadata arrays get appended the same items over and over again on every rebuild. This commit cleans the array before it appending the new values.
The `JavaScriptTransformer` class that is responsible for Angular linking and several build optimization
transformations can now be configured to track and reuse previous and pending transformation requests.
This allows for cases where multiple consumers of the class will not cause repeat transformation actions.
Pending results will be stored if the constructor option `reuseResults` is enabled. If two transformation
requests are issued for the same file, the same underlying result will be provided to each. This behavior
currently only applies to file transformation requests.
Vite will only start dependency optimization of SSR modules when the first request comes in.
In some cases, this causes a long waiting time. To mitigate this, we call `ssrLoadModule` to initiate this process before the first request.
This fixes the following warnings
```
Cannot optimize dependency: url, present in 'ssr.optimizeDeps.include'
Cannot optimize dependency: path, present in 'ssr.optimizeDeps.include'
```
The in-memory ESM loader hooks have been adjusted to avoid potential errors when
resolving and loading the bundled server code during prerendering. These errors
could result in hard to diagnose build failures. E2E testing via the deprecated
protractor builder, would silently exit, for instance. To ensure on disk files
including node modules are resolved from the workspace root, a virtual file root
is used for all in memory files. This path does not actually exist but is used to
overlay the in memory files with the actual filesystem for resolution purposes.
A custom URL schema (such as `memory://`) cannot be used for the resolve output
because the in-memory files may use `import.meta.url` in ways that assume a file
URL. `createRequire` from the Node.js `module` builtin is one example of this usage.
When using the esbuild-based builders (`application`/`browser-esbuild`), the secondary Angular compilations
will wait for the primary compilation to finish prior to bundling. This can potentially occur for polyfills
that contain TypeScript files and the server code if enabled. However, if the Angular compilation throws
an error during the start of the bundling process, the secondary compilations were never notified and instead
would wait indefinitely. To avoid this situation, the compilations will now always be notified at the end of
the compilation which will occur regardless. The build error that will be generated in these situations is
currently not ideal and more verbose than needed but will provide information pertaining to the root cause.
This commit splits the retrieval of external dependencies into two. Server imports and browser imports. This is so that we avoid vite from optimizing server or browser only dependencies twice.
This also fixes an issue were in some cases Vite would issue a warning like `Cannot optimize dependency: path, present in 'optimizeDeps.include'`. This was caused because of server only dependencies ended up trying to be optimized for a browser build.
When using the experimental programmatic API for the development server with an esbuild-based
builder (`application`/`browser-esbuild`), express compatible middleware can now be added.
Also, the index HTML transformer that previously only worked with the Webpack-based development
server is also now enabled.
However, usage of these options may result in unexpected application output and/or build failures.
They are also not officially supported and SemVer guarantees are not present.
Stable and supported methods for build process extension are being evaluated for a future release.
The dynamically compiled ESM import helper is now cached to prevent the need
to recompile the helper function everytime a load ESM helper call is made.
This helper is currently used to workaround dynamic import limitations with
the TypeScript compilation output. Once the build process is updated, it will
no longer be required.