To minimize ambiguity, the update related log messages for the development server now consistently
indicate that the page reload, HMR update, or otherwise has actually been sent to any connected clients.
This changes enables wrapping classes in side-effect free modules that make use of custom decorators when using the esbuild based builders so that when such classes are unused they can be treeshaken.
The Vite-based development server restricts filesystem access by default. However, assets
configured by the build option `assets` are intended to be accessible by the application at
runtime. To ensure that these files are accessible, the allow list will now explicitly include
all configured assets found during the build.
When using the `application` or `browser-esbuild` builder in watch mode on Windows, the project root
will now be watched by default. This provides a workaround for users of Visual Studio which uses a
file save mechanism that causes the watch mode to not correctly trigger. By watching the entire
project root, this problem is avoided. However, this may result in additional rebuilds due to changes
of unrelated files in the project root.
This behavior can be disabled using the environment variable `NG_BUILD_WATCH_ROOT=0`. On non-Windows
platforms, disabled is the default.
Addresses #26437
Prior to this change a postcss instance was created for every component style. This can cause a performance overhead when using tailwindcss, since each tailwind instance would do multiple IO calls to get the list of files specified in the `content` field.
The generated HTML files for the application were previously not included in the hash calculations for
the service worker. This has now been corrected and the index file for an application will not be included
when service worker support is enabled via the `serviceWorker` option.
The path comparisons for the TypeScript and AOT file reference tracking now use the native path normalization
functions. This avoids issues where the TypeScript paths which use POSIX separators may not correct match
system paths. The file reference tracking is used to trigger updates to both web workers as well as component
stylesheets that have preprocessor (Sass/Less/etc.) dependencies.
With the Vite-based development server, the build pipeline itself watches for files
and rebuilds the relevant parts of the application as needed. The Vite file watching
is unneeded and was previously setup to ignore all files. This worked but was not
ideal as chokidar was still initialized inside Vite. However, Vite now supports fully
disabling the file watching by passing `null` for the Vite watch option value.
The application builder logic will now be used when the Vite-based development server is used with a
custom builder. This aligns with the programmatic export of application builder. This allows consistent
behavior for custom builders that use both the application builder and dev server builder APIs.
A unit-test for the application builder has been added to that tests the rebuilds are triggered when
a template error has been introduced in a rebuild. The test also confirms that rebuilds continue to
function after the error has been corrected.
To avoid potential confusion when updating to v17, the usage warning as been removed
from the `browser-esbuild` builder. The `browser-esbuild` builder is considered stable
and fully supported. This is in addition to the other stable builders: `browser` and
`application`. The `browser-esbuild` builder provides similar behavior to the `browser`
builder but with the performance improvements of the `application` builder. However,
`browser-esbuild` does not have integrated SSR support and will not receive new/future
`application` builder options and features.
For more details on these builders, please see: https://angular.io/guide/esbuild
The TypeScript compiler converts all paths to use POSIX path separators. When on Windows,
this can cause problems when comparing paths from other parts of the build system including
the file watching provided by `chokidar`. The referenced files returned from the TypeScript
compiler are now normalized to the native path format to mitigate this problem. This also
avoids an issue where the same files but with differing path separators were included in
the watch files list on Windows due to the bundler using native paths and TypeScript using
converted paths.
The path comparisons for the TypeScript emit file lookups now use the native path normalization
functions. This removes the special handling previously used and better ensures that cache checks
are valid. The separate babel cache Map has also been combined with the already present memory
load cache within the Angular plugin. This removes the need for extra handling of another Map and
allows it to use the common logic of the load cache. To support this usage, the load cache will
also now automatically include the request path in the file dependencies if the request is from
the `file` namespace. This removes the need to manually specify the request path file for each
load result return value.
When using the `application` builder, a new `loader` option is now available for use.
The option allows a project to define the type of loader to use with a specified file extension.
A file with the defined extension can then used within the application code via an import statement
or dynamic import expression, for instance.
The available loaders that can be used are:
* `text` - inlines the content as a string
* `binary` - inlines the content as a Uint8Array
* `file` - emits the file and provides the runtime location of the file
* `empty` - considers the content to be empty and will not include it in bundles
The loader option is an object-based option with the keys used to define the file extension and the values used
to define the loader type.
An example to inline the content of SVG files into the bundled application would be as follows:
```
loader: {
".svg": "text"
}
```
An SVG file can then be imported:
```
import contents from './some-file.svg';
```
Additionally, TypeScript needs to be aware of the module type for the import to prevent type-checking
errors during the build. This can be accomplished with an additional type definition file within the
application source code (`src/types.d.ts`, for example) with the following or similar content:
```
declare module "*.svg" {
const content: string;
export default content;
}
```
The default project configuration is already setup to use any type definition files present in the project
source directories. If the TypeScript configuration for the project has been altered, the tsconfig may
need to be adjusted to reference this newly added type definition file.
When using the `application` and/or `browser-esbuild` builders, stylesheets
that generate errors will now have the errors cached between rebuilds during
watch mode (include `ng serve`). This not only avoids reprocessing files that
contain errors and that have not changed but also provides file watching information
from the cache to ensure the error-causing files are properly invalidated.
When using the `application` and/or `browser-esbuild` builders, the current watch files
will be maintained in the event of a build error. This better ensures that files used
in the last build/rebuild that may have caused an error will continue to be watched and
refreshed when later changed. Only when a successful rebuild has occurred will any stale
watch files be removed from the watch list.
If the TypeScript and/or Angular AOT compiler fails to initialize or emit files due to an error,
the shared compilation state between the browser code bundle action and any additional bundle actions
(polyfills, server, etc.) will now carry an error flag to ensure that the additional bundle actions
bypass file emit. The file emit bypass is necessary in these cases to prevent an unintentional and
misleading error about a file not being included in the compilation.
When the `deleteOutputPath` option is enabled (default is enabled), the configured
`outputPath` for the project was previously removed directly. This was problematic
for cases such as when the path was mounted via a Docker setup. To alleviate these
issues, the contents of the output path will now be removed instead. This maintains
the existing output path directory itself but ensures an empty location to place the
new build output.
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