【Angular Universal】SSR로 404를 돌려준다 (클라이언트측으로부터 express Response를 조작하는 방법)



해결하는 문제



존재하지 않는 페이지를 요청하면 일반 사이트 인 경우 Http Status Code를 404: Not Found로 반환합니다.

그러나 SPA의 경우 기점이 되는 index.html 가 문제 없이 취득할 수 있기 때문에, 적당히 친 경로에 액세스하려고 하면 항상 200: OK
이것은 SPA를 개발하는 사람이라면 누구나 한 번은 괴롭히는 문제라고 생각합니다.
이번에는 Angular Universal에서이 문제를 해결합니다.

서버측


  • 서버 측은 평소와 같이 @nguniversal/express-engine를 사용하여 SSR에 대비합니다.
  • 자세한 내용은 공식 문서을 참조하십시오.

    server.ts
    import { ngExpressEngine } from '@nguniversal/express-engine';
    import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';
    
    ...
    
    const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require(path.join(DIST_FOLDER, 'main.bundle'));
    
    const server = express();
    
    server.engine('html', ngExpressEngine({
        bootstrap: AppServerModuleNgFactory,
        providers: [ provideModuleMap(LAZY_MODULE_MAP) ],
    }));
    
    ...
    

    클라이언트측



    알 수없는 URL 리디렉션


  • 모든 정의와 일치하지 않는 URL을 캡처하고 not-found로 리디렉션합니다.

    app.routing.ts
    import { Routes } from '@angular/router';
    
    export const routes: Routes = [
        ...
        { path: 'not-found', loadChildren: './features/not-found/not-found.module#NotFoundModule' },
        { path: '**', redirectTo: 'not-found' },
    ];
    

    Not-Found 구성 요소 만들기


  • 「존재하지 않는 페이지입니다 🤖」적인 메세지가 표시되는 페이지를 이미지 한 컴퍼넌트입니다
  • 간단하게 구현하면 이런 느낌이 될까 생각합니다

  • not-found.component.ts
    import { Component, Inject, OnInit, Optional, PLATFORM_ID } from '@angular/core';
    import { isPlatformServer } from '@angular/common';
    import { RESPONSE } from '@nguniversal/express-engine/tokens';
    import { Response } from 'express';
    
    @Component({
        selector: 'app-not-found',
        templateUrl: './not-found.component.html',
        styleUrls: [ './not-found.component.scss' ],
    })
    export class NotFoundComponent implements OnInit {
        constructor(
            @Optional()
            @Inject(RESPONSE)
            private response: Response,
            @Inject(PLATFORM_ID) private platformId: Object,
        ) {}
    
        public ngOnInit() {
            if (isPlatformServer(this.platformId)) {
                this.response.status(404);
            }
        }
    }
    

    주목해야 할 점은 생성자에서 responseplatformId를받는 부분입니다.
        constructor(
            @Optional()
            @Inject(RESPONSE)
            private response: Response,
            @Inject(PLATFORM_ID) private platformId: Object,
        ) {}
    

    RESPONSE


    response 는 형식을 보면 알 수 있듯이 express에서 사용하는 것과 정확히 동일한 객체입니다.RESPONSEREQUEST@nguniversal/express-engine 가 자동으로 등록해 주므로 어디서나 Inject 할 수 있습니다.
    Optional 데코레이터는 그 이름대로, 있거나 없는 속성에 사용합니다
    이 예에서는 응용 프로그램이 서버 측에서 시작된 경우에만 response가 있으므로 부여했습니다.

    PLATFORM_ID


    platformId는 응용 프로그램의 실행 환경을 결정하는 데 사용되는 값입니다.
    @angular/commonisPlatformServerisPlatformBrowser 를 제공하기 때문에 platformId
            if (isPlatformServer(this.platformId)) {
                this.response.status(404);
            }
    

    이번에는 서버 측에서 실행중인 경우에만 response를 조작하여 상태 코드를 404: Not Found로 변경합니다.

    결과


  • 적절한 URL을 입력해보십시오
  • 무사히 404에서 Not-Found 페이지를 얻을 수있었습니다



  • 요약



    Angular를 Universal화하는 경우 이런 식으로 상태 코드를 조작할 수 있습니다.
    이번 예에서는 404로의 변경뿐이었습니다만, 실제로는 404 이외의 스테이터스 코드를 돌려주거나, 헤더를 조작하거나… 부터 this.responseService.setNotFound() 와 같이 사용하는 것이 좋을까 생각합니다

    Universal 화를 진행하는데 있어서 이 리포지토리 가 대단히 참고가 되고 있습니다
    이번에 소개한 응답을 조작하는 처리도 깨끗하게 정리되어 있으므로, 현재 Universal 챌린지하고 있는 사람은 참고가 될 것 같습니다 ヾ(。>﹏<.)노

    좋은 웹페이지 즐겨찾기