1. 무엇이 문제인가?
Next.js로 빌드한 스태틱(Static)을 S3에 서빙하면 생기는 문제 중 하나는 브라우저에서 요청한 주소와 실제 리소스의 주소(URI)가 다르다는 것입니다.
예를들어,
/pages/index.tsx
/pages/foo/bar.tsx
를 Next.js(디렉토리 기반 라우팅)에서 빌드를 한 경우
dist/index.html
dist/foo/bar.html
로 스태틱이 생성이 될겁니다. 이 스태틱을 그대로 배포하면www.AAAAA.com
은 문제가 없지만www.AAAAA.com/foo/bar
혹은 www.AAAAA.com/foo/bar/
로 접근을 한다면 www.AAAAA.com/foo/bar/index.html
을 조회 하게 되면서 원하는 리소스를 응답 받을 수 없습니다.클라이언트 사이드 라우팅은 문제가 없습니다. 주소창에 직접 주소를 치고 들어가거나 새로고침을 했을때 처럼 새로운 문서를 요청 할 때 문제가 발생합니다.
2. 해결방법은?
1) trailingslash
사실 Next.js 에서는
trailingSlash
라는 옵션을 제공합니다.// next.config.js module.exports = { ... trailingSlash: true, };
next export
를 하여 스태틱을 생성한다면 trailingSlash
가true
면/pages/foo/bar.tsx
=>/dist/foo/bar/index.html
false
면/pages/foo/bar.tsx
=>/dist/foo/bar.html
로 빌드가 됩니다.
그렇게 되면 배포를 하더라도
www.AAAAA.com/foo/bar/
로 접근이 가능하겠죠.2) cloudfront function (or lambda)
근데 저는 뒤에
/
가 붙는게 마음에 들지 않았습니다.www.AAAAA.com/foo
www.AAAAA.com/foo/bar
이런식으로 접근하고 주소창의 URL도 /
가 없었으면 좋겠습니다.따라서 cloudfron function을 아래와 같이 작성해 주었습니다. (es5딥빡..)
var config = { suffix: '.html', appendToDirs: 'index.html', removeTrailingSlash: true, }; var regexSuffixless = /\\/[^/.]+$/; var regexTrailingSlash = /.+\\/$/; function handler(event) { var request = event.request; var uri = request.uri; var suffix = config.suffix; var appendToDirs = config.appendToDirs; var removeTrailingSlash = config.removeTrailingSlash; // Redirect (301) non-root requests ending in "/" to URI without trailing slash // /foo/bar/ => /foo/bar (res) if (removeTrailingSlash && uri.match(regexTrailingSlash)) { var response = { statusCode: 301, statusDescription: 'Moved Permanently', headers: { location: { value: uri.slice(0, -1) }, }, }; return response; } // Append ".html" to origin request if (suffix && uri.match(regexSuffixless)) { request.uri = uri + suffix; return request; } // If nothing matches, return request unchanged return request; }
AAA.com/foo/
=>AAA.com/foo
로 리다이렉트
AAA.com/foo
=>AAA.com/foo.html
리퀘스트 리턴
필요에 따라
.html
패턴도 리다이렉트 시켜도 괜찮을것 같습니다.사실 중요한건 통일 같습니다..!