The `i18n` project field is used to configure i18n behavior for a project.
The validation code has been reorganized to use two helper functions to
centralize the type validation and exception throwing. This reduces the complexity
of the analysis code as well as removing the need to rely on `@angular-devkit/core`.
This commit removes the legacy Sass implementation previously used with Webpack.
BREAKING CHANGE: The support for the legacy Sass build pipeline, previously accessible via `NG_BUILD_LEGACY_SASS` when utilizing webpack-based builders, has been removed.
When purging stale build cache entries, the `readdir` call will fail if
the cache base path does not exist. This allows for a single check and
the removal of the previous separate `existSync` call. Additionally,
a repeat join call has also been removed during the stale directory check.
The Node.js `node:util` builtin contains a helper (`stripVTControlCharacters`) that
can be used to remove ANSI color characters from a string. Usage removes the need
for a custom helper within the package.
The Node.js async `pipeline` helper function reduces the amount of infrastructure code
needed to pipe HTML content through the parse5 transform stream.
The globally available TextDecoder class will automatically handle the presence of a BOM in
text files when decoding. This allows the removal of the utility function present in the
package to do the same.
To support future package building as ESM, the direct usage of require has now been
removed from the Angular compatibility check code used by various builders.
Additionally, the limited use of `@angular-devkit/core` has also been removed from
the check code as it was only used to adjust string values for error messages which
can be done directly instead.
The latest version of the worker pool package used by the build system (`Piscina`) now
has an option to disable performance timing information. Since the build system does
not currently use that information, disabling it avoids the extra overhead of histogram
creation and usage. This information collection could potentially be enabled conditionally
in the future if needed.
In certain cases, the plugin option may be a string value, as shown in the example below:
```json
{
"plugins": {
"tailwindcss/nesting": "postcss-nesting"
}
}
```
In certain cases, the plugin option may be a string value, as shown in the example below:
```json
{
"plugins": {
"tailwindcss/nesting": "postcss-nesting"
}
}
```
See: https://tailwindcss.com/docs/using-with-preprocessors#nesting
This change implements the capability to display JSON build logs in the terminal instead of a format readable by humans. This is particularly useful for hosting providers, as it allows them to effortlessly access the necessary information without having to parse the JSON configuration.
To enable this output, set the `NG_BUILD_LOGS_JSON=1` environment variable. Additionally, warnings, errors, and logs are automatically colorized when the standard output is a WritableStream. You can disable the colors by using the `FORCE_COLOR=0` environment variable.
```
FORCE_COLOR=0 NG_BUILD_LOGS_JSON=1 ng b
{
"errors": [],
"warnings": [],
"outputPaths": {
"root": "file:///usr/local/test/home//test-project/dist/test-project",
"browser": "file:///usr/local/test/home//test-project/dist/test-project/browser",
"server": "file:///usr/local/test/home//test-project/dist/test-project/server"
},
"prerenderedRoutes": [
"/"
]
}
```
```
NG_BUILD_LOGS_JSON=1 ng b
{
"errors": [],
"warnings": [],
"outputPaths": {
"root": "file:///usr/local/test/home//test-project/dist/test-project",
"browser": "file:///usr/local/test/home//test-project/dist/test-project/browser",
"server": "file:///usr/local/test/home//test-project/dist/test-project/server"
},
"prerenderedRoutes": [
"/"
]
}
```
When using the `application` builder, the usage of a custom postcss configuration is now supported.
The builder will automatically detect and use specific postcss configuration files if present in
either the project root directory or the workspace root. Files present in the project root will have
priority over a workspace root file. If using a custom postcss configuration file, the automatic
tailwind integration will be disabled. To use both a custom postcss configuration and tailwind, the
tailwind setup must be included in the custom postcss configuration file.
The configuration files must be JSON and named one of the following:
* `postcss.config.json`
* `.postcssrc.json`
A configuration file can use either an array form or an object form to setup plugins.
An example of the array form:
```
{
"plugins": [
"tailwindcss",
["rtlcss", { "useCalc": true }]
]
}
```
The same in an object form:
```
{
"plugins": {
"tailwindcss": {},
"rtlcss": { "useCalc": true }
}
}
```
NOTE: Using a custom postcss configuration may result in reduced build and rebuild
performance. Postcss will be used to process all global and component stylesheets
when a custom configuration is present. Without a custom postcss configuration,
postcss is only used for a stylesheet when tailwind is enabled and the stylesheet
requires tailwind processing.
The `load` event for each stylesheet may not always be triggered by Google Chrome's handling. Refer to: https://crbug.com/1521256
This results in the media attribute persistently being set to print, leading to distorted styles in the UI. To address this issue, we substitute the onload logic by replacing `link.addEventListener('load', ...` with `document.documentElement.addEventListener('load', ...` and filtering for link tags.
Closes#26932
To support generate diagnostics in varying ways, the internal compilation classes
now support a `modes` argument when diagnosing files during a build using the `application` builder.
This is not exposed as an option at this time but can be experimented with a build using the
`NG_BUILD_TYPE_CHECK` environment variable. This environment variable is not considered part of the
public API and may be removed or altered in the future. Its current purpose is to allow profiling
of the type checking diagnostics functionality of the build system.
This improvement harmonizes the proxy configuration loading mechanisms between the dev-server and ssr-dev-server. Previously, these servers used different methods for loading the proxy configuration, leading to inconsistencies. Notably, the ssr-dev-server was limited to loading configurations only in JSON format. This change enables the ssr-dev-server to support various configuration formats, aligning it with the dev-server's capabilities and improving overall developer experience.
The `deleteOutputPath` option will now empty specific build artifact directories instead of
removing them completely. This allows for symlinking or mounting the directories via Docker.
This is similar to the current behavior of emptying the root output path to allow similar
actions. All previous files will still be removed when the `deleteOutputPath` option is enabled.
This is useful in situations were the browser output files may be symlinked onto another
location on disk that is setup as a development server, or a Docker configuration mounts the browser
and server output to different locations on the host machine.
`@import url()` to Google and Adobe fonts that are located in global and component CSS will now be inlined when using the esbuild based builders.
Input
```css
@import url(https://fonts.googleapis.com/css?family=Roboto:300,400,500);
```
Output
```css
/* latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 500;
src: url(https://fonts.gstatic.com/s/roboto/v30/KFOlCnqEu92Fr1MmEU9fBBc4AMP6lQ.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
```
Closes#23054
Vite appears to consider a port value of `0` as a falsy value and use the default Vite port of
`5173` when zero is used as a value for the development server port option. To workaround this
issue, the port checker code now explicitly handles the zero value case and determines a random
port as would be done automatically by the Webpack-based development server.
When using the `application` builder with progress enabled (the default), the spinner text will
now automatically contain a trailing newline. This ensures that any diagnostic messages are not
awkwardly printed on the same line as the spinner.
This commit, fixes a file watching issue where file changes events are not triggered when using IDEs like Visual Studio (not VS Code).
The main changes to solve the issue are;
## Replace `watcher.on('all')` with `watcher.on('raw')`
Using `watcher.on('all')` does not capture some of events fired when using Visual studio and this does not happen all the time, but only after a file has been changed 3 or more times.
```
watcher.on('raw')
Change 1
rename | 'C:/../src/app/app.component.css'
rename | 'C:/../src/app/app.component.css'
change | 'C:/../src/app/app.component.css'
Change 2
rename | 'C:/../src/app/app.component.css'
rename | 'C:/../src/app/app.component.css'
change | 'C:/../src/app/app.component.css'
Change 3
rename | 'C:/../src/app/app.component.css'
rename | 'C:/../src/app/app.component.css'
change | 'C:/../src/app/app.component.css'
watcher.on('all')
Change 1
change | 'C:\\..\\src\\app\\app.component.css'
Change 2
unlink | 'C:\\..\\src\\app\\app.component.css'
Change 3
... (Nothing)
```
## Handle `rename` events
Some IDEs will fire a rename event instead of unlink/changed when a file is modified}
Closes#26437
(cherry picked from commit 1725b91e357f613f7fb7547d13d6499973ee3849)
This reverts commit bbbe13d6782ba9d1b80473a98ea95bc301c48597.
Switching to `raw` event changes the event names such that some events are getting dropped and breaking watch mode rebuilds on Mac.
Prior to this change special CSS comments `/*! comment */` were being removed during minification when using the application builder. This caused tools that ran post build that rely on such comments such as purgeCSS and critters not to function properly.
We now provide a `removeSpecialComments` option to enable retention of these comments in global CSS files.
Usage example:
```json
{
"projects": {
"my-app": {
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"configurations": {
"production": {
"optimization": {
"styles": {
"removeSpecialComments": false
}
}
}
}
}
}
}
}
}
```
Closes: #26432
This commit, fixes a file watching issue where file changes events are not triggered when using IDEs like Visual Studio (not VS Code).
The main changes to solve the issue are;
## Replace `watcher.on('all')` with `watcher.on('raw')`
Using `watcher.on('all')` does not capture some of events fired when using Visual studio and this does not happen all the time, but only after a file has been changed 3 or more times.
```
watcher.on('raw')
Change 1
rename | 'C:/../src/app/app.component.css'
rename | 'C:/../src/app/app.component.css'
change | 'C:/../src/app/app.component.css'
Change 2
rename | 'C:/../src/app/app.component.css'
rename | 'C:/../src/app/app.component.css'
change | 'C:/../src/app/app.component.css'
Change 3
rename | 'C:/../src/app/app.component.css'
rename | 'C:/../src/app/app.component.css'
change | 'C:/../src/app/app.component.css'
watcher.on('all')
Change 1
change | 'C:\\..\\src\\app\\app.component.css'
Change 2
unlink | 'C:\\..\\src\\app\\app.component.css'
Change 3
... (Nothing)
```
## Handle `rename` events
Some IDEs will fire a rename event instead of unlink/changed when a file is modified}
Closes#26437
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
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` 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.
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.
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.
The `server-utils` SSR generated chunk was not previously included in the ESM in memory loader for
prerendering which resulted in the ESM resolver incorrectly attempting to resolve non-relative
dependencies. This would lead to resolution errors when using the development server with caching
enabled. In this scenario, the Angular dependencies would be marked external and the server utilities
output chunk would contain non-relative imports and fail to prerender.
* fix(@angular-devkit/build-angular): Windows Node.js 20 prerendering failure
On Node.js 20 prerendering failed on Windows with `An unhandled exception occurred: No handler function exported` error. This appears to be caused by transforming Piscina CJS bundles using the `JavaScriptTransformer`. interestingly, this does not effect other OS like Linux and Mac.
* fixup! fix(@angular-devkit/build-angular): Windows Node.js 20 prerendering failure
Co-authored-by: Charles <19598772+clydin@users.noreply.github.com>
---------
Co-authored-by: Charles <19598772+clydin@users.noreply.github.com>
When using the application builder in watch mode (including `ng serve`), the file watching
will now only watch files used or relevant to the used files. Previously, all files within
the project root were watched. This previous behavior could result in unneeded rebuilds when
unrelated files were changed. An environment variable named `NG_BUILD_WATCH_ROOT` is also
now available to enable the previous behavior in cases where it is still preferred as well
as for testing and debugging purposes.
When destroying a `piscina` package worker pool, the minimum workers must be set to 0 first
to prevent the recreation of the minimum number of workers. These workers would then be
cleaned up once the worker pool goes out of scope but the recreation and initialization of
each worker is unneeded processing that should be avoided.
This commit improves the printed error messages when using Vite with SSR and/or SSG by doing a couple of things.
- Enabling resolving and loading of sourcemap in Node.js by using `process.setSourceMapsEnabled`. See https://nodejs.org/api/process.html#processsetsourcemapsenabledval
- Amends Vite's `ssrTransform` method to remap the sourcemaps and inlines them.
- Enables `__zone_symbol__DISABLE_WRAPPING_UNCAUGHT_PROMISE_REJECTION` Zone.js flag to output cleaner stacktraces.
To enable, the above mentioned zone.js flag we had to create a server polyfill bundle as otherwise in some cases, zone.js would have been split and loaded before the flag.
**Before**
```
ERROR ReferenceError: window is not defined
at new _AppComponent (/main.server.mjs:36:19)
at NodeInjectorFactory.AppComponent_Factory [as factory] (/main.server.mjs:42:12)
at getNodeInjectable (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:4277:44)
at createRootComponent (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:14399:35)
at ComponentFactory.create (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:14263:25)
at ApplicationRef.bootstrap (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:31122:42)
at file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:30644:32
at _ZoneDelegate.invoke (/usr/local/xxx/cli-reproduction/test-ssr-/node_modules/zone.js/fesm2015/zone-node.js:368:26)
at Object.onInvoke (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:11202:33)
at _ZoneDelegate.invoke (/usr/local/xxx/cli-reproduction/test-ssr-/node_modules/zone.js/fesm2015/zone-node.js:367:52)
ERROR Error: Uncaught (in promise): ReferenceError: window is not defined
ReferenceError: window is not defined
at new _AppComponent (/main.server.mjs:36:19)
at NodeInjectorFactory.AppComponent_Factory [as factory] (/main.server.mjs:42:12)
at getNodeInjectable (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:4277:44)
at createRootComponent (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:14399:35)
at ComponentFactory.create (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:14263:25)
at ApplicationRef.bootstrap (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:31122:42)
at file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:30644:32
at _ZoneDelegate.invoke (/usr/local/xxx/cli-reproduction/test-ssr-/node_modules/zone.js/fesm2015/zone-node.js:368:26)
at Object.onInvoke (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:11202:33)
at _ZoneDelegate.invoke (/usr/local/xxx/cli-reproduction/test-ssr-/node_modules/zone.js/fesm2015/zone-node.js:367:52)
at resolvePromise (/usr/local/xxx/cli-reproduction/test-ssr-/node_modules/zone.js/fesm2015/zone-node.js:1124:31)
at /usr/local/xxx/cli-reproduction/test-ssr-/node_modules/zone.js/fesm2015/zone-node.js:1195:17
at _ZoneDelegate.invokeTask (/usr/local/xxx/cli-reproduction/test-ssr-/node_modules/zone.js/fesm2015/zone-node.js:402:31)
at AsyncStackTaggingZoneSpec.onInvokeTask (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:10879:28)
at _ZoneDelegate.invokeTask (/usr/local/xxx/cli-reproduction/test-ssr-/node_modules/zone.js/fesm2015/zone-node.js:401:60)
at Object.onInvokeTask (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:11189:33)
at _ZoneDelegate.invokeTask (/usr/local/xxx/cli-reproduction/test-ssr-/node_modules/zone.js/fesm2015/zone-node.js:401:60)
at Zone.runTask (/usr/local/xxx/cli-reproduction/test-ssr-/node_modules/zone.js/fesm2015/zone-node.js:173:47)
at drainMicroTaskQueue (/usr/local/xxx/cli-reproduction/test-ssr-/node_modules/zone.js/fesm2015/zone-node.js:581:35) {
rejection: ReferenceError: window is not defined
at new _AppComponent (/main.server.mjs:36:19)
at NodeInjectorFactory.AppComponent_Factory [as factory] (/main.server.mjs:42:12)
at getNodeInjectable (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:4277:44)
at createRootComponent (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:14399:35)
at ComponentFactory.create (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:14263:25)
at ApplicationRef.bootstrap (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:31122:42)
at file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:30644:32
at _ZoneDelegate.invoke (/usr/local/xxx/cli-reproduction/test-ssr-/node_modules/zone.js/fesm2015/zone-node.js:368:26)
at Object.onInvoke (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:11202:33)
at _ZoneDelegate.invoke (/usr/local/xxx/cli-reproduction/test-ssr-/node_modules/zone.js/fesm2015/zone-node.js:367:52),
promise: ZoneAwarePromise [Promise] {
__zone_symbol__state: 0,
__zone_symbol__value: ReferenceError: window is not defined
at new _AppComponent (/main.server.mjs:36:19)
at NodeInjectorFactory.AppComponent_Factory [as factory] (/main.server.mjs:42:12)
at getNodeInjectable (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:4277:44)
at createRootComponent (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:14399:35)
at ComponentFactory.create (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:14263:25)
at ApplicationRef.bootstrap (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:31122:42)
at file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:30644:32
at _ZoneDelegate.invoke (/usr/local/xxx/cli-reproduction/test-ssr-/node_modules/zone.js/fesm2015/zone-node.js:368:26)
at Object.onInvoke (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:11202:33)
at _ZoneDelegate.invoke (/usr/local/xxx/cli-reproduction/test-ssr-/node_modules/zone.js/fesm2015/zone-node.js:367:52)
},
zone: <ref *1> Zone {
_parent: Zone {
_parent: [Zone],
_name: 'asyncStackTagging for Angular',
_properties: {},
_zoneDelegate: [_ZoneDelegate]
},
_name: 'angular',
_properties: { isAngularZone: true },
_zoneDelegate: <ref *2> _ZoneDelegate {
_taskCounts: [Object],
zone: [Circular *1],
_parentDelegate: [_ZoneDelegate],
_forkZS: null,
_forkDlgt: null,
_forkCurrZone: null,
_interceptZS: null,
_interceptDlgt: null,
_interceptCurrZone: null,
_invokeZS: [Object],
_invokeDlgt: [_ZoneDelegate],
_invokeCurrZone: [Circular *1],
_handleErrorZS: [Object],
_handleErrorDlgt: [_ZoneDelegate],
_handleErrorCurrZone: [Circular *1],
_scheduleTaskZS: [Object],
_scheduleTaskDlgt: [_ZoneDelegate],
8:23:50 AM [vite] Internal server error: window is not defined
at new _AppComponent (/main.server.mjs:36:19)
at NodeInjectorFactory.AppComponent_Factory [as factory] (/main.server.mjs:42:12)
at getNodeInjectable (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:4277:44)
at createRootComponent (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:14399:35)
at ComponentFactory.create (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:14263:25)
at ApplicationRef.bootstrap (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:31122:42)
at file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:30644:32
at _ZoneDelegate.invoke (/usr/local/xxx/cli-reproduction/test-ssr-/node_modules/zone.js/fesm2015/zone-node.js:368:26)
at Object.onInvoke (file:///usr/local/xxx/cli-reproduction/test-ssr-/node_modules/@angular/core/fesm2022/core.mjs:11202:33)
at _ZoneDelegate.invoke (/usr/local/xxx/cli-reproduction/test-ssr-/node_modules/zone.js/fesm2015/zone-node.js:367:52)
```
**After**
```
ERROR ReferenceError: window is not defined
at console (/src/app/app.component.ts:17:3)
at NodeInjectorFactory.AppComponent_Factory (/src/app/app.component.ts:12:26)
at getNodeInjectable (/usr/local/xxx/git/packages/core/src/render3/di.ts:659:38)
at createRootComponent (/usr/local/xxx/git/packages/core/src/render3/component_ref.ts:464:31)
at ComponentFactory.create (/usr/local/xxx/git/packages/core/src/render3/component_ref.ts:288:19)
at ApplicationRef.bootstrap (/usr/local/xxx/git/packages/core/src/application_ref.ts:1017:38)
at <anonymous> (/usr/local/xxx/git/packages/core/src/application_ref.ts:287:20)
at _ZoneDelegate.invoke (/node_modules/zone.js/fesm2015/zone-node.js:370:40)
at Object.onInvoke (/usr/local/xxx/git/packages/core/src/zone/ng_zone.ts:443:29)
at _ZoneDelegate.invoke (/node_modules/zone.js/fesm2015/zone-node.js:370:40)
ERROR ReferenceError: window is not defined
at console (/src/app/app.component.ts:17:3)
at NodeInjectorFactory.AppComponent_Factory (/src/app/app.component.ts:12:26)
at getNodeInjectable (/usr/local/xxx/git/packages/core/src/render3/di.ts:659:38)
at createRootComponent (/usr/local/xxx/git/packages/core/src/render3/component_ref.ts:464:31)
at ComponentFactory.create (/usr/local/xxx/git/packages/core/src/render3/component_ref.ts:288:19)
at ApplicationRef.bootstrap (/usr/local/xxx/git/packages/core/src/application_ref.ts:1017:38)
at <anonymous> (/usr/local/xxx/git/packages/core/src/application_ref.ts:287:20)
at _ZoneDelegate.invoke (/node_modules/zone.js/fesm2015/zone-node.js:370:40)
at Object.onInvoke (/usr/local/xxx/git/packages/core/src/zone/ng_zone.ts:443:29)
at _ZoneDelegate.invoke (/node_modules/zone.js/fesm2015/zone-node.js:370:40)
8:13:37 AM [vite] Internal server error: window is not defined
at console (/src/app/app.component.ts:17:3)
at NodeInjectorFactory.AppComponent_Factory (/src/app/app.component.ts:12:26)
at getNodeInjectable (/usr/local/xxx/git/packages/core/src/render3/di.ts:659:38)
at createRootComponent (/usr/local/xxx/git/packages/core/src/render3/component_ref.ts:464:31)
at ComponentFactory.create (/usr/local/xxx/git/packages/core/src/render3/component_ref.ts:288:19)
at ApplicationRef.bootstrap (/usr/local/xxx/git/packages/core/src/application_ref.ts:1017:38)
at <anonymous> (/usr/local/xxx/git/packages/core/src/application_ref.ts:287:20)
at _ZoneDelegate.invoke (/node_modules/zone.js/fesm2015/zone-node.js:370:40)
at Object.onInvoke (/usr/local/xxx/git/packages/core/src/zone/ng_zone.ts:443:29)
at _ZoneDelegate.invoke (/node_modules/zone.js/fesm2015/zone-node.js:370:40)
```
**Note:** in the above case the error is printed 3x, this will be addressed in the future.