When using Sass files with module import references in the esbuild-based browser application
builder, the module resolution attempts will now be cached in memory. This caching is only
local to each entry Sass file currently. However, this may be expanded to encompass all Sass
entries within a build in the future. In addition to caching the entire resolution attempt,
individual package root resolution is also cached for deep import attempts. This is useful
for packages (such as `@material/*`) which deep import to multiple different files in the
same package.
With this change combined with the previous lexer change, package managers (pnpm & Yarn PnP)
that require workarounds for functioning resolution will now perform at an equivalent level
to other package managers.
To correctly resolve a package based import reference in a Sass file with pnpm or Yarn PnP, the importer
file path must be known. Unfortunately, the Sass compiler does not provided the importer file to import plugins.
Previously to workaround this issue, all previously resolved stylesheets were tried as the importer path. This
allowed the stylesheets to be resolved but it also could cause a potentially large increase in build time due
to the amount of previous stylesheets that would need to be tried. To avoid the performance impact and to also
provide more accurate information regarding the importer file, a lexer is now used to extract import information
for a stylesheet and inject the importer file path into the specifier. This information is then extracted from the
import specifier during the Sass resolution process and allows the underlying package resolution access to a viable
location to resolve the package for all package managers. This information is currently limited to specifiers
referencing the `@angular` and `@material` package scopes but a comprehensive pre-resolution process may be added
in the future.
When optimizing a CommonJS exported enum, the build optimizer enum wrapping pass was previously
dropping the `exports` object assignment from the enum wrapper function call expression. This
would not occur with application code but is possible with library code that was built with
TypeScript and shipped as CommonJS.
Assuming the following TypeScript enum:
```
export enum ChangeDetectionStrategy {
OnPush = 0,
Default = 1,
}
```
TypeScript 5.1 will emit an exported enum for CommonJS as follows:
```
exports.ChangeDetectionStrategy = void 0;
var ChangeDetectionStrategy;
(function (ChangeDetectionStrategy) {
ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush";
ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default";
})(ChangeDetectionStrategy || (exports.ChangeDetectionStrategy = ChangeDetectionStrategy = {}));
```
The build optimizer would previously transform this into:
```
exports.ChangeDetectionStrategy = void 0;
var ChangeDetectionStrategy = /*#__PURE__*/ (() => {
ChangeDetectionStrategy = ChangeDetectionStrategy || {};
ChangeDetectionStrategy[(ChangeDetectionStrategy["OnPush"] = 5)] = "OnPush";
ChangeDetectionStrategy[(ChangeDetectionStrategy["Default"] = 8)] = "Default";
return ChangeDetectionStrategy;
})();
```
But this has a defect wherein the `exports` assignment is dropped. To rectify this situation, the build optimizer will now transform the code into:
```
exports.ChangeDetectionStrategy = void 0;
var ChangeDetectionStrategy = /*#__PURE__*/ (function (ChangeDetectionStrategy) {
ChangeDetectionStrategy[(ChangeDetectionStrategy["OnPush"] = 0)] = "OnPush";
ChangeDetectionStrategy[(ChangeDetectionStrategy["Default"] = 1)] = "Default";
return ChangeDetectionStrategy;
})(ChangeDetectionStrategy || (exports.ChangeDetectionStrategy = ChangeDetectionStrategy = {}))
```
This retains the `exports` assignment.
The esbuild plugin used within the esbuild-based browser application builder will now use the newly
introduced internal `supportJitMode` AOT compiler option to disable the emit of NgModule scope metadata
functions within the output code. This removes the need to perform an additional transformation of the
AOT compiler generated code to immediately remove the metadata. The Angular CLI neither previously nor currently
supports hybrid AOT/JIT mode. In the future if this support situation changes, additional behavior may
be added control the internal `supportJitMode` option.
When overriding module resolution on a TypeScript Host object, TypeScript will not
automatically create a resolution cache for the Host. Within the application build system
the TypeScript resolution is only overrided if file replacements are used. A resolution
cache is now manually created and added to the TypeScript Host when file replacements are
present.
This commit adds an `ssr` option to the application builder, this can be either a `boolean` or an `object` with an `entryPoint` property.
In the future, server bundles will only be emitted when the ssr option is truthy, as unlike SSR, SSG and AppShell do not require the server bundles to be written to disk.
The `browserslist` package is only needed in the custom Babel application preset if
the `supportedBrowsers` option is specified. This option is not used within the esbuild-
based browser application builder. The `browserslist` is now lazily imported only when
needed and avoids the overhead of loading browser support data when not needed by the build.
When using the esbuild-based browser application builder, stylesheets that do not need any
postcss processing will now skip the postcss step of the stylesheet build pipeline. Currently,
only Tailwind CSS leverages postcss and Tailwind CSS is an opt-in feature. As a result, postcss
will only be used if Tailwind CSS is configured for the project and a stylesheet contains one or
more of the directives/functions specific to Tailwind as provided by https://tailwindcss.com/docs/functions-and-directives.
This change should be most beneficial for component stylesheets which will rarely contain Tailwind
specific rules that need additional processing.
This commit introduces experimental support to pre-render (SSG) and app-shell generation to the new application builder.
- `appShell`: option which can have a value of `true` or `false` has been added to support generating an app-shell.
- `prerender`: option which can have a value of `true`, `false` or an object with the below listed properties can be used to static render pages;
- `routes`: Array of routes to render.
- `discoverRoutes`: Whether the builder should statically discover routes.
- `routesFile`: The path to a file containing routes separated by newlines.
This `resourcesOutputPath` option is removed from the application builder. Instead the CSS resources will always be emitted in a directory named `media`. This is preparation to output server and browser bundles in different directories.
When using the esbuild-based application builder, some plugins may return watch file
lists that contain POSIX paths on Windows systems. This can cause the file watcher
to not correctly invalidate files that need to be processed during a rebuild. All
watch files are now normalized prior to being added to the in-memory cache to avoid
this problem.
Postcss's directory dependency message can use a glob pattern to reflect that multiple files
within a given directory should be watched. When calculated the complete file set, the paths
must be absolute to ensure that the watch system correctly invalidates the stylesheet being
processed.
As of esbuild v0.18.9, vendor prefixing of CSS is now supported. The esbuild target option
is generated from a project's browserslist and the vendor prefixing will reflect the configured
browsers for a project. This improvement allows for the removal of the postcss autoprefixer
plugin from the build pipeline. This can provide a performance benefit for projects especially
when project stylesheets contain nothing that would require prefixing since postcss processing can
potentially be skipped completely.
As of esbuild v0.18.8, async generators can be downleveled when not supported. This improvement
allows for the removal of the babel plugins to perform the async generator downleveling that were
previously used. This can provide a performance benefit for cases of async generator usage in
application and third-party library code.
The esbuild plugin used within the esbuild-based browser application builder will not use the
newly introduced internal `supportTestBed` AOT compiler option to disable the emit of class
metadata functions within the output code. This removes the need to perform an additional
transformation of the AOT compiler generated code to immediately remove the class metadata.
The class metadata is only needed when using TestBed with AOT generated code but testing
infrastructure within the CLI only performs unit-testing in JIT mode. In the future event,
that AOT enabled unit-testing is supported, this compiler option can be enabled for test
related builds.
A recent change to better support Tailwind CSS in watch mode unintentionally caused part
of the watch files list for stylesheets to be ignored when Tailwind and/or autoprefixer
were required to be executed. This resulted in rebuilds occurring but all stylesheet changes
were not fully propagated to the development server. This has now been corrected.
When a preload hint is added for a stylesheet that is referenced via an `@import` that has an URL that
does not contain a file extension, an `as` attribute is now correctly added to the hint to ensure that
the stylesheet is loaded properly. This case can happen when a font service URL is imported within a
initial stylesheet.
The development `NG_BUILD_MANGLE` environment variable is now supported when using the
esbuild-based browser application builder. This environment variable is intended only
for Angular CLI development and test purposes.
When using prebundling with the Vite-based development server, the Angular linker will now
correctly emit JIT module scope information. This information is required in JIT mode for
NgModules to successfully be used in an application.
Postcss plugins may provide result messages that contain stylesheet dependencies that should
be watched and should trigger a rebuild of the stylesheet being processed. These files will
now be linked to the stylesheet and will allow the provided file dependencies to be
watched and in-memory caches to be invalidated. Both the `dependency` and `dir-dependency`
postcss messages are supported.
The `cacache` package was only minimally used within the font inlining post-build
processing. The usage has now been replaced with direct filesystem access and key
hashing to cache any font files. This not only lowers the overall dependency count
but also provides a small performance improvement by removing the need to resolve,
load, and evaluate additional JavaScript at build time.
When using the esbuild-based browser application builder in watch mode (including `ng serve`),
all input files provided by the bundler via the internal metafile information will now be
watched and will trigger rebuilds if changed. This allows for files outside of the TypeScript
compilation that are also outside of the project source root to be watched. This situation
can be encountered in monorepo setups where library code is directly referenced within an application.
Currently, for RxJS v6, no conditions are available, and the ESBuild
pipeline will select the ES5 distribution based on the `module` main
field. This is fine in most cases, but applications could benefit from
better optimization with the use of the ES2015 output + there are
certain code differences that currently would cause runtime breakages
when e.g. `rxjs/testing` is used.
See: https://github.com/angular/angular-cli/issues/25405 for more details.
Fixes#25405.
esbuild 0.18.2 contains a fix that removes the need for the workaround of disabling
support for static class blocks.
Related issue: https://github.com/evanw/esbuild/issues/2950