From c40300ba7e420edaad4da2bb666eb35a807ae5d7 Mon Sep 17 00:00:00 2001 From: Suguru Inatomi Date: Wed, 20 Nov 2024 14:54:49 +0900 Subject: [PATCH 01/27] fix: update origin to 19.0.0 --- origin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/origin b/origin index 76721458e..e7566c3c4 160000 --- a/origin +++ b/origin @@ -1 +1 @@ -Subproject commit 76721458ec3a58a79702d8871bb4902b3f4444ac +Subproject commit e7566c3c475560616f97de2ab3c8f8d6f83be015 From 6b12134babd9388f92f3773e3aefde6ac04ca39a Mon Sep 17 00:00:00 2001 From: Suguru Inatomi Date: Wed, 20 Nov 2024 15:00:38 +0900 Subject: [PATCH 02/27] fix: migrate untranslated contents --- .../ecosystem/rxjs-interop/output-interop.md | 52 +++ .../ecosystem/rxjs-interop/signals-interop.md | 105 ++++++ .../ecosystem/service-workers/config.md | 23 +- adev-ja/src/content/guide/hybrid-rendering.md | 322 +++++++++++++++++ .../src/content/guide/image-optimization.md | 2 + .../content/guide/incremental-hydration.md | 212 +++++++++++ .../src/content/guide/ngmodules/overview.md | 209 ++++++++--- adev-ja/src/content/guide/signals/resource.md | 115 ++++++ adev-ja/src/content/guide/zoneless.md | 6 +- .../essentials/dependency-injection.md | 60 ++++ .../introduction/essentials/signals.md | 80 +++++ .../introduction/essentials/templates.md | 148 ++++++++ .../reference/extended-diagnostics/NG8103.md | 3 - .../reference/extended-diagnostics/NG8113.md | 48 +++ .../extended-diagnostics/overview.md | 1 + .../content/reference/migrations/overview.md | 6 + .../reference/migrations/signal-inputs.md | 116 ++++++ .../reference/migrations/signal-queries.md | 115 ++++++ .../tools/cli/build-system-migration.md | 332 ++++++++++++++++-- adev-ja/src/content/tools/cli/overview.md | 6 + .../tools/libraries/angular-package-format.md | 33 +- 21 files changed, 1890 insertions(+), 104 deletions(-) create mode 100644 adev-ja/src/content/ecosystem/rxjs-interop/output-interop.md create mode 100644 adev-ja/src/content/ecosystem/rxjs-interop/signals-interop.md create mode 100644 adev-ja/src/content/guide/hybrid-rendering.md create mode 100644 adev-ja/src/content/guide/incremental-hydration.md create mode 100644 adev-ja/src/content/guide/signals/resource.md create mode 100644 adev-ja/src/content/introduction/essentials/dependency-injection.md create mode 100644 adev-ja/src/content/introduction/essentials/signals.md create mode 100644 adev-ja/src/content/introduction/essentials/templates.md create mode 100644 adev-ja/src/content/reference/extended-diagnostics/NG8113.md create mode 100644 adev-ja/src/content/reference/migrations/signal-inputs.md create mode 100644 adev-ja/src/content/reference/migrations/signal-queries.md diff --git a/adev-ja/src/content/ecosystem/rxjs-interop/output-interop.md b/adev-ja/src/content/ecosystem/rxjs-interop/output-interop.md new file mode 100644 index 000000000..cfe278e81 --- /dev/null +++ b/adev-ja/src/content/ecosystem/rxjs-interop/output-interop.md @@ -0,0 +1,52 @@ +# RxJS interop with component and dirctive outputs + +IMPORTANT: The RxJS Interop package is available for [developer preview](reference/releases#developer-preview). It's ready for you to try, but it might change before it is stable. + +Tip: This guide assumes you're familiar with [component and directive outputs](guide/components/outputs). + +The `@angular/rxjs-interop` package offers two APIs related to component and directive outputs. + +## Creating an output based on an RxJs Observable + +The `outputFromObservable` lets you create a component or directive output that emits based on an RxJS observable: + + +import {Directive} from '@angular/core'; +import {outputFromObservable} from '@angular/core/rxjs-interop'; + +@Directive({/*...*/}) +class Draggable { + pointerMoves$: Observable = listenToPointerMoves(); + + // Whenever `pointerMoves$` emits, the `pointerMove` event fires. + pointerMove = outputFromObservable(this.pointerMoves$); +} + + +The `outputFromObservable` function has special meaning to the Angular compiler. **You may only call `outputFromObservable` in component and directive property initializers.** + +When you `subscribe` to the output, Angular automatically forwards the subscription to the underlying observable. Angular stops forwarding values when the component or directive is destroyed. + +HELPFUL: Consider using `output()` directly if you can emit values imperatively. + +## Creating an RxJS Observable from a component or directive output + +The `outputToObservable` function lets you create an RxJS observable from a component output. + + +import {outputToObservable} from '@angular/core/rxjs-interop'; + +@Component(/*...*/) +class CustomSlider { + valueChange = output(); +} + +// Instance reference to `CustomSlider`. +const slider: CustomSlider = createSlider(); + +outputToObservable(slider.valueChange) // Observable + .pipe(...) + .subscribe(...); + + +HELPFUL: Consider using the `subscribe` method on `OutputRef` directly if it meets your needs. diff --git a/adev-ja/src/content/ecosystem/rxjs-interop/signals-interop.md b/adev-ja/src/content/ecosystem/rxjs-interop/signals-interop.md new file mode 100644 index 000000000..410507043 --- /dev/null +++ b/adev-ja/src/content/ecosystem/rxjs-interop/signals-interop.md @@ -0,0 +1,105 @@ +# RxJS interop with Angular signals + +IMPORTANT: The RxJS Interop package is available for [developer preview](reference/releases#developer-preview). It's ready for you to try, but it might change before it is stable. + +The `@angular/rxjs-interop` package offers APIs that help you integrate RxJS and Angular signals. + +## Create a signal from an RxJs Observable with `toSignal` + +Use the `toSignal` function to create a signal which tracks the value of an Observable. It behaves similarly to the `async` pipe in templates, but is more flexible and can be used anywhere in an application. + +```ts +import { Component } from '@angular/core'; +import { AsyncPipe } from '@angular/common'; +import { interval } from 'rxjs'; +import { toSignal } from '@angular/core/rxjs-interop'; + +@Component({ + template: `{{ counter() }}`, +}) +export class Ticker { + counterObservable = interval(1000); + + // Get a `Signal` representing the `counterObservable`'s value. + counter = toSignal(this.counterObservable, {initialValue: 0}); +} +``` + +Like the `async` pipe, `toSignal` subscribes to the Observable immediately, which may trigger side effects. The subscription created by `toSignal` automatically unsubscribes from the given Observable when the component or service which calls `toSignal` is destroyed. + +IMPORTANT: `toSignal` creates a subscription. You should avoid calling it repeatedly for the same Observable, and instead reuse the signal it returns. + +### Injection context + +`toSignal` by default needs to run in an [injection context](guide/di/dependency-injection-context), such as during construction of a component or service. If an injection context is not available, you can manually specify the `Injector` to use instead. + +### Initial values + +Observables may not produce a value synchronously on subscription, but signals always require a current value. There are several ways to deal with this "initial" value of `toSignal` signals. + +#### The `initialValue` option + +As in the example above, you can specify an `initialValue` option with the value the signal should return before the Observable emits for the first time. + +#### `undefined` initial values + +If you don't provide an `initialValue`, the resulting signal will return `undefined` until the Observable emits. This is similar to the `async` pipe's behavior of returning `null`. + +#### The `requireSync` option + +Some Observables are guaranteed to emit synchronously, such as `BehaviorSubject`. In those cases, you can specify the `requireSync: true` option. + +When `requiredSync` is `true`, `toSignal` enforces that the Observable emits synchronously on subscription. This guarantees that the signal always has a value, and no `undefined` type or initial value is required. + +### `manualCleanup` + +By default, `toSignal` automatically unsubscribes from the Observable when the component or service that creates it is destroyed. + +To override this behavior, you can pass the `manualCleanup` option. You can use this setting for Observables that complete themselves naturally. + +### Error and Completion + +If an Observable used in `toSignal` produces an error, that error is thrown when the signal is read. + +If an Observable used in `toSignal` completes, the signal continues to return the most recently emitted value before completion. + +## Create an RxJS Observale from a signal with `toObservable` + +Use the `toObservable` utility to create an `Observable` which tracks the value of a signal. The signal's value is monitored with an `effect` which emits the value to the Observable when it changes. + +```ts +import { Component, signal } from '@angular/core'; + +@Component(...) +export class SearchResults { + query: Signal = inject(QueryService).query; + query$ = toObservable(this.query); + + results$ = this.query$.pipe( + switchMap(query => this.http.get('/search?q=' + query )) + ); +} +``` + +As the `query` signal changes, the `query$` Observable emits the latest query and triggers a new HTTP request. + +### Injection context + +`toObservable` by default needs to run in an [injection context](guide/di/dependency-injection-context), such as during construction of a component or service. If an injection context is not available, you can manually specify the `Injector` to use instead. + +### Timing of `toObservable` + +`toObservable` uses an effect to track the value of the signal in a `ReplaySubject`. On subscription, the first value (if available) may be emitted synchronously, and all subsequent values will be asynchronous. + +Unlike Observables, signals never provide a synchronous notification of changes. Even if you update a signal's value multiple times, `toObservable` will only emit the value after the signal stabilizes. + +```ts +const obs$ = toObservable(mySignal); +obs$.subscribe(value => console.log(value)); + +mySignal.set(1); +mySignal.set(2); +mySignal.set(3); +``` + +Here, only the last value (3) will be logged. diff --git a/adev-ja/src/content/ecosystem/service-workers/config.md b/adev-ja/src/content/ecosystem/service-workers/config.md index da5239f6a..a4d16eea2 100644 --- a/adev-ja/src/content/ecosystem/service-workers/config.md +++ b/adev-ja/src/content/ecosystem/service-workers/config.md @@ -197,6 +197,7 @@ export interface DataGroup { maxSize: number; maxAge: string; timeout?: string; + refreshAhead?: string; strategy?: 'freshness' | 'performance'; }; cacheQueryOptions?: { @@ -270,6 +271,22 @@ The network timeout is how long the Angular service worker waits for the network For example, the string `5s30u` translates to five seconds and 30 milliseconds of network timeout. + +##### `refreshAhead` + +This duration string specifies the time ahead of the expiration of a cached resource when the Angular service worker should proactively attempt to refresh the resource from the network. +The `refreshAhead` duration is an optional configuration that determines how much time before the expiration of a cached response the service worker should initiate a request to refresh the resource from the network. + +| Suffixes | Details | +|:--- |:--- | +| `d` | Days | +| `h` | Hours | +| `m` | Minutes | +| `s` | Seconds | +| `u` | Milliseconds | + +For example, the string `1h30m` translates to one hour and 30 minutes ahead of the expiration time. + ##### `strategy` The Angular service worker can use either of two caching strategies for data resources. @@ -330,7 +347,7 @@ A request is considered to be a navigation request if: * The URL must not contain a file extension (that is, a `.`) in the last path segment * The URL must not contain `__` -HELPFUL: To configure whether navigation requests are sent through to the network or not, see the [navigationRequestStrategy](#navigationrequeststrategy) section. +HELPFUL: To configure whether navigation requests are sent through to the network or not, see the [navigationRequestStrategy](#navigationrequeststrategy) section and [applicationMaxAge](#application-max-age) sections. #### Matching navigation request URLs @@ -374,3 +391,7 @@ This optional property enables you to configure how the service worker handles n | `'freshness'` | Passes the requests through to the network and falls back to the `performance` behavior when offline. This value is useful when the server redirects the navigation requests elsewhere using a `3xx` HTTP redirect status code. Reasons for using this value include:
  • Redirecting to an authentication website when authentication is not handled by the application
  • Redirecting specific URLs to avoid breaking existing links/bookmarks after a website redesign
  • Redirecting to a different website, such as a server-status page, while a page is temporarily down
| IMPORTANT: The `freshness` strategy usually results in more requests sent to the server, which can increase response latency. It is recommended that you use the default performance strategy whenever possible. + +### `applicationMaxAge` + +This optional property enables you to configure how long the service worker will cache any requests. Within the `maxAge`, files will be served from cache. Beyond it, all requests will only be served from the network, including asset and data requests. diff --git a/adev-ja/src/content/guide/hybrid-rendering.md b/adev-ja/src/content/guide/hybrid-rendering.md new file mode 100644 index 000000000..7206518bc --- /dev/null +++ b/adev-ja/src/content/guide/hybrid-rendering.md @@ -0,0 +1,322 @@ +# Hybrid rendering + +## What is hybrid rendering? + +Hybrid rendering combines the benefits of server-side rendering (SSR), pre-rendering (also known as "static site generation" or SSG) and client-side rendering (CSR) to optimize your Angular application. It allows you to render different parts of your application using different strategies, giving you fine-grained control over how your app is delivered to users. + +Angular’s new **developer preview** server rendering APIs offer a more efficient and adaptable approach to building modern web applications. These APIs give you complete control over your app’s rendering, allowing for optimizations that enhance performance, Search Engine Optimization (SEO), and overall user experience. + +**Benefits of these new APIs:** + +- **Greater flexibility:** + - Leverage fine-grained control over rendering allows you to optimize for performance and user experience in different parts of your application. + - Choose the best rendering strategy for each route, whether it's server-side rendering for fast initial load times, client-side rendering for dynamic interactivity, or a hybrid approach. +- **Built-in internationalization (i18n):** + - Easily adapt your application to different languages and regions with out-of-the-box i18n support. +- **Environment agnostic:** + - Use these APIs with any JavaScript runtime environment, not just Node.js. + - Enjoy the benefits of enhanced rendering capabilities regardless of your technology stack. +- **Seamless dev server integration:** + - Take advantage of a smooth and efficient development experience from a fully integrated development server. + +This developer preview gives you a first look at these powerful new features. The Angular team encourages you to explore them and provide feedback to help shape the future of Angular server rendering. + +## Setting up hybrid rendering + +You can create a **new** project with server-side routing with the Angular CLI: + +```shell +ng new --ssr --server-routing +``` + +You can also add server-side routing to an existing project with the `ng add` command: + +```shell +ng add @angular/ssr --server-routing +``` + +## Server routing + +### Configuring server routes + +You can create a server route config by declaring an array of [`ServerRoute`](api/ssr/ServerRoute 'API reference') objects. This configuration typically lives in a file named `app.routes.server.ts`. + +```typescript +// app.routes.server.ts +import { RenderMode, ServerRoute } from '@angular/ssr'; + +export const serverRoutes: ServerRoute[] = [ + { + path: '', // This renders the "/" route on the client (CSR) + renderMode: RenderMode.Client, + }, + { + path: 'about', // This page is static, so we prerender it (SSG) + renderMode: RenderMode.Prerender, + }, + { + path: 'profile', // This page requires user-specific data, so we use SSR + renderMode: RenderMode.Server, + }, + { + path: '**', // All other routes will be rendered on the server (SSR) + renderMode: RenderMode.Server, + }, +]; +``` + +You can add this config to your application using the [`provideServerRoutesConfig`](api/ssr/provideServerRoutesConfig 'API reference') function. + +```typescript +import { provideServerRoutesConfig } from '@angular/ssr'; +import { serverRoutes } from './app.routes.server'; + +// app.config.server.ts +const serverConfig: ApplicationConfig = { + providers: [ + provideServerRendering(), + provideServerRoutesConfig(serverRoutes), + // ... other providers ... + ] +}; +``` + +When using the [App shell pattern](ecosystem/service-workers/app-shell), you must specify the route to be used as the app shell for client-side rendered routes. To do this, provide an options object with the `appShellRoute` property to [`provideServerRoutesConfig`](api/ssr/provideServerRoutesConfig 'API reference'): + +```typescript +const serverConfig: ApplicationConfig = { + providers: [ + provideServerRoutesConfig(serverRoutes, { appShellRoute: 'shell' }), + // ... other providers ... + ] +}; +``` + +### Rendering modes + +The server routing configuration lets you specify how each route in your application should render by setting a [`RenderMode`](api/ssr/RenderMode 'API reference'): + +| Rendering mode | Description | +| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Server (SSR)** | Renders the application on the server for each request, sending a fully populated HTML page to the browser. See the [Server-Side Rendering (SSR) guide](guide/ssr) for more information. | +| **Client (CSR)** | Renders the application in the browser. This is the default Angular behavior. | +| **Prerender (SSG)** | Prerenders the application at build time, generating static HTML files for each route. See the [Prerendering guide](guide/prerendering) for more information. | + +#### Choosing a rendering mode + +Each rendering mode has different benefits and drawbacks. You can choose rendering modes based on the specific needs of your application. + +##### Client-side rendering + +Client-side rendering has the simplest development model, as you can write code that assumes it always runs in a web browser. This lets you use a wide range of client-side libraries that also assume they run in a browser. + +Client-side rendering generally has worse performance than other rendering modes, as it must download, parse, and execute your page's JavaScript before the user can see any rendered content. If your page fetches more data from the server as it renders, users also have to wait for those additional requests before they can view the complete content. + +If your page is indexed by search crawlers, client-side rendering may negatively affect search engine optimization (SEO), as search crawlers have limits to how much JavaScript they execute when indexing a page. + +When client-side rendering, the server does not need to do any work to render a page beyond serving static JavaScript assets. You may consider this factor if server cost is a concern. + +Applications that support installable, offline experiences with [service workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) can rely on client-side rendering without needing to communicate with a server. + +##### Server-side rendering + +Server-side rendering offers faster page loads than client-side rendering. Instead of waiting for JavaScript to download and run, the server directly renders an HTML document upon receiving a request from the browser. The user experiences only the latency necessary for the server to fetch data and render the requested page. This mode also eliminates the need for additional network requests from the browser, as your code can fetch data during rendering on the server. + +Server-side rendering generally has excellent search engine optimization (SEO), as search crawlers receive a fully rendered HTML document. + +Server-side rendering requires you to author code that does not strictly depend on browser APIs and limits your selection of JavaScript libraries that assume they run in a browser. + +When server-side rendering, your server runs Angular to produce an HTML response for every request. This additional cost may affect server hosting costs. + +##### Build-time prerendering + +Prerendering offers faster page loads than both client-side rendering and server-side rendering. Because prerendering creates HTML documents at _build-time_, the server can directly respond to requests with the static HTML document without any additional work. + +Prerendering requires that all information necessary to render a page is available at _build-time_. This means that prerendered pages cannot include any data to the specific user loading the page. This means that prerendering is primarily useful for pages that are the same for all users of your application. + +Because prerendering occurs at build-time, it may add significant time to your production builds. Using [`getPrerenderParams`](api/ssr/ServerRoutePrerenderWithParams#getPrerenderParams 'API reference') to produce a large number of HTML documents may affect the total file size of your deployments, and thus lead to slower deployments. + +It may also add time to your deployments based on the number of static HTML documents included in your build output. + +Prerendering generally has excellent search engine optimization (SEO), as search crawlers receive a fully rendered HTML document. + +Prerendering requires you to author code that does not strictly depend on browser APIs and limits your selection of JavaScript libraries that assume they run in a browser. + +Prerendering incurs extremely little overhead per server request, as your server responds with static HTML documents. Static files are also easily cached by Content Delivery Networks (CDNs), browsers, and intermediate caching layers for even faster subsequent page loads. Deploying static HTML files to a CDN improves scalability by offloading work from your application web server, which is impactful for high-traffic applications. + +### Setting headers and status codes + +You can set custom headers and status codes for individual server routes using the `headers` and `status` properties in the `ServerRoute` configuration. + +```typescript +// app.routes.server.ts +import { RenderMode, ServerRoute } from '@angular/ssr'; + +export const serverRoutes: ServerRoute[] = [ + { + path: 'profile', + renderMode: RenderMode.Server, + headers: { + 'X-My-Custom-Header': 'some-value', + }, + status: 201, + }, + // ... other routes +]; +``` + +### Redirects + +Angular handles redirects specified by the [`redirectTo`](api/ssr/ServerRoutePrerenderWithParams#getPrerenderParams 'API reference') property in route configurations, differently on the server-side. + +**Server-Side Rendering (SSR)** +Redirects are performed using standard HTTP redirects (e.g., 301, 302) within the server-side rendering process. + +**Prerendering (SSG)** +Redirects are implemented as "soft redirects" using `` tags in the prerendered HTML. This allows for redirects without requiring a round trip to the server. + +### Customizing build-time prerendering (SSG) + +When using [`RenderMode.Prerender`](api/ssr/RenderMode#Prerender 'API reference'), you can specify several configuration options to customize the prerendering and serving process. + +#### Parameterized routes + +For each route with [`RenderMode.Prerender`](api/ssr/RenderMode#Prerender 'API reference'), you can specify a [`getPrerenderParams`](api/ssr/ServerRoutePrerenderWithParams#getPrerenderParams 'API reference') function. This function lets you control which specific parameters produce separate prerendered documents. + +The [`getPrerenderParams`](api/ssr/ServerRoutePrerenderWithParams#getPrerenderParams 'API reference') function returns a `Promise` that resolves to an array of objects. Each object is a key-value map of route parameter name to value. For example, if you define a route like `posts/:id`, `getPrerenderParams ` could return the array `[{id: 123}, {id: 456}]`, and thus render separate documents for `posts/123` and `posts/456`. + +The body of [`getPrerenderParams`](api/ssr/ServerRoutePrerenderWithParams#getPrerenderParams 'API reference') can use Angular's [`inject`](api/core/inject 'API reference') function to inject dependencies and perform any work to determine which routes to prerender. This typically includes making requests to fetch data to construct the array of parameter values. + +```typescript +// app.routes.server.ts +import { RenderMode, ServerRoute } from '@angular/ssr'; + +export const serverRoutes: ServerRoute[] = [ + { + path: 'post/:id', + renderMode: RenderMode.Prerender, + async getPrerenderParams() { + const dataService = inject(PostService); + const ids = await dataService.getIds(); // Assuming this returns ['1', '2', '3'] + + return ids.map(id => ({ id })); // Transforms IDs into an array of objects for prerendering + + // This will prerender the paths: `/post/1`, `/post/2` and `/post/3` + }, + }, +]; +``` + +Because [`getPrerenderParams`](api/ssr/ServerRoutePrerenderWithParams#getPrerenderParams 'API reference') exclusively applies to [`RenderMode.Prerender`](api/ssr/RenderMode#Prerender 'API reference'), this function always runs at _build-time_. `getPrerenderParams` must not rely on any browser-specific or server-specific APIs for data. If the route does not specify a [`fallback`](api/ssr/ServerRoutePrerenderWithParams#fallback 'API reference') option, the route falls back to [`PrerenderFallback.Server`](api/ssr/PrerenderFallback#Server 'API reference') (SSR) by default. + +IMPORTANT: When using [`inject`](api/core/inject 'API reference') inside `getPrerenderParams`, please remember that `inject` must be used synchronously. It cannot be invoked within asynchronous callbacks or following any `await` statements. For more information, refer to [`runInInjectionContext` API reference](api/core/runInInjectionContext). + +#### Fallback strategies + +When using [`RenderMode.Prerender`](api/ssr/RenderMode#Prerender 'API reference') mode, you can specify a fallback strategy to handle requests for paths that haven't been prerendered. + +The available fallback strategies are: + +- **Server:** Fallback to server-side rendering. This is the **default** behavior if no `fallback` property is specified. +- **Client:** Fallback to client-side rendering. +- **None:** No fallback. Angular will not handle requests for paths that are not prerendered. + +```typescript +// app.routes.server.ts +import { RenderMode, PrerenderFallback, ServerRoute } from '@angular/ssr'; + +export const serverRoutes: ServerRoute[] = [ + { + path: 'post/:id', + renderMode: RenderMode.Prerender, + fallback: PrerenderFallback.Client, // Fallback to CSR if not prerendered + async getPrerenderParams() { + // This function returns an array of objects representing prerendered posts at the paths: + // `/post/1`, `/post/2`, and `/post/3`. + // The path `/post/4` will utilize the fallback behavior if it's requested. + return [{ id: 1 }, { id: 2 }, { id: 3 }]; + }, + }, +]; +``` + +## Accessing Request and Response via DI + +The `@angular/core` package provides several tokens for interacting with the server-side rendering environment. These tokens give you access to crucial information and objects within your Angular application during SSR. + +- **[`REQUEST`](api/core/REQUEST 'API reference'):** Provides access to the current request object, which is of type [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) from the Web API. This allows you to access headers, cookies, and other request information. +- **[`RESPONSE_INIT`](api/core/RESPONSE_INIT 'API reference'):** Provides access to the response initialization options, which is of type [`ResponseInit`](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response#parameters) from the Web API. This allows you to set headers and the status code for the response dynamically. Use this token to set headers or status codes that need to be determined at runtime. +- **[`REQUEST_CONTEXT`](api/core/REQUEST_CONTEXT 'API reference'):** Provides access to additional context related to the current request. This context can be passed as the second parameter of the [`handle`](api/ssr/AngularAppEngine#handle 'API reference') function. Typically, this is used to provide additional request-related information that is not part of the standard Web API. + +```angular-ts +import { inject, REQUEST } from '@angular/core'; + +@Component({ + selector: 'app-my-component', + template: `

My Component

`, +}) +export class MyComponent { + constructor() { + const request = inject(REQUEST); + console.log(request?.url); + } +} +``` + +IMPORTANT: The above tokens will be `null` in the following scenarios:

+ +- During the build processes. +- When the application is rendered in the browser (client-side rendering). +- When performing static site generation (SSG). +- During route extraction in development (at the time of the request). + +## Configuring a non-Node.js Server + +The `@angular/ssr` provides essential APIs for server-side rendering your Angular application on platforms other than Node.js. It leverages the standard [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) and [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) objects from the Web API, enabling you to integrate Angular SSR into various server environments. For detailed information and examples, refer to the [`@angular/ssr` API reference](api/ssr/node/AngularAppEngine). + +```typescript +// server.ts +import { AngularAppEngine, createRequestHandler } from '@angular/ssr'; + +const angularApp = new AngularAppEngine(); + +/** + * This is a request handler used by the Angular CLI (dev-server and during build). + */ +const reqHandler = createRequestHandler(async (req: Request) => { + const res: Response|null = await angularApp.render(req); + + // ... +}); +``` + +## Configuring a Node.js Server + +The `@angular/ssr/node` extends `@angular/ssr` specifically for Node.js environments. It provides APIs that make it easier to implement server-side rendering within your Node.js application. For a complete list of functions and usage examples, refer to the [`@angular/ssr/node` API reference](api/ssr/node/AngularNodeAppEngine) API reference. + +```typescript +// server.ts +import { AngularNodeAppEngine, createNodeRequestHandler, writeResponseToNodeResponse } from '@angular/ssr/node'; +import express from 'express'; + +const app = express(); +const angularApp = new AngularNodeAppEngine(); + +app.get('*', (req, res, next) => + angularApp + .handle(req) + .then(response => { + if (response) { + writeResponseToNodeResponse(response, res); + } else { + next(); // Pass control to the next middleware + } + }) + .catch(next); +}); + +/** + * The request handler used by the Angular CLI (dev-server and during build). + */ +export const reqHandler = createNodeRequestHandler(app); +```v diff --git a/adev-ja/src/content/guide/image-optimization.md b/adev-ja/src/content/guide/image-optimization.md index 44c82a78c..2d80daa07 100644 --- a/adev-ja/src/content/guide/image-optimization.md +++ b/adev-ja/src/content/guide/image-optimization.md @@ -248,6 +248,8 @@ If you haven't used `sizes` before, a good place to start is to set it based on If you find that the above does not cover your desired image behavior, see the documentation on [advanced sizes values](#advanced-sizes-values). +Note that `NgOptimizedImage` automatically prepends `"auto"` to the provided `sizes` value. This is an optimization that increases the accuracy of srcset selection on browsers which support `sizes="auto"`, and is ignored by browsers which do not. + By default, the responsive breakpoints are: `[16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840]` diff --git a/adev-ja/src/content/guide/incremental-hydration.md b/adev-ja/src/content/guide/incremental-hydration.md new file mode 100644 index 000000000..6ba5a5534 --- /dev/null +++ b/adev-ja/src/content/guide/incremental-hydration.md @@ -0,0 +1,212 @@ +# Incremental Hydration + +Tip: Incremental hydration is currently in [developer preview](/reference/releases#developer-preview). + +**Incremental hydration** is an advanced type of [hydration](guide/hydration) that can leave sections of your application dehydrated and _incrementally_ trigger hydration of those sections as they are needed. + +## Why use incremental hydration? + +Incremental hydration is a performance improvement that builds on top of full application hydration. It can produce smaller initial bundles while still providing an end-user experience that is comparable to a full application hydration experience. Smaller bundles improve initial load times, reducing [First Input Delay (FID)](<(https://web.dev/fid)>) and [Cumulative Layout Shift (CLS)](https://web.dev/cls). + +Incremental hydration also lets you use deferrable views (`@defer`) for content that may not have been deferrable before. Specifically, you can now use deferrable views for content that is above the fold. Prior to incremental hydration, putting a `@defer` block above the fold would result in placeholder content rendering and then being replaced by the `@defer` block's main template content. This would result in a layout shift. Incremental hydration means the main template of the `@defer` block will render with no layout shift on hydration. + +## How do you enable incremental hydration in Angular? + +You can enable incremental hydration for applications that already use server-side rendering (SSR) with hydration. Follow the [Angular SSR Guide](guide/ssr) to enable server-side rendering and the [Angular Hydration Guide](guide/hydration) to enable hydration first. + +Enable incremental hydration by adding the `withIncrementalHydration()` function to the `provideClientHydration` provider. + +```typescript +import { + bootstrapApplication, + provideClientHydration, + withIncrementalHydration, +} from '@angular/platform-browser'; +... + +bootstrapApplication(AppComponent, { + providers: [provideClientHydration(withIncrementalHydration())] +}); +``` + +Incremental Hydration depends on and enables event replay automatically. If you already have `withEventReplay()` in your list, you can safely remove it after enabling incremental hydration. + +## How does incremental hydration work? + +Incremental hydration builds on top of full-application [hydration](guide/hydration), [deferrable views](guide/defer), and [event replay](guide/hydration#capturing-and-replaying-events). With incremental hydration, you can add additional triggers to `@defer` blocks that define incremental hydration boundaries. Adding a `hydrate` trigger to a defer block tells Angular that it should load that defer block's dependencies during server-side rendering and render the main template rather than the `@placeholder`. When client-side rendering, the dependencies are still deferred, and the defer block content stays dehydrated until its `hydrate` trigger fires. That trigger tells the defer block to fetch its dependencies and hydrate the content. Any browser events, specifically those that match listeners registered in your component, that are triggered by the user prior to hydration are queued up and replayed once the hydration process is complete. + +## Controlling hydration of content with triggers + +You can specify **hydrate triggers** that control when Angular loads and hydrates deferred content. These are additional triggers that can be used alongside regular `@defer` triggers. + +Each `@defer` block may have multiple hydrate event triggers, separated with a semicolon (`;`). Angular triggers hydration when _any_ of the triggers fire. + +There are three types of hydrate triggers: `hydrate on`, `hydrate when`, and `hydrate never`. + +### `hydrate on` + +`hydrate on` specifies a condition for when hydration is triggered for the `@defer` block. + +The available triggers are as follows: + +| Trigger | Description | +| --------------------------------------------------- | ---------------------------------------------------------------------- | +| [`hydrate on idle`](#hydrate-on-idle) | Triggers when the browser is idle. | +| [`hydrate on viewport`](#hydrate-on-viewport) | Triggers when specified content enters the viewport | +| [`hydrate on interaction`](#hydrate-on-interaction) | Triggers when the user interacts with specified element | +| [`hydrate on hover`](#hydrate-on-hover) | Triggers when the mouse hovers over specified area | +| [`hydrate on immediate`](#hydrate-on-immediate) | Triggers immediately after non-deferred content has finished rendering | +| [`hydrate on timer`](#hydrate-on-timer) | Triggers after a specific duration | + +#### `hydrate on idle` + +The `hydrate on idle` trigger loads the deferrable view's dependencies and hydrates the content once the browser has reached an idle state, based on `requestIdleCallback`. + +```angular-html +@defer (hydrate on idle) { + +} @placeholder { +
Large component placeholder
+} +``` + +#### `hydrate on viewport` + +The `hydrate on viewport` trigger loads the deferrable view's dependencies and hydrates the corresponding page of the app when the specified content enters the viewport using the +[Intersection Observer API](https://developer.mozilla.org/docs/Web/API/Intersection_Observer_API). + +```angular-html +@defer (hydrate on viewport) { + +} @placeholder { +
Large component placeholder
+} +``` + +#### `hydrate on interaction` + +The `hydrate on interaction` trigger loads the deferrable view's dependencies and hydrates the content when the user interacts with the specified element through +`click` or `keydown` events. + +```angular-html +@defer (hydrate on interaction) { + +} @placeholder { +
Large component placeholder
+} +``` + +#### `hydrate on hover` + +The `hydrate on hover` trigger loads the deferrable view's dependencies and hydrates the content when the mouse has hovered over the triggered area through the +`mouseover` and `focusin` events. + +```angular-html +@defer (hydrate on hover) { + +} @placeholder { +
Large component placeholder
+} +``` + +#### `hydrate on immediate` + +The `hydrate on immediate` trigger loads the deferrable view's dependencies and hydrates the content immediately. This means that the deferred block loads as soon +as all other non-deferred content has finished rendering. + +```angular-html +@defer (hydrate on immediate) { + +} @placeholder { +
Large component placeholder
+} +``` + +#### `hydrate on timer` + +The `hydrate on timer` trigger loads the deferrable view's dependencies and hydrates the content after a specified duration. + +```angular-html +@defer (hydrate on timer(500ms)) { + +} @placeholder { +
Large component placeholder
+} +``` + +The duration parameter must be specified in milliseconds (`ms`) or seconds (`s`). + +### `hydrate when` + +The `hydrate when` trigger accepts a custom conditional expression and loads the deferrable view's dependencies and hydrates the content when the +condition becomes truthy. + +```angular-html +@defer (hydrate when condition) { + +} @placeholder { +
Large component placeholder
+} +``` + +Note: `hydrate when` conditions only trigger when they are the top-most dehydrated `@defer` block. The condition provided for the trigger is +specified in the parent component, which needs to exist before it can be triggered. If the parent block is dehydrated, that expression will not yet +be resolvable by Angular. + +### `hydrate never` + +The `hydrate never` allows users to specify that the content in the defer block should remain dehydrated indefinitely, effectively becoming static +content. Note that this applies to the initial render only. During a subsequent client-side render, a `@defer` block with `hydrate never` would +still fetch dependencies, as hydration only applies to initial load of server-side rendered content. In the example below, subsequent client-side +renders would load the `@defer` block dependencies on viewport. + +```angular-html +@defer (on viewport; hydrate never) { + +} @placeholder { +
Large component placeholder
+} +``` + +Note: Using `hydrate never` prevents hydration of the entire nested subtree of a given `@defer` block. No other `hydrate` triggers fire for content nested underneath that block. + +## Hydrate triggers alongside regular triggers + +Hydrate triggers are additional triggers that are used alongside regular triggers on a `@defer` block. Hydration is an initial load optimization, and that means hydrate triggers only apply to that initial load. Any subsequent client side render will still use the regular trigger. + +```angular-html +@defer (on idle; hydrate on interaction) { + +} @placeholder{ +
Example Placeholder
+} +``` + +In this example, on the initial load, the `hydrate on interaction` applies. Hydration will be triggered on interaction with the `` component. On any subsequent page load that is client-side rendered, for example when a user clicks a routerLink that loads a page with this component, the `on idle` will apply. + +## How does incremental hydration work with nested `@defer` blocks? + +Angular's component and dependency system is hierarchical, which means hydrating any component requires all of its parents also be hydrated. So if hydration is triggered for a child `@defer` block of a nested set of dehydrated `@defer` blocks, hydration is triggered from the top-most dehydrated `@defer` block down to the triggered child and fire in that order. + +```angular-html +@defer (hydrate on interaction) { + + @defer (hydrate on hover) { + + } @placeholder { +
Child placeholder
+ } +} @placeholder{ +
Parent Placeholder
+} +``` + +In the above example, hovering over the nested `@defer` block triggers hydration. The parent `@defer` block with the `` hydrates first, then the child `@defer` block with `` hydrates after. + +## Constraints + +Incremental hydration has the same constraints as full-application hydration, including limits on direct DOM manipulation and requiring valid HTML structure. Visit the [Hydration guide constraints](guide/hydration#constraints) section for more details. + +## Do I still need to specify `@placeholder` blocks? + +Yes. `@placeholder` block content is not used for incremental hydration, but a `@placeholder` is still necessary for subsequent client-side rendering cases. If your content was not on the route that was part of the initial load, then any navigation to the route that has your `@defer` block content renders like a regular `@defer` block. So the `@placeholder` is rendered in those client-side rendering cases. diff --git a/adev-ja/src/content/guide/ngmodules/overview.md b/adev-ja/src/content/guide/ngmodules/overview.md index 00c0ee444..9a4e61b73 100644 --- a/adev-ja/src/content/guide/ngmodules/overview.md +++ b/adev-ja/src/content/guide/ngmodules/overview.md @@ -1,67 +1,188 @@ # NgModules -**NgModules** configure the injector, the compiler and help organize related things together. +IMPORTANT: The Angular team recommends using [standalone components](guide/components/anatomy-of-components#-imports-in-the-component-decorator) instead of `NgModule` for all new code. Use this guide to understand existing code built with `@NgModule`. -An NgModule is a class marked by the `@NgModule` decorator. -`@NgModule` takes a metadata object that describes how to compile a component's template and how to create an injector at runtime. -It identifies the module's own components, directives, and pipes, making some of them public, through the `exports` property, so that external components can use them. -`@NgModule` can also add service providers to the application dependency injectors. +An NgModule is a class marked by the `@NgModule` decorator. This decorator accepts *metadata* that tells Angular how to compile component templates and configure dependency injection. -## Angular modularity +```typescript +import {NgModule} from '@angular/core'; -Modules are a great way to organize an application and extend it with capabilities from external libraries. +@NgModule({ + // Metadata goes here +}) +export class CustomMenuModule { } +``` + +An NgModule has two main responsibilities: +* Declaring components, directives, and pipes that belong to the NgModule +* Add providers to the injector for components, directives, and pipes that import the NgModule + +## Declarations + +The `declarations` property of the `@NgModule` metadata declares the components, directives, and pipes that belong to the NgModule. + +```typescript +@NgModule({ + /* ... */ + // CustomMenu and CustomMenuItem are components. + declarations: [CustomMenu, CustomMenuItem], +}) +export class CustomMenuModule { } +``` + +In the example above, the components `CustomMenu` and `CustomMenuItem` belong to `CustomMenuModule`. + +The `declarations` property additionally accepts _arrays_ of components, directives, and pipes. These arrays, in turn, may also contain other arrays. + +```typescript +const MENU_COMPONENTS = [CustomMenu, CustomMenuItem]; +const WIDGETS = [MENU_COMPONENTS, CustomSlider]; + +@NgModule({ + /* ... */ + // This NgModule declares all of CustomMenu, CustomMenuItem, + // CustomSlider, and CustomCheckbox. + declarations: [WIDGETS, CustomCheckbox], +}) +export class CustomMenuModule { } +``` + +If Angular discovers any components, directives, or pipes declared in more than one NgModule, it reports an error. + +Any components, directives, or pipes must be explicitly marked as `standalone: false` in order to be declared in an NgModule. + +```typescript +@Component({ + // Mark this component as `standalone: false` so that it can be declared in an NgModule. + standalone: false, + /* ... */ +}) +export class CustomMenu { /* ... */ } +``` + +### imports + +Components declared in an NgModule may depend on other components, directives, and pipes. Add these dependencies to the `imports` property of the `@NgModule` metadata. + +```typescript +@NgModule({ + /* ... */ + // CustomMenu and CustomMenuItem depend on the PopupTrigger and SelectorIndicator components. + imports: [PopupTrigger, SelectionIndicator], + declarations: [CustomMenu, CustomMenuItem], +}) +export class CustomMenuModule { } +``` -Angular libraries are NgModules, such as `FormsModule`, `HttpClientModule`, and `RouterModule`. -Many third-party libraries are available as NgModules such as the [Material Design component library](https://material.angular.io), [Ionic](https://ionicframework.com), or [Angular's Firebase integration](https://github.com/angular/angularfire). +The `imports` array accepts other NgModules, as well as standalone components, directives, and pipes. -NgModules consolidate components, directives, and pipes into cohesive blocks of functionality, each focused on a feature area, application business domain, workflow, or common collection of utilities. +### exports -Modules can also add services to the application. -Such services might be internally developed, like something you'd develop yourself or come from outside sources, such as the Angular router and HTTP client. +An NgModule can _export_ its declared components, directives, and pipes such that they're available to other components and NgModules. -Modules can be loaded eagerly when the application starts or lazy loaded asynchronously by the router. + ```typescript +@NgModule({ + imports: [PopupTrigger, SelectionIndicator], + declarations: [CustomMenu, CustomMenuItem], + + // Make CustomMenu and CustomMenuItem available to + // components and NgModules that import CustomMenuModule. + exports: [CustomMenu, CustomMenuItem], +}) +export class CustomMenuModule { } +``` + +The `exports` property is not limited to declarations, however. An NgModule can also export any other components, directives, pipes, and NgModules that it imports. + + ```typescript +@NgModule({ + imports: [PopupTrigger, SelectionIndicator], + declarations: [CustomMenu, CustomMenuItem], -NgModule metadata does the following: + // Also make PopupTrigger available to any component or NgModule that imports CustomMenuModule. + exports: [CustomMenu, CustomMenuItem, PopupTrigger], +}) +export class CustomMenuModule { } +``` + +## `NgModule` providers + +Tip: See the [Dependency Injection guide](guides/di) for information on dependency injection and providers. -* Declares which components, directives, and pipes belong to the module -* Makes some of those components, directives, and pipes public so that other module's component templates can use them -* Imports other modules with the components, directives, and pipes that components in the current module need -* Provides services that other application components can use +An `NgModule` can specify `providers` for injected dependencies. These providers are available to: +* Any standalone component, directive, or pipe that imports the NgModule, and +* The `declarations` and `providers` of any _other_ NgModule that imports the NgModule. -Every Module-based Angular application has at least one module, the root module. -You [bootstrap](guide/ngmodules/bootstrapping) that module to launch the application. +```typescript +@NgModule({ + imports: [PopupTrigger, SelectionIndicator], + declarations: [CustomMenu, CustomMenuItem], + + // Provide the OverlayManager service + providers: [OverlayManager], + /* ... */ +}) +export class CustomMenuModule { } + +@NgModule({ + imports: [CustomMenuModule], + declarations: [UserProfile], + providers: [UserDataClient], +}) +export class UserProfileModule { } +``` + +In the example above: +* The `CustomMenuModule` provides `OverlayManager`. +* The `CustomMenu` and `CustomMenuItem` components can inject `OverlayManager` because they're declared in `CustomMenuModule`. +* `UserProfile` can inject `OverlayManager` because its NgModule imports `CustomMenuModule`. +* `UserDataClient` can inject `OverlayManager` because its NgModule imports `CustomMenuModule`. + +### The `forRoot` and `forChild` pattern + +Some NgModules define a static `forRoot` method that accepts some configuration and returns an array of providers. The name "`forRoot`" is a convention that indicates that these providers are intended to be added exclusively to the _root_ of your application during bootstrap. + +Any providers included in this way are eagerly loaded, increasing the JavaScript bundle size of your initial page load. + +```typescript +boorstrapApplication(MyApplicationRoot, { + providers: [ + CustomMenuModule.forRoot(/* some config */), + ], +}); +``` + +Similarly, some NgModules may before a static `forChild` that indicates the providers are intended to be added to components within your application hierarchy. + +```typescript +@Component({ + /* ... */ + providers: [ + CustomMenuModule.forChild(/* some config */), + ], +}) +export class UserProfile { /* ... */ } +``` -The root module is all you need in an application with few components. -As the application grows, you refactor the root module into [feature modules](guide/ngmodules/feature-modules) that represent collections of related functionality. -You then import these modules into the root module. +## Bootstrapping an application -## The basic NgModule +IMPORTANT: The Angular team recommends using [bootstrapApplication](api/platform-browser/bootstrapApplication) instead of `bootstrapModule` for all new code. Use this guide to understand existing applications bootstrapped with `@NgModule`. -The [Angular CLI](/tools/cli) generates the following basic `AppModule` when creating a new application with the `--no-standalone` option. +The `@NgModule` decorator accepts an optional `bootstrap` array that may contain one or more components. - -import { BrowserModule } from '@angular/platform-browser'; -import { NgModule } from '@angular/core'; +You can use the [`bootstrapModule`](https://angular.dev/api/core/PlatformRef#bootstrapModule) method from either [`platformBrowser`](api/platform-browser/platformBrowser) or [`platformServer`](api/platform-server/platformServer) to start an Angular application. When run, this function locates any elements on the page with a CSS selector that matches the listed componet(s) and renders those components on the page. -import { AppComponent } from './app.component'; +```typescript +import {platformBrowser} from '@angular/platform-browser'; @NgModule({ - declarations: [AppComponent], - imports: [BrowserModule], - providers: [], - bootstrap: [AppComponent] + bootstrap: [MyApplication], }) -export class AppModule {} - +export class MyApplciationModule { } -At the top are the import statements. -The next section is where you configure the `@NgModule` by stating what components and directives belong to it (`declarations`) as well as which other modules it uses (`imports`). -For more information on the structure of an `@NgModule`, be sure to read [Bootstrapping](guide/ngmodules/bootstrapping). +platformBrowser().bootstrapModule(MyApplicationModule); +``` -## More on NgModules +Components listed in `bootstrap` are automatically included in the NgModule's declarations. - - - - - +When you bootstrap an application from an NgModule, the collected `providers` of this module and all of the `providers` of its `imports` are eagerly loaded and available to inject for the entire application. diff --git a/adev-ja/src/content/guide/signals/resource.md b/adev-ja/src/content/guide/signals/resource.md new file mode 100644 index 000000000..3de38a2f1 --- /dev/null +++ b/adev-ja/src/content/guide/signals/resource.md @@ -0,0 +1,115 @@ +# Async reactivity with resources + +IMPORTANT: `resource` is [experimental](reference/releases#experimental). It's ready for you to try, but it might change before it is stable. + +Most signal APIs are synchronous— `signal`, `computed`, `input`, etc. However, applications often need to deal with data that is available asynchronously. A `Resource` gives you a way to incorporate async data into your application's signal-based code. + +You can use a `Resource` to perform any kind of async operation, but the most common use-case for `Resource` is fetching data from a server. The following creates a resource to fetch some user data. + +The easiest way to create a `Resource` is the `resource` function. + +```typescript +import {resource, Signal} from '@angular/core'; + +const userId: Signal = getUserId(); + +const userResource = resource({ + // Define a reactive request computation. + // The request value recomputes whenever any read signals change. + request: () => ({id: userId()}), + + // Define an async loader that retrieves data. + // The resource calls this function every time the `request` value changes. + loader: ({request}) => fetchUser(request), +}); + +// Created a computed based on the result of the resource's loader function. +const firstName = computed(() => userResource.value().firstName); +``` + +The `resource` function accepts a `ResourceOptions` object with two main properties: `request` and `loader`. + +The `request` property defines a reactive computation that produce a request value. Whenever signals read in this computation change, the resource produces a new request value, similar to `computed`. + +The `loader` property defines a `ResourceLoader`— an async function that retrieves some state. The resource calls the loader every time the `request` computation produces a new value, passing that value to the loader. See [Resource loaders](#resource-loaders) below for more details. + +`Resource` has a `value` signal that contains the results of the loader. + +## Resource loaders + +When creating a resource, you specify a `ResourceLoader`. This loader is an async function that accepts a single parameter— a `ResourceLoaderParams` object— and returns a value. + +The `ResourceLoaderParams` object contains three properties: `request`, `previous`, and `abortSignal`. + +| Property | Description | +| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| `request` | The value of the resource's `request` computation. | +| `previous` | An object with a `status` property, containing the previous `ResourceStatus`. | +| `abortSignal` | An [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal). See [Aborting requests](#aborting-requests) below for details. | + +### Aborting requests + +A resource aborts an outstanding request if the `request` computation changes while the resource is loading. + +You can use the `abortSignal` in `ResourceLoaderParams` to respond to aborted requests. For example, the native `fetch` function accepts an `AbortSignal`: + +```typescript +const userId: Signal = getUserId(); + +const userResource = resource({ + request: () => ({id: userId()}), + loader: ({request, abortSignal}): Promise => { + // fetch cancels any outstanding HTTP requests when the given `AbortSignal` + // indicates that the request has been aborted. + return fetch(`users/${request.id}`, {signal: abortSignal}); + }, +}); +``` + +See [`AbortSignal` on MDN](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) for more details on request cancellation with `AbortSignal`. + +### Reloading + +You can programmatically trigger a resource's `loader` by calling the `reload` method. + +```typescript +const userId: Signal = getUserId(); + +const userResource = resource({ + request: () => ({id: userId()}), + loader: ({request}) => fetchUser(request), +}); + +// ... + +userResource.reload(); +``` + +### `undefined` requests + +A request value of `undefined` prevents the resource from running its loader, and will put the resource into an `Idle` state. + +## Resource status + +The resource object has several signal properties for reading the status of the asynchronous loader. + +| Property | Description | +| ----------- | --------------------------------------------------------------------------------------------------------------- | +| `value` | The most recent value of the resource, or `undefined` if no value has been recieved. | +| `hasValue` | Whether the resource has a value. | +| `error` | The most recent error encountered while running the resource's loader, or `undefined` if no error has occurred. | +| `isLoading` | Whether the resource loader is currently running. | +| `status` | The resource's specific `ResourceStatus`, as described below. | + +The `status` signal provides a specific `ResourceStatus` that describes the state of the resource. + +| Status | `value()` | Description | +| ----------- | :---------------- | ---------------------------------------------------------------------------- | +| `Idle` | `undefined` | The resource has no valid request and the loader has not run. | +| `Error` | `undefined` | The loader has encountered an error. | +| `Loading` | `undefined` | The loader is running as a result of the `request` value changing. | +| `Reloading` | Previous value | The loader is running as a result calling of the resource's `reload` method. | +| `Resolved` | Resolved value | The loader has completed. | +| `Local` | Locally set value | The resource's value has been set locally via `.set()` or `.update()` | + +You can use this status information to conditionally display user interface elements, such loading indicators and error messages. diff --git a/adev-ja/src/content/guide/zoneless.md b/adev-ja/src/content/guide/zoneless.md index 3d7e34193..5577b2339 100644 --- a/adev-ja/src/content/guide/zoneless.md +++ b/adev-ja/src/content/guide/zoneless.md @@ -81,15 +81,15 @@ Zoneless applications. In fact, removing these calls can lead to performance reg are used in applications that still rely on ZoneJS. -### `ExperimentalPendingTasks` for Server Side Rendering (SSR) +### `PendingTasks` for Server Side Rendering (SSR) If you are using SSR with Angular, you may know that it relies on ZoneJS to help determine when the application is "stable" and can be serialized. If there are asynchronous tasks that should prevent serialization, an application -not using ZoneJS will need to make Angular aware of these with the `ExperimentalPendingTasks` service. Serialization +not using ZoneJS will need to make Angular aware of these with the `PendingTasks` service. Serialization will wait for the first moment that all pending tasks have been removed. ```typescript -const taskService = inject(ExperimentalPendingTasks); +const taskService = inject(PendingTasks); const taskCleanup = taskService.add(); await doSomeWorkThatNeedsToBeRendered(); taskCleanup(); diff --git a/adev-ja/src/content/introduction/essentials/dependency-injection.md b/adev-ja/src/content/introduction/essentials/dependency-injection.md new file mode 100644 index 000000000..60fef13cf --- /dev/null +++ b/adev-ja/src/content/introduction/essentials/dependency-injection.md @@ -0,0 +1,60 @@ + +Reuse code and control behaviors across your application and tests. + + +When you need to share logic between components, Angular leverages the design pattern of [dependency injection](guide/di) that allows you to create a “service” which allows you to inject code into components while managing it from a single source of truth. + +## What are services? + +Services are reusable pieces of code that can be injected + +Similar to defining a component, services are comprised of the following: + +- A **TypeScript decorator** that declares the class as an Angular service via `@Injectable` and allows you to define what part of the application can access the service via the `providedIn` property (which is typically `'root'`) to allow a service to be accessed anywhere within the application. +- A **TypeScript class** that defines the desired code that will be accessible when the service is injected + +Here is an example of a `Calculator` service. + +```angular-ts +import {Injectable} from '@angular/core'; + +@Injectable({providedIn: 'root'}) +export class Calculator { + add(x: number, y: number) { + return x + y; + } +} +``` + +## How to use a service + +When you want to use a service in a component, you need to: + +1. Import the service +2. Declare a class field where the service is injected. Assign the class field to the result of the call of the built-in function `inject` which creates the service + +Here’s what it might look like in the `Receipt` component: + +```angular-ts +import { Component, inject } from '@angular/core'; +import { Calculator } from './calculator'; + +@Component({ + selector: 'app-receipt', + template: `

The total is {{ totalCost }}

`, +}) + +export class Receipt { + private calculator = inject(Calculator); + totalCost = this.calculator.add(50, 25); +} +``` + +In this example, the `Calculator` is being used by calling the Angular function `inject` and passing in the service to it. + +## Next Step + + + + + diff --git a/adev-ja/src/content/introduction/essentials/signals.md b/adev-ja/src/content/introduction/essentials/signals.md new file mode 100644 index 000000000..570d9da6c --- /dev/null +++ b/adev-ja/src/content/introduction/essentials/signals.md @@ -0,0 +1,80 @@ + +Create and manage dynamic data. + + +In Angular, you use *signals* to create and manage state. A signal is a lightweight wrapper around a value. + +Use the `signal` function to create a signal for holding local state: + +```typescript +import {signal} from '@angular/core'; + +// Create a signal with the `signal` function. +const firstName = signal('Morgan'); + +// Read a signal value by calling it— signals are functions. +console.log(firstName()); + +// Change the value of this signal by calling its `set` method with a new value. +firstName.set('Jaime'); + +// You can also use the `update` method to change the value +// based on the previous value. +firstName.update(name => name.toUpperCase()); +``` + +Angular tracks where signals are read and when they're updated. The framework uses this information to do additional work, such as updating the DOM with new state. This ability to respond to changing signal values over time is known as *reactivity*. + +## Computed expressions + +A `computed` is a signal that produces its value based on other signals. + +```typescript +import {signal, computed} from '@angular/core'; + +const firstName = signal('Morgan'); +const firstNameCapitalized = computed(() => firstName().toUpperCase()); + +console.log(firstNameCapitalized()); // MORGAN +``` + +A `computed` signal is read-only; it does not have a `set` or an `update` method. Instead, the value of the `computed` signal automatically changes when any of the signals it reads change: + +```typescript +import {signal, computed} from '@angular/core'; + +const firstName = signal('Morgan'); +const firstNameCapitalized = computed(() => firstName().toUpperCase()); +console.log(firstNameCapitalized()); // MORGAN + +firstName.set('Jaime'); +console.log(firstNameCapitalized()); // JAIME +``` + +## Using signals in components + +Use `signal` and `computed` inside your components to create and manage state: + +```typescript +@Component({/* ... */}) +export class UserProfile { + isTrial = signal(false); + isTrialExpired = signal(false); + showTrialDuration = computed(() => this.isTrial() && !this.isTrialExpired()); + + activateTrial() { + this.isTrial.set(true); + } +} +``` + +Tip: Want to know more about Angular Signals? See the [In-depth Signals guide](guide/signals) for the full details. + +## Next Step + +Now that you have learned how to declare and manage dynamic data, it's time to learn how to use that data inside of templates. + + + + + diff --git a/adev-ja/src/content/introduction/essentials/templates.md b/adev-ja/src/content/introduction/essentials/templates.md new file mode 100644 index 000000000..0a4336a3d --- /dev/null +++ b/adev-ja/src/content/introduction/essentials/templates.md @@ -0,0 +1,148 @@ + +Use Angular's template syntax to create dynamic user interfaces. + + +Component templates aren't just static HTML— they can use data from your component class and set up handlers for user interaction. + +## Showing dynamic text + +In Angular, a *binding* creates a dynamic connection between a component's template and its data. This connection ensures that changes to the component's data automatically update the rendered template. + +You can create a binding to show some dynamic text in a template by using double curly-braces: + +```angular-ts +@Component({ + selector: 'user-profile', + template: `

Profile for {{userName()}}

`, +}) +export class TodoListItem { + userName = signal('pro_programmer_123'); +} +``` + +When Angular renders the component, you see: + +```html +

Profile file pro_programmer_123

+``` + +Angular automatically keeps the binding up-to-date when the value of the signal changes. Building on +the example above, if we update the value of the `userName` signal: + +```typescript +this.userName.set('cool_coder_789'); +``` + +The rendered page updates to reflect the new value: + +```html +

Profile file cool_coder_789

+``` + +## Setting dynamic properties and attributes + +Angular supports binding dynamic values into DOM properties with square brackets: + +```angular-ts +@Component({ + /*...*/ + // Set the `disabled` property of the button based on the value of `isAccountDisabled`. + template: ``, +}) +export class UserProfile { + isValidUserId = signal(false); +} +``` + +You can also bind to HTML _attributes_ by prefixing the attribute name with `attr.`: + +```angular-html + +
    +``` + +Angular automatically updates DOM properties and attribute when the bound value changes. + +## Handling user interaction + +Angular lets you add event listeners to an element in your template with parentheses: + +```angular-ts +@Component({ + /*...*/ + // Add an 'click' event handler that calls the `cancelSubscription` method. + template: ``, +}) +export class UserProfile { + /* ... */ + + cancelSubscription() { /* Your event handling code goes here. */ } +} +``` + +If you need to pass the [event](https://developer.mozilla.org/docs/Web/API/Event) object to your listener, you can use Angular's built-in `$event` variable inside the function call: + +```angular-ts +@Component({ + /*...*/ + // Add an 'click' event handler that calls the `cancelSubscription` method. + template: ``, +}) +export class UserProfile { + /* ... */ + + cancelSubscription(event: Event) { /* Your event handling code goes here. */ } +} +``` + +## Control flow with `@if` and `@for` + +You can conditionally hide and show parts of a template with Angular's `@if` block: + +```angular-html +

    User profile

    + +@if (isAdmin()) { +

    Admin settings

    + +} +``` + +The `@if` block also supports an optional `@else` block: + +```angular-html +

    User profile

    + +@if (isAdmin()) { +

    Admin settings

    + +} @else { +

    User settings

    + +} +``` + +You can repeat part of a template multiple times with Angular's `@for` block: + +```angular-html +

    User profile

    + +
      + @for (badge of badges(); track badge.id) { +
    • {{badge.name}}
    • + } +
    +``` + +Angular's uses the `track` keyword, shown in the example above, to associate data with the DOM elements created by `@for`. See [_Why is track in @for blocks important?_](guide/templates/control-flow#why-is-track-in-for-blocks-important) for more info. + +Tip: Want to know more about Angular templates? See the [In-depth Templates guide](guide/templates) for the full details. + +## Next Step + +Now that you have dynamic data and templates in the application, it's time to learn how to enhance templates by conditionally hiding or showing certain elements, looping over elements, and more. + + + + + diff --git a/adev-ja/src/content/reference/extended-diagnostics/NG8103.md b/adev-ja/src/content/reference/extended-diagnostics/NG8103.md index cd1dacfee..0d2a96bfb 100644 --- a/adev-ja/src/content/reference/extended-diagnostics/NG8103.md +++ b/adev-ja/src/content/reference/extended-diagnostics/NG8103.md @@ -9,7 +9,6 @@ individually or by importing the `CommonModule`. import {Component} from '@angular/core'; @Component({ - standalone: true, // Template uses `*ngIf`, but no corresponding directive imported. imports: [], template: `
    Hi
    `, @@ -34,7 +33,6 @@ import {Component} from '@angular/core'; import {NgIf} from '@angular/common'; @Component({ - standalone: true, imports: [NgIf], template: `
    Hi
    `, }) @@ -50,7 +48,6 @@ import {Component} from '@angular/core'; import {CommonModule} from '@angular/common'; @Component({ - standalone: true, imports: [CommonModule], template: `
    Hi
    `, }) diff --git a/adev-ja/src/content/reference/extended-diagnostics/NG8113.md b/adev-ja/src/content/reference/extended-diagnostics/NG8113.md new file mode 100644 index 000000000..92a50a251 --- /dev/null +++ b/adev-ja/src/content/reference/extended-diagnostics/NG8113.md @@ -0,0 +1,48 @@ +# Unused Standalone Imports + +This diagnostic detects cases where the `imports` array of a `@Component` contains symbols that +aren't used within the template. + + + +@Component({ + imports: [UsedDirective, UnusedPipe] +}) +class AwesomeCheckbox {} + + + +## What's wrong with that? + +The unused imports add unnecessary noise to your code and can increase your compilation time. + +## What should I do instead? + +Delete the unused import. + + + +@Component({ + imports: [UsedDirective] +}) +class AwesomeCheckbox {} + + + +## What if I can't avoid this? + +This diagnostic can be disabled by editing the project's `tsconfig.json` file: + + +{ + "angularCompilerOptions": { + "extendedDiagnostics": { + "checks": { + "unusedStandaloneImports": "suppress" + } + } + } +} + + +See [extended diagnostic configuration](extended-diagnostics#configuration) for more info. diff --git a/adev-ja/src/content/reference/extended-diagnostics/overview.md b/adev-ja/src/content/reference/extended-diagnostics/overview.md index d64df7a36..94714804e 100644 --- a/adev-ja/src/content/reference/extended-diagnostics/overview.md +++ b/adev-ja/src/content/reference/extended-diagnostics/overview.md @@ -20,6 +20,7 @@ Currently, Angular supports the following extended diagnostics: | `NG8108` | [`skipHydrationNotStatic`](extended-diagnostics/NG8108) | | `NG8109` | [`interpolatedSignalNotInvoked`](extended-diagnostics/NG8109) | | `NG8111` | [`uninvokedFunctionInEventBinding`](extended-diagnostics/NG8111) | +| `NG8113` | [`unusedStandaloneImports`](extended-diagnostics/NG8113) | ## Configuration diff --git a/adev-ja/src/content/reference/migrations/overview.md b/adev-ja/src/content/reference/migrations/overview.md index a5eaa805f..d047fc664 100644 --- a/adev-ja/src/content/reference/migrations/overview.md +++ b/adev-ja/src/content/reference/migrations/overview.md @@ -15,4 +15,10 @@ Learn about how you can migrate your existing angular project to the latest feat Convert eagerly loaded component routes to lazy loaded ones. This allows the build process to split production bundles into smaller chunks, to load less JavaScript at initial page load. + + Convert existing `@Input` fields to the new signal input API that is now production ready. + + + Convert existing decorator query fields to the improved signal queries API. The API is now production ready. + diff --git a/adev-ja/src/content/reference/migrations/signal-inputs.md b/adev-ja/src/content/reference/migrations/signal-inputs.md new file mode 100644 index 000000000..d2b31625a --- /dev/null +++ b/adev-ja/src/content/reference/migrations/signal-inputs.md @@ -0,0 +1,116 @@ +# Migration to signal inputs + +Angular introduced an improved API for inputs that is considered +production ready as of v19. +Read more about signal inputs and their benefits in the [dedicated guide](guide/signals/inputs). + +To support existing teams that would like to use signal inputs, the Angular team +provides an automated migration that converts `@Input` fields to the new `input()` API. + +Run the schematic using the following command: + +```bash +ng generate @angular/core:signal-input-migration +``` + +Alternatively, the migration is available as a [code refactor action](https://code.visualstudio.com/docs/typescript/typescript-refactoring#_refactoring) in VSCode. +Install the latest version of the VSCode extension and click on an `@Input` field. +See more details in the section [below](#vscode-extension). + +## What does the migration change? + +1. `@Input()` class members are updated to their signal `input()` equivalent. +2. References to migrated inputs are updated to call the signal. + - This includes references in templates, host bindings or TypeScript code. + +**Before** + +```typescript +import {Component, Input} from '@angular/core'; + +@Component({ + template: `Name: {{name ?? ''}}` +}) +export class MyComponent { + @Input() name: string|undefined = undefined; + + someMethod(): number { + if (this.name) { + return this.name.length; + } + return -1; + } +} +``` + +**After** + + +import {Component, input} from '@angular/core'; + +@Component({ +template: `Name: {{name() ?? ''}}` +}) +export class MyComponent { +readonly name = input(); + +someMethod(): number { +const name = this.name(); +if (name) { +return name.length; +} +return -1; +} +} + + +## Configuration options + +The migration supports a few options for fine tuning the migration to your specific needs. + +### `--path` + +By default, the migration will update your whole Angular CLI workspace. +You can limit the migration to a specific sub-directory using this option. + +### `--best-effort-mode` + +By default, the migration skips inputs that cannot be safely migrated. +The migration tries to refactor code as safely as possible. + +When the `--best-effort-mode` flag is enabled, the migration eagerly +tries to migrate as much as possible, even if it could break your build. + +### `--insert-todos` + +When enabled, the migration will add TODOs to inputs that couldn't be migrated. +The TODOs will include reasoning on why inputs were skipped. E.g. + +```ts +// TODO: Skipped for migration because: +// Your application code writes to the input. This prevents migration. +@Input() myInput = false; +``` + +### `--analysis-dir` + +In large projects you may use this option to reduce the amount of files being analyzed. +By default, the migration analyzes the whole workspace, regardless of the `--path` option, in +order to update all references affected by an `@Input()` migration. + +With this option, you can limit analysis to a sub-folder. Note that this means that any +references outside this directory are silently skipped, potentially breaking your build. + +## VSCode extension + +![Screenshot of the VSCode extension and clicking on an `@Input` field](assets/images/migrations/signal-inputs-vscode.png "Screenshot of the VSCode extension and clicking on an `@Input` field.") + +The migration is available as a [code refactor action](https://code.visualstudio.com/docs/typescript/typescript-refactoring#_refactoring) in VSCode. + +To make use of the migration via VSCode, install the latest version of the VSCode extension and either click: + +- on a `@Input` field. +- or, on a directive/component + +Then, wait for the yellow lightbulb VSCode refactoring button to appear. +Via this button you can then select the signal input migration. diff --git a/adev-ja/src/content/reference/migrations/signal-queries.md b/adev-ja/src/content/reference/migrations/signal-queries.md new file mode 100644 index 000000000..8b9484c2d --- /dev/null +++ b/adev-ja/src/content/reference/migrations/signal-queries.md @@ -0,0 +1,115 @@ +# Migration to signal queries + +Angular introduced improved APIs for queries that are considered +production ready as of v19. +Read more about signal queries and their benefits in the [dedicated guide](guide/signals/queries). + +To support existing teams that would like to use signal queries, the Angular team +provides an automated migration that converts existing decorator query fields to the new API. + +Run the schematic using the following command: + +```bash +ng generate @angular/core:signal-queries-migration +``` + +Alternatively, the migration is available as a [code refactor action](https://code.visualstudio.com/docs/typescript/typescript-refactoring#_refactoring) in VSCode. +Install the latest version of the VSCode extension and click onto e.g. a `@ViewChild` field. +See more details in the section [below](#vscode-extension). + +## What does the migration change? + +1. `@ViewChild()`, `@ViewChildren`, `@ContentChild` and `@ContentChildren` class members + are updated to their signal equivalents. +2. References in your application to migrated queries are updated to call the signal. + - This includes references in templates, host bindings or TypeScript code. + +**Before** + +```typescript +import {Component, ContentChild} from '@angular/core'; + +@Component({ + template: `Has ref: {{someRef ? 'Yes' : 'No'}}` +}) +export class MyComponent { + @ContentChild('someRef') ref: ElementRef|undefined = undefined; + + someMethod() { + if (this.ref) { + this.ref.nativeElement; + } + } +} +``` + +**After** + +```typescript +import {Component, contentChild} from '@angular/core'; + +@Component({ + template: `Has ref: {{someRef() ? 'Yes' : 'No'}}` +}) +export class MyComponent { + readonly ref = contentChild('someRef'); + + someMethod() { + const ref = this.ref(); + if (ref) { + ref.nativeElement; + } + } +} +``` + +## Configuration options + +The migration supports a few options for fine tuning the migration to your specific needs. + +### `--path` + +By default, the migration will update your whole Angular CLI workspace. +You can limit the migration to a specific sub-directory using this option. + +### `--best-effort-mode` + +By default, the migration skips queries that cannot be safely migrated. +The migration tries to refactor code as safely as possible. + +When the `--best-effort-mode` flag is enabled, the migration eagerly +tries to migrate as much as possible, even if it could break your build. + +### `--insert-todos` + +When enabled, the migration will add TODOs to queries that couldn't be migrated. +The TODOs will include reasoning on why queries were skipped. E.g. + +```ts +// TODO: Skipped for migration because: +// Your application code writes to the query. This prevents migration. +@ViewChild('ref') ref?: ElementRef; +``` + +### `--analysis-dir` + +In large projects you may use this option to reduce the amount of files being analyzed. +By default, the migration analyzes the whole workspace, regardless of the `--path` option, in +order to update all references affected by a query declaration being migrated. + +With this option, you can limit analysis to a sub-folder. Note that this means that any +references outside this directory are silently skipped, potentially breaking your build. + +## VSCode extension + +![Screenshot of the VSCode extension and clicking on an `@ViewChild` field](assets/images/migrations/signal-queries-vscode.png "Screenshot of the VSCode extension and clicking on an `@ViewChild` field.") + +The migration is available as a [code refactor action](https://code.visualstudio.com/docs/typescript/typescript-refactoring#_refactoring) in VSCode. + +To make use of the migration via VSCode, install the latest version of the VSCode extension and either click: + +- on a `@ViewChild`, `@ViewChildren`, `@ContentChild`, or `@ContentChildren` field. +- on a directive/component + +Then, wait for the yellow lightbulb VSCode refactoring button to appear. +Via this button you can then select the signal queries migration. diff --git a/adev-ja/src/content/tools/cli/build-system-migration.md b/adev-ja/src/content/tools/cli/build-system-migration.md index 55dcdde38..bc9e353b9 100644 --- a/adev-ja/src/content/tools/cli/build-system-migration.md +++ b/adev-ja/src/content/tools/cli/build-system-migration.md @@ -1,4 +1,4 @@ -# Migrating to the new build system +# Angular application build system In v17 and higher, the new build system provides an improved way to build Angular applications. This new build system includes: @@ -6,13 +6,14 @@ In v17 and higher, the new build system provides an improved way to build Angula - Faster build-time performance for both initial builds and incremental rebuilds. - Newer JavaScript ecosystem tools such as [esbuild](https://esbuild.github.io/) and [Vite](https://vitejs.dev/). - Integrated SSR and prerendering capabilities. +- Automatic global and component stylesheet hot replacement. This new build system is stable and fully supported for use with Angular applications. You can migrate to the new build system with applications that use the `browser` builder. If using a custom builder, please refer to the documentation for that builder on possible migration options. IMPORTANT: The existing Webpack-based build system is still considered stable and fully supported. -Applications can continue to use the `browser` builder and will not be automatically migrated when updating. +Applications can continue to use the `browser` builder and projects can opt-out of migrating during an update. ## For new applications @@ -20,8 +21,9 @@ New applications will use this new build system by default via the `application` ## For existing applications -Both automated and manual procedures are available dependening on the requirements of the project. +Both automated and manual procedures are available depending on the requirements of the project. Starting with v18, the update process will ask if you would like to migrate existing applications to use the new build system via the automated migration. +Prior to migrating, please consider reviewing the [Known Issues](#known-issues) section as it may contain relevant information for your project. HELPFUL: Remember to remove any CommonJS assumptions in the application server code if using SSR such as `require`, `__filename`, `__dirname`, or other constructs from the [CommonJS module scope](https://nodejs.org/api/modules.html#the-module-scope). All application code should be ESM compatible. This does not apply to third-party dependencies. @@ -56,7 +58,8 @@ Additionally for existing projects, you can manually opt-in to use the new build Both options are considered stable and fully supported by the Angular team. The choice of which option to use is a factor of how many changes you will need to make to migrate and what new features you would like to use in the project. -- The `browser-esbuild` builder builds only the client-side bundle of an application designed to be compatible with the existing `browser` builder that provides the preexisting build system. It serves as a drop-in replacement for existing `browser` applications. +- The `browser-esbuild` builder builds only the client-side bundle of an application designed to be compatible with the existing `browser` builder that provides the preexisting build system. +This builder provides equivalent build options, and in many cases, it serves as a drop-in replacement for existing `browser` applications. - The `application` builder covers an entire application, such as the client-side bundle, as well as optionally building a server for server-side rendering and performing build-time prerendering of static pages. The `application` builder is generally preferred as it improves server-side rendered (SSR) builds, and makes it easier for client-side rendered projects to adopt SSR in the future. @@ -176,19 +179,310 @@ ng serve You can continue to use the [command line options](/cli/serve) you have used in the past with the development server. -## Hot module replacement +### Hot module replacement -JavaScript-based hot module replacement (HMR) is currently not supported. -However, global stylesheet (`styles` build option) HMR is available and enabled by default. -Angular focused HMR capabilities are currently planned and will be introduced in a future version. +Hot Module Replacement (HMR) is a technique used by development servers to avoid reloading the entire page when only part of an application is changed. +The changes in many cases can be immediately shown in the browser which allows for an improved edit/refresh cycle while developing an application. +While general JavaScript-based hot module replacement (HMR) is currently not supported, several more specific forms of HMR are available: +- **global stylesheets** (default) +- **component stylesheet** (default) +- **component template** (experimental opt-in) -## Unimplemented options and behavior +The stylesheet HMR capabilities are automatically enabled and require no code or configuration changes to use. +Angular provides HMR support for both file-based (`styleUrl`/`styleUrls`) and inline (`styles`) component styles. +The build system will attempt to compile and process the minimal amount of application code when it detects a stylesheet only change. +In many cases, no JavaScript/TypeScript processing will be required. -Several build options are not yet implemented but will be added in the future as the build system moves towards a stable status. If your application uses these options, you can still try out the build system without removing them. Warnings will be issued for any unimplemented options but they will otherwise be ignored. However, if your application relies on any of these options to function, you may want to wait to try. +If preferred, the HMR capabilities can be disabled by setting the `hmr` development server option to `false`. +This can also be changed on the command line via: -- [WASM imports](https://github.com/angular/angular-cli/issues/25102) -- WASM can still be loaded manually via [standard web APIs](https://developer.mozilla.org/docs/WebAssembly/Loading_and_running). + + +ng serve --no-hmr + + + +In addition to fully supported component stylesheet HMR, Angular provides **experimental** support for component template HMR. +Template HMR also requires no application code changes but currently requires the use of the `NG_HMR_TEMPLATES=1` environment variable to enable. + +IMPORTANT: Component **template** HMR is experimental and is not enabled by default. +Currently, only file-based (`styleUrl`) templates are supported and any inline template changes will cause a full page reload. +When manually enabled, there may be cases where the browser is not fully synchronized with the application code and a restart of the development server may be required. +If you encounter an issue while using this feature, please [report the bug](https://github.com/angular/angular-cli/issues) to help the Angular team stabilize the feature. + +### Vite as a development server + +The usage of Vite in the Angular CLI is currently within a _development server capacity only_. Even without using the underlying Vite build system, Vite provides a full-featured development server with client side support that has been bundled into a low dependency npm package. This makes it an ideal candidate to provide comprehensive development server functionality. The current development server process uses the new build system to generate a development build of the application in memory and passes the results to Vite to serve the application. The usage of Vite, much like the Webpack-based development server, is encapsulated within the Angular CLI `dev-server` builder and currently cannot be directly configured. + +### Prebundling + +Prebundling provides improved build and rebuild times when using the development server. +Vite provides [prebundling capabilities](https://vite.dev/guide/dep-pre-bundling) that are enabled by default when using the Angular CLI. +The prebundling process analyzes all the third-party project dependencies within a project and processes them the first time the development server is executed. +This process removes the need to rebuild and bundle the project's dependencies each time a rebuild occurs or the development server is executed. + +In most cases, no additional customization is required. However, some situations where it may be needed include: +- Customizing loader behavior for imports within the dependency such as the [`loader` option](#file-extension-loader-customization) +- Symlinking a dependency to local code for development such as [`npm link`](https://docs.npmjs.com/cli/v10/commands/npm-link) +- Working around an error encountered during prebundling of a dependency + +The prebundling process can be fully disabled or individual dependencies can be excluded if needed by a project. +The `dev-server` builder's `prebundle` option can be used for these customizations. +To exclude specific dependencies, the `prebundle.exclude` option is available: + + + "serve": { + "builder": "@angular/build:dev-server", + "options": { + "prebundle": { + "exclude": ["some-dep"] + } + }, + + +By default, `prebundle` is set to `true` but can be set to `false` to fully disable prebundling. +However, excluding specific dependencies is recommended instead since rebuild times will increase with prebundling disabled. + + + "serve": { + "builder": "@angular/build:dev-server", + "options": { + "prebundle": false + }, + + +## New features + +One of the main benefits of the application build system is the improved build and rebuild speed. +However, the new application build system also provides additional features not present in the `browser` builder. + +IMPORTANT: The new features of the `application` builder described here are incompatible with the `karma` test builder by default because it is using the `browser` builder internally. +Users can opt-in to use the `application` builder by setting the `builderMode` option to `application` for the `karma` builder. +This option is currently in developer preview. +If you notice any issues, please report them [here](https://github.com/angular/angular-cli/issues). + +### Build-time value replacement (define) + +The `define` option allows identifiers present in the code to be replaced with another value at build time. +This is similar to the behavior of Webpack's `DefinePlugin` which was previously used with some custom Webpack configurations that used third-party builders. +The option can either be used within the `angular.json` configuration file or on the command line. +Configuring `define` within `angular.json` is useful for cases where the values are constant and able to be checked in to source control. + +Within the configuration file, the option is in the form of an object. +The keys of the object represent the identifier to replace and the values of the object represent the corresponding replacement value for the identifier. +An example is as follows: + + + "build": { + "builder": "@angular/build:application", + "options": { + ... + "define": { + "SOME_NUMBER": "5", + "ANOTHER": "''this is a string literal, note the extra single quotes'", + "REFERENCE": "globalThis.someValue.noteTheAbsentSingleQuotes" + } + } + } + -## ESM default imports vs. namespace imports +HELPFUL: All replacement values are defined as strings within the configuration file. +If the replacement is intended to be an actual string literal, it should be enclosed in single quote marks. +This allows the flexibility of using any valid JSON type as well as a different identifier as a replacement. + +The command line usage is preferred for values that may change per build execution such as the git commit hash or an environment variable. +The CLI will merge `--define` values from the command line with `define` values from `angular.json`, including both in a build. +Command line usage takes precedence if the same identifier is present for both. +For command line usage, the `--define` option uses the format of `IDENTIFIER=VALUE`. + + +ng build --define SOME_NUMBER=5 --define "ANOTHER='these will overwrite existing'" + + +Environment variables can also be selectively included in a build. +For non-Windows shells, the quotes around the hash literal can be escaped directly if preferred. +This example assumes a bash-like shell but similar behavior is available for other shells as well. + + +export MY_APP_API_HOST="http://example.com" +export API_RETRY=3 +ng build --define API_HOST=\'$MY_APP_API_HOST\' --define API_RETRY=$API_RETRY + + +For either usage, TypeScript needs to be aware of the types for the identifiers 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 similar content: + +```ts +declare const SOME_NUMBER: number; +declare const ANOTHER: string; +declare const GIT_HASH: string; +declare const API_HOST: string; +declare const API_RETRY: number; +``` + +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, it may need to be adjusted to reference this newly added type definition file. + +IMPORTANT: This option will not replace identifiers contained within Angular metadata such as a Component or Directive decorator. + +### File extension loader customization + +IMPORTANT: This feature is only available with the `application` builder. + +Some projects may need to control how all files with a specific file extension are loaded and bundled into an application. +When using the `application` builder, the `loader` option can be used to handle these cases. +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 be used within the application code via an import statement or dynamic import expression. +The available loaders that can be used are: +* `text` - inlines the content as a `string` available as the default export +* `binary` - inlines the content as a `Uint8Array` available as the default export +* `file` - emits the file at the application output path and provides the runtime location of the file as the default export +* `empty` - considers the content to be empty and will not include it in bundles + +The `empty` value, while less common, can be useful for compatibility of third-party libraries that may contain bundler-specific import usage that needs to be removed. +One case for this is side-effect imports (`import 'my.css';`) of CSS files which has no effect in a browser. +Instead, the project can use `empty` and then the CSS files can be added to the `styles` build option or use some other injection method. + +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 of the build option usage to inline the content of SVG files into the bundled application would be as follows: + + + "build": { + "builder": "@angular/build:application", + "options": { + ... + "loader": { + ".svg": "text" + } + } + } + + +An SVG file can then be imported: +```ts +import contents from './some-file.svg'; + +console.log(contents); // ... +``` + +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: +```ts +declare module "*.svg" { + const content: string; + export default content; +} +``` + +The default project configuration is already setup to use any type definition files (`.d.ts` 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. + +### Import attribute loader customization + +For cases where only certain files should be loaded in a specific way, per file control over loading behavior is available. +This is accomplished with a `loader` [import attribute](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import/with) that can be used with both import statements and expressions. +The presence of the import attribute takes precedence over all other loading behavior including JS/TS and any `loader` build option values. +For general loading for all files of an otherwise unsupported file type, the [`loader`](#file-extension-loader-customization) build option is recommended. + +For the import attribute, the following loader values are supported: +* `text` - inlines the content as a `string` available as the default export +* `binary` - inlines the content as a `Uint8Array` available as the default export +* `file` - emits the file at the application output path and provides the runtime location of the file as the default export + +An additional requirement to use import attributes is that the TypeScript `module` option must be set to `esnext` to allow TypeScript to successfully build the application code. +Once `ES2025` is available within TypeScript, this change will no longer be needed. + +At this time, TypeScript does not support type definitions that are based on import attribute values. +The use of `@ts-expect-error`/`@ts-ignore` or the use of individual type definition files (assuming the file is only imported with the same loader attribute) is currently required. +As an example, an SVG file can be imported as text via: +```ts +// @ts-expect-error TypeScript cannot provide types based on attributes yet +import contents from './some-file.svg' with { loader: 'text' }; +``` + +The same can be accomplished with an import expression inside an async function. +```ts +async function loadSvg(): Promise { + // @ts-expect-error TypeScript cannot provide types based on attributes yet + return import('./some-file.svg', { with: { loader: 'text' } }).then((m) => m.default); +} +``` +For the import expression, the `loader` value must be a string literal to be statically analyzed. +A warning will be issued if the value is not a string literal. + +The `file` loader is useful when a file will be loaded at runtime through either a `fetch()`, setting to an image elements `src`, or other similar method. +```ts +// @ts-expect-error TypeScript cannot provide types based on attributes yet +import imagePath from './image.webp' with { loader: 'file' }; + +console.log(imagePath); // media/image-ULK2SIIB.webp +``` +For production builds as shown in the code comment above, hashing will be automatically added to the path for long-term caching. + +HELPFUL: When using the development server and using a `loader` attribute to import a file from a Node.js package, that package must be excluded from prebundling via the development server `prebundle` option. + +### Import/export conditions + +Projects may need to map certain import paths to different files based on the type of build. +This can be particularly useful for cases such as `ng serve` needing to use debug/development specific code but `ng build` needing to use code without any development features/information. +Several import/export [conditions](https://nodejs.org/api/packages.html#community-conditions-definitions) are automatically applied to support these project needs: +* For optimized builds, the `production` condition is enabled. +* For non-optimized builds, the `development` condition is enabled. +* For browser output code, the `browser` condition is enabled. + +An optimized build is determined by the value of the `optimization` option. +When `optimization` is set to `true` or more specifically if `optimization.scripts` is set to `true`, then the build is considered optimized. +This classification applies to both `ng build` and `ng serve`. +In a new project, `ng build` defaults to optimized and `ng serve` defaults to non-optimized. + +A useful method to leverage these conditions within application code is to combine them with [subpath imports](https://nodejs.org/api/packages.html#subpath-imports). +By using the following import statement: +```ts +import {verboseLogging} from '#logger'; +``` + +The file can be switched in the `imports` field in `package.json`: + + +{ + ... + "imports": { + "#logger": { + "development": "./src/logging/debug.ts", + "default": "./src/logging/noop.ts" + } + } +} + + +For applications that are also using SSR, browser and server code can be switched by using the `browser` condition: + + +{ + ... + "imports": { + "#crashReporter": { + "browser": "./src/browser-logger.ts", + "default": "./src/server-logger.ts" + } + } +} + + +These conditions also apply to Node.js packages and any defined [`exports`](https://nodejs.org/api/packages.html#conditional-exports) within the packages. + +HELPFUL: If currently using the `fileReplacements` build option, this feature may be able to replace its usage. + +## Known Issues + +There are currently several known issues that you may encounter when trying the new build system. This list will be updated to stay current. If any of these issues are currently blocking you from trying out the new build system, please check back in the future as it may have been solved. + +### Type-checking of Web Worker code and processing of nested Web Workers + +Web Workers can be used within application code using the same syntax (`new Worker(new URL('', import.meta.url))`) that is supported with the `browser` builder. +However, the code within the Worker will not currently be type-checked by the TypeScript compiler. TypeScript code is supported just not type-checked. +Additionally, any nested workers will not be processed by the build system. A nested worker is a Worker instantiation within another Worker file. + +### ESM default imports vs. namespace imports TypeScript by default allows default exports to be imported as namespace imports and then used in call expressions. This is unfortunately a divergence from the ECMAScript specification. @@ -232,20 +526,6 @@ import moment from 'moment'; console.log(moment().format()); ``` -## Vite as a development server - -The usage of Vite in the Angular CLI is currently within a _development server capacity only_. Even without using the underlying Vite build system, Vite provides a full-featured development server with client side support that has been bundled into a low dependency npm package. This makes it an ideal candidate to provide comprehensive development server functionality. The current development server process uses the new build system to generate a development build of the application in memory and passes the results to Vite to serve the application. The usage of Vite, much like the Webpack-based development server, is encapsulated within the Angular CLI `dev-server` builder and currently cannot be directly configured. - -## Known Issues - -There are currently several known issues that you may encounter when trying the new build system. This list will be updated to stay current. If any of these issues are currently blocking you from trying out the new build system, please check back in the future as it may have been solved. - -### Type-checking of Web Worker code and processing of nested Web Workers - -Web Workers can be used within application code using the same syntax (`new Worker(new URL('', import.meta.url))`) that is supported with the `browser` builder. -However, the code within the Worker will not currently be type-checked by the TypeScript compiler. TypeScript code is supported just not type-checked. -Additionally, any nested workers will not be processed by the build system. A nested worker is a Worker instantiation within another Worker file. - ### Order-dependent side-effectful imports in lazy modules Import statements that are dependent on a specific ordering and are also used in multiple lazy modules can cause top-level statements to be executed out of order. diff --git a/adev-ja/src/content/tools/cli/overview.md b/adev-ja/src/content/tools/cli/overview.md index 47b2fdfc8..13090475d 100644 --- a/adev-ja/src/content/tools/cli/overview.md +++ b/adev-ja/src/content/tools/cli/overview.md @@ -41,6 +41,12 @@ If neither option is supplied, the flag remains in its default state, as listed Array options can be provided in two forms: `--option value1 value2` or `--option value1 --option value2`. +### Key/value options + +Some options like `--define` expect an array of `key=value` pairs as their values. +Just like array options, key/value options can be provided in two forms: +`--define 'KEY_1="value1"' KEY_2=true` or `--define 'KEY_1="value1"' --define KEY_2=true`. + ### Relative paths Options that specify files can be given as absolute paths, or as paths relative to the current working directory, which is generally either the workspace or project root. diff --git a/adev-ja/src/content/tools/libraries/angular-package-format.md b/adev-ja/src/content/tools/libraries/angular-package-format.md index 7ee9d4699..6f13abee0 100644 --- a/adev-ja/src/content/tools/libraries/angular-package-format.md +++ b/adev-ja/src/content/tools/libraries/angular-package-format.md @@ -26,21 +26,16 @@ The following example shows a simplified version of the `@angular/core` package' ```markdown node_modules/@angular/core -├── README.md -├── package.json -├── index.d.ts -├── esm2022 -│ ├── core.mjs -│ ├── index.mjs -│ ├── public_api.mjs -│ └── testing -├── fesm2022 +├── README.md +├── package.json +├── index.d.ts +├── fesm2022 │ ├── core.mjs │ ├── core.mjs.map │ ├── testing.mjs │ └── testing.mjs.map -└── testing - └── index.d.ts +└── testing + └── index.d.ts ``` This table describes the file layout under `node_modules/@angular/core` annotated to describe the purpose of files and directories: @@ -50,8 +45,6 @@ This table describes the file layout under `node_modules/@angular/core` annotate | `README.md` | Package README, used by npmjs web UI. | | `package.json` | Primary `package.json`, describing the package itself as well as all available entrypoints and code formats. This file contains the "exports" mapping used by runtimes and tools to perform module resolution. | | `index.d.ts` | Bundled `.d.ts` for the primary entrypoint `@angular/core`. | -| `esm2022/`
      ─ `core.mjs`
      ─ `index.mjs`
      ─ `public_api.mjs` | Tree of `@angular/core` sources in unflattened ES2022 format. | -| `esm2022/testing/` | Tree of the `@angular/core/testing` entrypoint in unflattened ES2022 format. | | `fesm2022/`
      ─ `core.mjs`
      ─ `core.mjs.map`
      ─ `testing.mjs`
      ─ `testing.mjs.map` | Code for all entrypoints in flattened \(FESM\) ES2022 format, along with source maps. | | `testing/` | Directory representing the "testing" entrypoint. | | `testing/index.d.ts` | Bundled `.d.ts` for the `@angular/core/testing` entrypoint. | @@ -96,14 +89,10 @@ The `"exports"` field has the following structure: }, ".": { "types": "./core.d.ts", - "esm": "./esm2022/core.mjs", - "esm2022": "./esm2022/core.mjs", "default": "./fesm2022/core.mjs" }, "./testing": { "types": "./testing/testing.d.ts", - "esm": "./esm2022/testing/testing.mjs", - "esm2022": "./esm2022/testing/testing.mjs", "default": "./fesm2022/testing.mjs" } } @@ -116,8 +105,6 @@ For each entrypoint, the available formats are: | Formats | Details | |:--- |:--- | | Typings \(`.d.ts` files\) | `.d.ts` files are used by TypeScript when depending on a given package. | -| `es2022` | ES2022 code flattened into a single source file. | -| `esm2022` | ES2022 code in unflattened source files \(this format is included for experimentation - see [this discussion of defaults](#note-about-the-defaults-in-packagejson) for details\). | | `default` | ES2022 code flattened into a single source. Tooling that is aware of these keys may preferentially select a desirable code format from `"exports"`. @@ -263,14 +250,6 @@ To generate a flattened ES Module index file, use the following configuration op Once the index file \(for example, `my-ui-lib.js`\) is generated by ngc, bundlers and optimizers like Rollup can be used to produce the flattened ESM file. -#### Note about the defaults in package.json - -As of webpack v4, the flattening of ES modules optimization should not be necessary for webpack users. It should be possible to get better code-splitting without flattening of modules in webpack. -In practice, size regressions can still be seen when using unflattened modules as input for webpack v4. -This is why `module` and `es2022` package.json entries still point to FESM files. -This issue is being investigated. It is expected to switch the `module` and `es2022` package.json entry points to unflattened files after the size regression issue is resolved. -The APF currently includes unflattened ESM2022 code for the purpose of validating such a future change. - ### "sideEffects" flag By default, EcmaScript Modules are side-effectful: importing from a module ensures that any code at the top level of that module should run. From fdb847a0f893590197c473c75a61d59a319ae6d3 Mon Sep 17 00:00:00 2001 From: Suguru Inatomi Date: Wed, 20 Nov 2024 15:02:39 +0900 Subject: [PATCH 03/27] fix: migrate tutorial contents --- .../learn-angular/steps/11-optimizing-images/README.en.md | 2 -- .../learn-angular/steps/11-optimizing-images/README.md | 2 -- .../learn-angular/steps/12-enable-routing/README.en.md | 1 - .../tutorials/learn-angular/steps/12-enable-routing/README.md | 1 - .../tutorials/learn-angular/steps/14-routerLink/README.en.md | 2 -- .../tutorials/learn-angular/steps/14-routerLink/README.md | 2 -- .../content/tutorials/learn-angular/steps/15-forms/README.en.md | 1 - .../content/tutorials/learn-angular/steps/15-forms/README.md | 1 - .../learn-angular/steps/17-reactive-forms/README.en.md | 1 - .../tutorials/learn-angular/steps/17-reactive-forms/README.md | 1 - .../tutorials/learn-angular/steps/24-create-a-pipe/README.en.md | 2 -- .../tutorials/learn-angular/steps/24-create-a-pipe/README.md | 2 -- 12 files changed, 18 deletions(-) diff --git a/adev-ja/src/content/tutorials/learn-angular/steps/11-optimizing-images/README.en.md b/adev-ja/src/content/tutorials/learn-angular/steps/11-optimizing-images/README.en.md index baa59de49..526fb8b99 100644 --- a/adev-ja/src/content/tutorials/learn-angular/steps/11-optimizing-images/README.en.md +++ b/adev-ja/src/content/tutorials/learn-angular/steps/11-optimizing-images/README.en.md @@ -16,7 +16,6 @@ In order to leverage the `NgOptimizedImage` directive, first import it from the import { NgOptimizedImage } from '@angular/common'; @Component({ - standalone: true, imports: [NgOptimizedImage], ... }) @@ -32,7 +31,6 @@ To enable the `NgOptimizedImage` directive, swap out the `src` attribute for `ng import { NgOptimizedImage } from '@angular/common'; @Component({ - standalone: true, template: ` ...
  • diff --git a/adev-ja/src/content/tutorials/learn-angular/steps/11-optimizing-images/README.md b/adev-ja/src/content/tutorials/learn-angular/steps/11-optimizing-images/README.md index 5185d3654..99bdd44fe 100644 --- a/adev-ja/src/content/tutorials/learn-angular/steps/11-optimizing-images/README.md +++ b/adev-ja/src/content/tutorials/learn-angular/steps/11-optimizing-images/README.md @@ -16,7 +16,6 @@ import { NgOptimizedImage } from '@angular/common'; @Component({ - standalone: true, imports: [NgOptimizedImage], ... }) @@ -32,7 +31,6 @@ import { NgOptimizedImage } from '@angular/common'; import { NgOptimizedImage } from '@angular/common'; @Component({ - standalone: true, template: ` ...
  • diff --git a/adev-ja/src/content/tutorials/learn-angular/steps/12-enable-routing/README.en.md b/adev-ja/src/content/tutorials/learn-angular/steps/12-enable-routing/README.en.md index 71c3183d0..927bb72da 100644 --- a/adev-ja/src/content/tutorials/learn-angular/steps/12-enable-routing/README.en.md +++ b/adev-ja/src/content/tutorials/learn-angular/steps/12-enable-routing/README.en.md @@ -62,7 +62,6 @@ import {RouterOutlet} from '@angular/router'; `, - standalone: true, imports: [RouterOutlet], }) export class AppComponent {} diff --git a/adev-ja/src/content/tutorials/learn-angular/steps/12-enable-routing/README.md b/adev-ja/src/content/tutorials/learn-angular/steps/12-enable-routing/README.md index bec8301b4..b356c9d4b 100644 --- a/adev-ja/src/content/tutorials/learn-angular/steps/12-enable-routing/README.md +++ b/adev-ja/src/content/tutorials/learn-angular/steps/12-enable-routing/README.md @@ -62,7 +62,6 @@ import {RouterOutlet} from '@angular/router'; `, - standalone: true, imports:[RouterOutlet], }) export class AppComponent {} diff --git a/adev-ja/src/content/tutorials/learn-angular/steps/14-routerLink/README.en.md b/adev-ja/src/content/tutorials/learn-angular/steps/14-routerLink/README.en.md index 813ca3bc3..f01ad405e 100644 --- a/adev-ja/src/content/tutorials/learn-angular/steps/14-routerLink/README.en.md +++ b/adev-ja/src/content/tutorials/learn-angular/steps/14-routerLink/README.en.md @@ -17,7 +17,6 @@ In `app.component.ts` add the `RouterLink` directive import to the existing impo import { RouterLink, RouterOutlet } from '@angular/router'; @Component({ - standalone: true, imports: [RouterLink, RouterOutlet], ... }) @@ -34,7 +33,6 @@ import { RouterLink, RouterOutlet } from '@angular/router'; @Component({ ... - standalone: true, template: ` ... Home diff --git a/adev-ja/src/content/tutorials/learn-angular/steps/14-routerLink/README.md b/adev-ja/src/content/tutorials/learn-angular/steps/14-routerLink/README.md index 8e600c3c6..532f57f32 100644 --- a/adev-ja/src/content/tutorials/learn-angular/steps/14-routerLink/README.md +++ b/adev-ja/src/content/tutorials/learn-angular/steps/14-routerLink/README.md @@ -17,7 +17,6 @@ import { RouterLink, RouterOutlet } from '@angular/router'; @Component({ - standalone: true, imports: [RouterLink, RouterOutlet], ... }) @@ -34,7 +33,6 @@ import { RouterLink, RouterOutlet } from '@angular/router'; @Component({ ... - standalone: true, template: ` ... Home diff --git a/adev-ja/src/content/tutorials/learn-angular/steps/15-forms/README.en.md b/adev-ja/src/content/tutorials/learn-angular/steps/15-forms/README.en.md index 0fafc8c5e..08dbb5bc9 100644 --- a/adev-ja/src/content/tutorials/learn-angular/steps/15-forms/README.en.md +++ b/adev-ja/src/content/tutorials/learn-angular/steps/15-forms/README.en.md @@ -35,7 +35,6 @@ import {FormsModule} from '@angular/forms'; @Component({ ... - standalone: true, imports: [FormsModule], }) export class UserComponent {} diff --git a/adev-ja/src/content/tutorials/learn-angular/steps/15-forms/README.md b/adev-ja/src/content/tutorials/learn-angular/steps/15-forms/README.md index 62e534f18..c8b9d446f 100644 --- a/adev-ja/src/content/tutorials/learn-angular/steps/15-forms/README.md +++ b/adev-ja/src/content/tutorials/learn-angular/steps/15-forms/README.md @@ -35,7 +35,6 @@ import {FormsModule} from '@angular/forms'; @Component({ ... - standalone: true, imports:[FormsModule], }) export class UserComponent {} diff --git a/adev-ja/src/content/tutorials/learn-angular/steps/17-reactive-forms/README.en.md b/adev-ja/src/content/tutorials/learn-angular/steps/17-reactive-forms/README.en.md index a44d5bce7..c257767e0 100644 --- a/adev-ja/src/content/tutorials/learn-angular/steps/17-reactive-forms/README.en.md +++ b/adev-ja/src/content/tutorials/learn-angular/steps/17-reactive-forms/README.en.md @@ -17,7 +17,6 @@ import { ReactiveFormsModule } from '@angular/forms'; @Component({ selector: 'app-root', - standalone: true, template: `