---
title: "JSSアプリをJSS 21.11にアップグレードする"
slug: "upgrade-jss-apps-to-jss-21-11"
abstract: "最新の改善、特にAngular 20へのアップデートを享受するために、JavaScriptレンダリングSDKをバージョン21.11にアップグレードする方法。"
---
# JSSアプリをJSS 21.11にアップグレードする

Sitecore JavaScript Rendering SDKバージョン21.11はAngularのバージョン20のサポートを導入します。アップグレードするには、Angularアプリにいくつかの小さな変更を加える必要があります。

> !注**始める前に**
> 
> -   まだであれば、[アプリをJSS 21.10にアップグレード](https://doc.sitecore.com/xp/en/developers/hd/21/sitecore-headless-development/upgrade-jss-apps-to-jss-21-10.html)してください。
>     
> -   このプロセスにはAngularをバージョン20にアップデートすることも含まれるため、アプリのアップグレード手続きを完了するには [公式ガイド](https://angular.dev/update-guide?v=18.0-20.0&l=3) を参照する必要があります。
>     
> -   アップグレードの影響を理解するために、[JSS 21.11](http://https://github.com/Sitecore/jss/releases/tag/v21.11.0)に精通してください。
>     

このトピックでは、以下の方法を説明します:

1.  [既存のアプリ内のAngularテンプレートファイルを更新してください](https://doc.sitecore.com/xp/ja/developers/hd/21/sitecore-headless-development/upgrade-jss-apps-to-jss-21-11.html#UUID-92b28e7f-3f70-8cfe-5a6b-d572ddbb17b4_section-id235281237141058 "Update the Angular template files in your existing app")
2.  [既存のアプリでアプリケーション依存関係を更新する](https://doc.sitecore.com/xp/ja/developers/hd/21/sitecore-headless-development/upgrade-jss-apps-to-jss-21-11.html#UUID-92b28e7f-3f70-8cfe-5a6b-d572ddbb17b4_section-id235281233363217 "Update application dependencies in your existing app")

## 既存のアプリ内のAngularテンプレートファイルを更新してください

このバージョンのJSSはAngularをバージョン20にアップグレードし、コンポーネントをデフォルトでスタンドアロンに切り替えます。アプリのアップグレードプロセスを完了し、スタンドアロンコンポーネントや[関連する移行](https://v20.angular.dev/reference/migrations)に慣れるには[、公式のAngularガイド](https://angular.dev/update-guide?v=18.0-20.0&l=3)を参照してください。

JSSアプリをAngular 20にアップグレードするには:

1.  既存のアプリケーションのpackage.jsonファイルで、以下の依存関係を指定されたバージョンに更新してください:
    
    "@angular/animations": "~20.3.10",
    "@angular/common": "~20.3.10",
    "@angular/compiler": "~20.3.10",
    "@angular/core": "~20.3.10",
    "@angular/forms": "~20.3.10",
    "@angular/platform-browser": "~20.3.10",
    "@angular/platform-browser-dynamic": "~20.3.10",
    "@angular/platform-server": "~20.3.10",
    "@angular/router": "~20.3.10",
    ....
    "apollo-angular": "~11.0.0",
    ...
    "graphql": "~16.11.0",
    ...
    "zone.js": "~0.15.0",
    ...
    "@angular-builders/custom-webpack": "^20.0.0",
    "@angular-devkit/build-angular": "^20.3.9",
    "@angular-eslint/builder": "^20.5.1",
    "@angular-eslint/eslint-plugin": "^20.5.1",
    "@angular-eslint/eslint-plugin-template": "^20.5.1",
    "@angular-eslint/schematics": "^20.5.1",
    "@angular-eslint/template-parser": "^20.5.1",
    "@angular/cli": "~20.3.9",
    "@angular/compiler-cli": "~20.3.10",
    "@angular/language-service": "~20.3.10",
    ...
    "typescript": "~5.8.0"
    
2.  src/appフォルダの中:
    
    -   以下の内容を持つ新しいファイル「 ViewBag.ts 」を追加します。
        
        export interface ViewBag {
         key: string: unknown;
         dictionary: { key: string: string };
        }
        
    -   以下の内容を持つ新しいファイル「 injection-tokens.ts 」を追加します。
        
        import { InjectionToken } from '@angular/core';
        import { InMemoryCache } from '@apollo/client/core';
        import { JssState } from './JssState';
        import { ViewBag } from './ViewBag';
        
        /\*\*
         \* Injection token for server-side layout data provided by server.bundle
         \*/
        export const JSS\_SERVER\_LAYOUT\_DATA = new InjectionToken<JssState>('JSS\_SERVER\_LAYOUT\_DATA');
        
        export const JSS\_SERVER\_VIEWBAG = new InjectionToken<ViewBag>('JSS\_SERVER\_VIEWBAG');
        
        export const APOLLO\_CACHE = new InjectionToken<InMemoryCache>('APOLLO\_CACHE');
        
3.  すべてのクラスフィールドインスタンスのフィールド初期化をコンストラクタで置き換えるためにinject() メソッドを用いてください。
    
    例えば、src/app/jss-context.service.tsにおいて、元の構成子は次のように示されました:
    
    constructor(protected transferState: TransferState, protected layoutService: JssLayoutService, protected stateService: JssStateService<JssState>) {}
    
    ここでのinject() 方法を使うと:
    
    -   angularパッケージからメソッドをインポートします:
        
        import { Injectable, TransferState, makeStateKey, inject } from '@angular/core';
        
    -   inject()関数を使って、示すようにコンストラクタからフィールドの初期化を除去します。
        
        protected transferState = inject(TransferState);
        protected layoutService = inject(JssLayoutService);
        protected stateService = inject(JssStateService<JssState>);
        
    -   上記の手順を、コンポーネントやサービス(例: src/app/jss-context.server.ts、jss-graphql.service.tsファイルなど)の他のアプリロジックについて繰り返します。
        
4.  declarationsを使うすべての加群については、代わりに の項目をimportsに移動させます。
    
    -   例えば、src/app/routing/routing.module.tsでは、既存の宣言は以下の通りです。
        
        @NgModule({
         imports: 
         ....
         ,
         exports: ...,
         declarations: NotFoundComponent, ServerErrorComponent, LayoutComponent, NavigationComponent,
        
        エントリをインポートに移動してください:
        
        @NgModule({
         imports: 
         ...
         LayoutComponent,
         NotFoundComponent,
         ServerErrorComponent,
         ,
         exports: RouterModule, TranslateModule,
         ...
        })
        
    -   同様に、src/app/routing/scripts/scripts.module.tsでは、ScriptsComponentとVisitorIdentificationComponent (存在する場合は)をdeclarationsからimportsに移動させます。
        
        @NgModule({
         exports: ScriptsComponent,
         imports: ScriptsComponent, VisitorIdentificationComponent,
        })
        
    -   src/app/components/app-components.shared.module.tsのStyleguideSpecimenComponentや、スタンドアロンにしたい他のコンポーネントモジュールにも同じ手順を行ってください。
        
5.  app.component.tsファイルは、SSRプロキシのサポート継続とシンプルさのため、スタンドアロンではありません。app.component.ts ファイルには以下の変更を加えてください:
    
    -   示すようにstandalone: falseでコンポーネントをマークしてください
        
        @Component({
         selector: 'app-root',
         templateUrl: './app.component.html'
         templateUrl: './app.component.html',
         /\* eslint-disable-next-line @angular-eslint/prefer-standalone \*/
         standalone: false,
        })
        
    -   OnInitインターフェースを実装してください
        
        export class AppComponent implements OnInit, OnDestroy {
        
    -   ngInit()メソッドを加えます:
        
        ngOnInit() {
        this.contextSubscription = this.jssContextService.state.subscribe((jssState: { language: string }) => {
         // listen for language changes
         if (jssState.language) {
         this.translate.use(jssState.language);
         }
        });
        }
        
    -   元のコンストラクタを削除し、inject() メソッドでフィールドを初期化します:
        
        ...
        private contextSubscription: Subscription;
        private translate = inject(TranslateService);
        private jssContextService = inject(JssContextService);
        ...
        
    -   アプリコンポーネントをスタンドアロンにしないと、declarationsセクションはそのままapp.module.tsにできますが、インジェクショントークンを使うように修正app.server.module.ts必要です。
        
        既存の文字列トークンを見つける:
        
        TranslateModule.forRoot({
         ....
         deps: 'JSS\_SERVER\_VIEWBAG', TransferState,
         ....
         }),
        
        インポートされたトークンオブジェクトに置き換えます:
        
        import { JSS\_SERVER\_VIEWBAG } from './src/app/injection-tokens';
        ....
        ....
        TranslateModule.forRoot({
         ...
         deps: JSS\_SERVER\_VIEWBAG, TransferState,
         ...
         }),
        
6.  server.bundle.tsファイルでインジェクショントークンを使いましょう:
    
    -   インジェクショントークンをインポートする:
        
        import { JSS\_SERVER\_LAYOUT\_DATA, JSS\_SERVER\_VIEWBAG } from './src/app/injection-tokens';
        
    -   示すようにrenderModule関数のextraProvidersセクションに注入トークンを追加します。
        
        renderModule(AppServerModule, {
         document: template,
         url: path,
         extraProviders: 
         // custom injection with the initial state that SSR should utilize
         { provide: JSS\_SERVER\_LAYOUT\_DATA, useValue: transferState },
         { provide: JSS\_SERVER\_VIEWBAG, useValue: state.viewBag },
         ,
         })
        
7.  アプリのsrc/app/routing/layout/layout.component.tsファイルでは:
    
    -   以下のインポートが存在していることを確認してください:
        
        import { Component, OnInit, OnDestroy, inject } from '@angular/core';
        import {
         RouteData,
         Field,
         LayoutServiceContextData,
         getContentStylesheetLink,
         JssModule,
        } from '@sitecore-jss/sitecore-jss-angular';
        ...
        import { NotFoundComponent } from '../not-found/not-found.component';
        import { ServerErrorComponent } from '../server-error/server-error.component';
        import { ScriptsComponent } from '../scripts/scripts.component';
        ...
        import { CommonModule } from '@angular/common';
        
    -   Component指令の分importsセクションを追加してください:
        
        @Component({
         selector: 'app-layout',
         templateUrl: './layout.component.html',
         imports: CommonModule, JssModule, NotFoundComponent, ServerErrorComponent, ScriptsComponent,
        })
        
    -   inject()関数を使って、示すようにコンストラクタからフィールドの初期化を除去します。
        
        private activatedRoute = inject(ActivatedRoute);
        private readonly meta = inject(JssMetaService);
        private linkService = inject(JssLinkService);
        
8.  アプリのjss-graphql.module.tsファイルでは:
    
    -   angularパッケージからinjectをインポートし、apollo-angularパッケージからApolloModuleをprovideApolloに置き換え、示すようにAPOLLO\_CACHEインジェクショントークンをインポートします。
        
        import { makeStateKey, TransferState, NgModule, PLATFORM\_ID, inject } from '@angular/core';
        ....
        import { Apollo, provideApollo } from 'apollo-angular';
        ...
        import { APOLLO\_CACHE } from './injection-tokens';
        
    -   GraphQLModule外に次の2つの新しい関数を追加します:
        
        const getGraphQLCache = () => {
         const possibleTypes = {} as PossibleTypesMap;
         introspectionQueryResultData.\_\_schema.types.forEach((supertype) => {
         possibleTypessupertype.name = supertype.possibleTypes.map((subtype) => subtype.name);
         });
         return new InMemoryCache({
         possibleTypes,
         });
        };
        
        const getApolloOptions = () => {
         const httpLink = inject(HttpBatchLink);
         const platformId = inject(PLATFORM\_ID);
         /\*
         QUERY LINK SELECTION
         A link is transport which GraphQL queries are pushed across.
         You have many choices.
         See the apollo-link documentation for more details.
        \*/
        
         // set sc\_apikey header which is required for any GraphQL calls
         const sc\_apikey = new HttpHeaders().set('sc\_apikey', environment.sitecoreApiKey);
        
         // choose between a basic HTTP link to run queries...
         // import { createHttpLink } from 'apollo-angular-link-http';
         // const link = createHttpLink({ uri: endpoint });
        
         // ...or a batched link (multiple queries within 10ms all go in one HTTP request)
         const batchHttp = httpLink.create({
         uri: environment.graphQLEndpoint,
         headers: sc\_apikey,
         });
        
         const cache = inject(APOLLO\_CACHE);
        
         return {
         link: batchHttp,
         cache,
         ssrMode: isPlatformServer(platformId),
         ssrForceFetchDelay: 100,
         };
        }
        
    -   ApolloModuleをimportsから削除し、providersセクションを図のように展開します:
        
        @NgModule({
         imports: 
         HttpClientModule, // provides HttpClient for HttpLink
         ,
         providers: 
         JssGraphQLService,
         { provide: APOLLO\_CACHE, useValue: getGraphQLCache() },
         provideApollo(getApolloOptions),
         ,
        })
        
    -   モジュール構造体を次のように修正します:
        
        constructor() {
         this.addCacheEvents();
        }
        
    -   inject()関数で2つのモジュールフィールドを初期化します:
        
        private readonly transferState = inject(TransferState);
        apolloClient = inject(Apollo);
        
    -   createApolloClient方法を以下の方法に置き換えます:
        
        private addCacheEvents(): void {
         const cache = inject(APOLLO\_CACHE);
        
         const isBrowser = this.transferState.hasKey(STATE\_KEY);
        
         if (isBrowser) {
         this.onBrowser(cache);
         } else {
         this.onServer(cache);
         }
        }
        
9.  アプリのsrc/app/jss-graphql.service.tsファイルで、inject() 関数を使って構成体からフィールド初期化を削除します。
    
    protected apollo = inject(Apollo);
    protected sitecoreContext = inject(JssContextService);
    protected platformId = inject(PLATFORM\_ID);
    
10.  コンポーネント内のngIfやngForのすべての使用を新しい@ifおよび@for指示に置き換えることも可能です。その方法については更新された[Angularサンプル](https://github.com/Sitecore/jss/tree/v22.10.0/packages/sitecore-jss-angular)をご覧ください。スタンドアロンコンポーネントでNgIfとNgForを使い続けるには、@angular/core packageからngIfとngForをインポートし、コンポーネントのimportsセクションに追加してください:
     
     @Component({
      ...
      imports: NgIf, NgFor, ....,
     })
     export class MyComponent implements .... {...
     

## 既存のアプリでアプリケーション依存関係を更新する

アップグレードしたアプリケーションを正しく動作させるには、依存関係を更新する必要があります。

依存関係を更新するには:

1.  既存のアプリケーションのpackage.jsonファイルで、すべての @sitecore-jssパッケージをバージョン ~21.11.0に更新してください。
    
2.  以下のコマンドで依存関係をインストールします:
    
    npm install