Next.js에서 SSG 한 정적 사이트를 (CSR 후 리로드시 404 문제를 최소 비용으로 해결하면서) S3에서 호스팅

7053 단어 SSGS3next.js

개요



Next.js에서 SSG 한 정적 사이트를 S3에 배포하는 경우 기본적으로 next export 결과를 버킷에 넣으면 좋지만 아무 것도 고려하지 않고 그냥 그렇다면 CSR 한 페이지에서 다시로드했습니다. 때 404입니다.

다른 AWS 서비스의 도입은 관리 비용 증가의 관점에서 피하고 싶습니다.여기서는 S3와 쉘 스크립트만으로 어떻게 든 방법을 공유합니다.
(그러나 쉘 스크립트는 aws 명령에 의존합니다)

S3 배포 시 발생하는 문제



(실제로는 S3 이외의 호스팅 서비스에서도 일어나지만)
next export.html의 확장자로 페이지를 내보내는 경우 (pages/hoge.tsx이면 out/hoge.html와 같이), 아무 것도 고려하지 않으면 URL이 https://hoge.com/hoge.html처럼 .html 붙어 버립니다.

이것이 문제인가 하면 해당 페이지에 Next CSR을 하면 URL은 https://hoge.com/hoge (.html 없음)이 되므로 이 상태에서 다시 로드하면 404가 되어 버립니다.

탈선이지만



Amplify로 배포하면 이 문제가 발생하지 않습니다.
Amplify를 사용하는 것에 우려가 없다면 추천합니다.

Next.js에서 SSG 한 사이트를 Amplify에서 호스팅 - Qiita

대책


  • next export로 할 수있는 .html 파일에서 확장자를 제거하십시오.
  • S3에 배치 한 후 확장자를 제거한 HTML 파일에 content-type: "text/html"를 부여합니다.

  • 이것들을 손으로 하고 싶지 않기 때문에 쉘 스크립트를 작성합니다.

    1. next export에서 할 수 있는 HTML 파일에서 확장자를 제거한다.



    원래 CSR이 .html를 붙이지 않는다면, 파일명으로부터 .html를 깎으면 좋지요.
    하지만, index.html에 관해서는 어느 쪽이든 URL에 포함되지 않거나, 깎지 않아도 되는가. 그래서
    next export
    
    html_filepaths=$(find ./out -name "*.html" ! -path "*/index.html")
    for filepath in $html_filepaths; do
      mv $filepath ${filepath%\.html}
    done
    

    이런 식으로 index.html 이외의 xxx.html 파일에서 확장명을 지 웁니다.
    (next export의 출력 대상이 out/인 경우)

    2. S3에 배치한 후 확장자를 제거한 HTML 파일에 content-type: "text/html"을 부여한다.



    그러나 .html를 깎은 파일에는 Content-Type 헤더가 없습니다.
    그러면 브라우저에서 거기에 액세스했을 때 HTML로 인식되지 않고 브라우저 다운로드가 실행됩니다.

    그래서 위에서 확장자를 깎은 HTML 파일(S3의 오브젝트) 모두에, Content-Type: "text/html"를 붙입니다.
    # 拡張子を削ったファイルのファイル名を回して、S3上のオブジェクトに対してContent-Typeを付与する
    for filepath in $html_filepaths; do
      path=${filepath#\.\/out\/}
      key=${path%\.html}
    
      aws s3api copy-object \
        --bucket $bucket_name \
        --copy-source $bucket_name/$key \
        --key $key \
        --metadata-directive "REPLACE" \
        --content-type "text/html"
    done
    

    여기서 aws 명령을 사용하고 있으므로 없으면 설치해야합니다.

    CSR 후 리로드시 404 문제에 대해서는 이것으로 해결입니다.

    배포 스크립트



    위의 대책 포함 배포 스크립트는 이런 느낌입니다.
    실제로는 환경의 배분이라든지 그 외 세세한 처리가 더 있습니다만 그 근처는 여기에서는 생략하고 있습니다.
    # next exportの実行
    npm run export
    
    # 趣旨と関係ないけど、これら消さずにS3に上げるとブラウザからダウンロードできちゃうので消す
    find ./out -name ".DS_Store" | xargs rm
    find ./out -name ".keep" | xargs rm
    
    # .html なファイルから拡張子を取り除く
    html_filepaths=$(find ./out -name "*.html" ! -path "*/index.html")
    for filepath in $html_filepaths; do
      mv $filepath ${filepath%\.html}
    done
    
    # S3にsync(アップロード)
    $bucket_name=hoge_bucket
    aws s3 sync ./out/ s3://$bucket_name/ --delete
    
    # Content-Type付与する
    for filepath in $html_filepaths; do
      path=${filepath#\.\/out\/}
      key=${path%\.html}
    
      aws s3api copy-object \
        --bucket $bucket_name \
        --copy-source $bucket_name/$key \
        --key $key \
        --metadata-directive "REPLACE" \
        --content-type "text/html"
    done
    

    오시마



    페이지가 몇 계층이 있는 사이트에서 시도하지 않으므로, 안 된다면 좋은 느낌으로 고쳐 주세요🚀

    추가



    계속해서 이쪽의 말미 슬래시 404 문제에의 대응이 있습니다.

    Next.js의 SSG 사이트를 S3에 정적 호스팅 할 때 발생하는 후행 슬래시 404 문제를 저렴한 비용으로 해결했습니다.

    좋은 웹페이지 즐겨찾기