Migrates the `@angular-devkit/build-angular` tests to `rules_js`. This
was a rather larger undertaking as the tests were very reliant on e.g.
the directory structure or specific node module layout; so some changes
were needed.
- the Sass files include a much larger file header now. That is because
the npm Sass files have much larger paths, given being inside a
symlinked pnpm store directory. E.g.
```
/*!**********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\
!*** css ../../../../../node_modules/.aspect_rules_js/css-loader@7.1.2_webpack_5.97.1/node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].rules[0].oneOf[0].use[1]!../../../../../node_modules/.aspect_rules_js/postcss-loader@8.1.1_1462687623/node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].rules[0].oneOf[0].use[2]!./src/test-style-a.css?ngGlobalStyle ***!
\**********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
.test-a {color: red}
```
- Similarly to above, hashed chunk files can change given different
paths of e.g. Webpack, or external sources.
- Tests for verifying the lazy module chunks may enable
`preserveSymlinks` just to make the chunk names shorter and easier to
verify, avoiding truncatd super long paths to the e.g. pnpm stores
again.
- the ngsw-worker.js file cannot be copied using `copyFile` as that
results in permissions being copied as well. In Bazel, now that
the npm files are properly captured, are readonly, so subsequent
builds (e.g. the watch tests) will fail to copy/override the file
again! Reading and writing the file consistently seems appropriate.
- Tests relying on puppeteer and webdriver-manager worked in the past,
by accident, because postinstall scripts (from e.g. puppeteer) were
able to modify content of other packages (e.g. the puppeteer-core
cache of browsers then). This does not work with `rules_js` anymore,
so we need to keep the cache local to the puppeteer postinstall
script. This requires a little trickery right now to ensure resolution
of the browsers at runtime works..
- server tests did miss the `node` types to be explicitly listed (as
they would be in a fresh project), and this caused failures. Likely
because we no longer patch resolution.
- avoid npm-module style imports from tests within the same package.
This is not allowed with `rules_js` and also is inconsistent.
This is necessary as `rules_js` requires this "common name" when dealing
with Yarn workspaces, linking first party dependencies automatically.
In the future, we may be able to send a PR to `rules_js` to support a
custom name somehow.
* Removes `interop_deps` from the `ts_project` interop macro.
* Keeps `_rjs` suffix for now as we still need the interop targets for
e.g. `jasmine_node_test` and the `rules_nodejs` linker.
In follow-ups we can remove the suffix, and interop layer.
This commit updates `build_angular` to the `rules_js` ts_project rule.
Notably a few real type issues surfaced but previously didn't surface
due to some unknown resolution issues that resulted in `never` types;
where every possible value was assignable; so this change improves type
safety and a TODO was left for the "brittle code fragment".
Currently the interop resulting target of a `ts_project` ends up not
necessarily working at runtime. This may be the case because a consuming
Node program may end up with mixes of `node_modules` dependencies from
`rules_nodejs` (old) and `rules_js` (new). This sounds fine at first
glance, but in practice can break very subtly because:
* Rules NodeJS leverages the linker, creating `node_module` directories
outside of Bazel, at runtime. These don't depend on symlink resolving.
* Rules JS puts real node module folders via Bazel actions. These rely
on `pnpm` non-hoisting layout, and symlink resolving.
As we can see there is a hard conflict with symlinks. They need to be
enabled with the new toolchain, but the other one doesn't enable symlink
resolution, and enabling is not possible as we'd otherwise risk escaping
the sandbox and cause even more subtle errors.
A good compromise solution is to automatically drop the `rules_js` node
module files/folder in the interop-`rules_nodejs` target and instead
brining in the equivalent `@npm//` dependencies from `rules_nodejs`.
This kind of keeps the logic similar to when not using `rules_js` or the
interop, and enables the simplest & safest mental model; and it works
compared to other solutions I tried with symlinking. Notably, we can't
keep both node module variants as the linker doesn't override existing
node module files from e.g. rules_js then (and would break then).
Runs all existing karma tests twice: Once in an environment that uses the
application builder and once in one that uses the browser builder. The
general approach is taken from the dev server tests.
This is in preparation for supporting the application builder for karma tests.
Refactored the `CommonEngine` API import path to remove Node.js dependencies from the `@angular/ssr` main entry-point.
BREAKING CHANGE:
The `CommonEngine` API now needs to be imported from `@angular/ssr/node`.
**Before**
```ts
import { CommonEngine } from '@angular/ssr';
```
**After**
```ts
import { CommonEngine } from '@angular/ssr/node';
```
These server tests frequently fail due to timeouts. Despite efforts, the root cause has not yet been identified, so they are being marked as flaky to prevent blocking the pipeline while further investigation continues.
The Node.js types (`@types/node`) now contains the information for the `Response`
class and the global `fetch` function. The `Response` object is also globally
accessible in all versions of Node.js supported by the Angular CLI. This removes
the need to depend directly on the `undici` package.
The `undici` package is still used for unit-testing and remains as a development
dependency.
The `istanbul-lib-instrument` package provides the required functionality needed
to instrument code for test coverage within the context of the Angular CLI.
Since the build pipeline already contains a customized babel preset, this package
can be integrated directly into the pipeline.
This reduces the number of dependencies required for `@angular-devkit/build-angular`
including the deprecated `inflight` package.
Updates for all angular.io links to the new angular.dev domain. Additionally, adjustment to new resources where the equivalent does not exist on the new site (e.g. Tour of Heroes tutorial)
When creating a local development build of the repository via `yarn build --local`,
the package version for `@angular/build` within `@angular-devkit/build-angular`
will now correctly be replaced with the path to the locally built archive of
`@angular/build`.
The dev-server builder will now only provide an interface with typed fields
for the combined set of common elements for the Webpack and Vite development
server implementations. Any additional builder specific runtime fields will
still be present and accessible.
The `@angular/build` package has been introduced to house the esbuild/Vite-based
build system that was newly introduced as stable in v17. The existing
`@angular-devkit/build-angular` package will continue to contain the Webpack-based
build system and to ensure backwards compatibility it will also provide aliases
for the esbuild/Vite-based build system. The changes here are the first stage
of the builder transition and moves the `application` builder into the new package.
The application builder can now be accessed when this package is installed directly
via `@angular/build:application`.
No changes are required for existing projects.
The builder testing infrastructure and harness has been moved out of the
`@angular-devkit/build-angular` package and into a separate bazel only
module. This allows the testing code to be shared with other packages
within the repository. It also removes test only code from within
the package that is not specific any of the included builders.
This is a new `@angular-devkit/build-angular:web-test-runner` builder which invokes Web Test Runner to execute unit tests in a real browser.
The implementation calls `application` builder under the hood with some option overrides build the application to a temporary directory and then runs Web Test Runner on the output. This set up is still minimal, but sufficient to run and pass tests in the generated `ng new` application.
The `schema.json` file is directly copied from the `karma` builder, since this is intended to serve as a migration target for users coming from Karma. Most of the options don't actually work yet, which is logged when they are used.
The most interesting part of this change is configuring Jasmine to execute in Web Test Runner. This is done through the `testRunnerHtml` option which allows us to control the HTML page tests are executed on. We use `test_page.html` which very carefully controls the loading process. I opted to make a single `<script type="module">` which dynamic imports all the relevant pieces so the ordering can be directly controlled more easily. This is better than trying to manage multiple `<script>` tags and pass data between them. Ideally everything would be bundled into a single entry point, however this is not feasible due to the way that ordering requirements do not align with typical `import` structure. Jasmine must come before polyfills which must come before the runner which invokes user code. In an ideal world, this ordering relationship would be represented in `import` statements, but this is not practically feasible because Angular CLI doesn't own all the files (`./polyfills.js` is user-defined) and Jasmine's loading must be split into two places so Zone.js can properly patch it.
`jasmine_runner.js` serves the purpose of executing Jasmine tests and reporting their results to Web Test Runner. I tried to write `jasmine_runner.js` in TypeScript and compile it with a `ts_library`. Unfortunately I don't think this is feasible because it needs to import `@web/test-runner-core` at runtime. This dependency has some code generated at runtime in Web Test Runner, meaning we cannot bundle this dependency and must mark it as external and dynamic `import()` the package at runtime. This works fine in native ESM, but compiling with TypeScript outputs CommonJS code by default (and I don't believe our `@build_bazel_rules_nodejs` setup can easily change that), so any `import('@web/test-runner-core')` becomes `require('@web/test-runner-core')` which fails because that package is ESM-only. The `loadEsmModule` trick does work here either because Web Test Runner is applying Node module resolution at serve time, meaning it looks for `import('@web/test-runner-core')` and rewrites it to something like `import('/node_modules/@web/test-runner-core')`. In short, there is no easy syntax which circumvents the TypeScript compiler while also being statically analyzable to Web Test Runner.
The underlying file watching functionality now uses the `watchpack` library for all
builders. This includes the Webpack-based `browser` and the esbuild-based `application`/
`browser-esbuild`. This not only has the advantage of a single dependency for both but also
provides more consistent behavior between the two build system in regards to file watching.
Since the implementation of the file watching is fully encapsulated, there is no change to
the options or configurations of consuming applications.
The stylesheet url() resource plugin will now correctly issue warnings for the usage of Webpack
specific prefixes such as the tilde when used in an imported Sass file. Previously, these URLs
would be rebased by the Sass processing step which would cause the tilde prefix to no longer
be a prefix. This would then no longer be considered a warning due to the tilde no longer being
the first character of the URL value. Additionally, a warning is also now issued for the previously
unsupported but available caret prefix. Removing the caret prefix and adding the path to the
`externalDependencies` build option should provide equivalent behavior.
Previously, the application builder relied on TypeScript to detect affected component files via changes
to the internal template type check code. However, not all AOT compiler generated template errors will cause
the template type check code to be changed. Block syntax errors are one example. To ensure that component
diagnostics are recalculated when required, the component file will now always be considered affected when
a used template file is changed.
This fixes an issue were routes could not be discovered automatically in a standalone application.
This is a total overhaul of the route extraction process as instead of using `guess-parser` NPM package, we now use the Angular Router. This enables a number of exciting possibilities for the future which were not possible before.
# How it works?
The application is bootstrapped and through DI injection we get the injector and router config instance and recursively build the routes tree.
Newer versions of the babel packages allow for removing some types packages as well as some helper
packages. The `@babel/template` package export used within the CLI is accessible from the `@babel/core`
package which allows removal of `@babel/template` as a direct dependency. Also, the `@babel/plugin-proposal-async-generator-functions`
package has been transitioned to `@babel/plugin-transform-async-generator-functions` due to async generators
being merged into the ECMAScript standard. Minor code cleanup based on the type cleanup was also performed
in the build optimizer babel passes.
BREAKING CHANGE: Node.js v16 support has been removed
Node.js v16 is planned to be End-of-Life on 2023-09-11. Angular will stop supporting Node.js v16 in Angular v17.
For Node.js release schedule details, please see: https://github.com/nodejs/release#release-schedule
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.
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.
The file searching within the build system (both Webpack and esbuild) now use the
`fast-glob` package for globbing which provides a small performance improvement.
Since the assets option in particular is within the critical path of the buil pipeline,
the performance benefit from the switch will be most prevalent in asset heavy projects.
As an example, the Angular Material documentation site saw the asset discovery time
reduced by over half with the switch. `fast-glob` is also the package used by Vite
which provides additional benefit by ensuring that the Angular CLI behavior matches
that of the newly integrated Vite development server.