2024.03.22 갑자기 vercel 배포가 오류가 발생하였다.
공식문서를 열쉼히 찾아본다.
요약하자면 다음과 같다.
package.json
내부 packageManager
프로퍼티가 생김. 그 프로퍼티를 vercel이 오늘부로 참조하기로 정함.해결 방법은 3가지로보임
1.배포처를 옮긴다.(아마존으로 곧 이사갈 예정)
2.pacakageManager를 임시로 지우고 올린다 (제일 간단하지만, 로컬에서 사용할땐 다시 적어주어야 한다.)
3. vercel 빌드 도중 packageManager를 참조하지 못하게 하는 명령어 or 설정을 찾는다(찾아봤는데 잘 안나온다.)
따라서 하드한 방법인 2번을 택하여 임시로 배포성공하게 만들었음.
다음주 내로 AWS로 이사가야겠다!
코드 스플리팅이란? 뜻 그대로 파일을 분리하는 작업(런타임시 필요한 모듈 불러오게 하는 것) 이다. 왜 필요할까?
SPA방식 사이트는 하나의 JS파일로 번들링된다. 따라서 당장 유저가 사용하지 않는 내용마저 합쳐져서 불러오기때문에, js파일의 용량이 커져 초기로딩속도가 느려진다.
우리 프로젝트의 초기 로딩속도는 lighthouse기준 fcp점수가 90점대였지만, Vercel에서 빌드할때 한 청크가 500kb
를 넘는다며 워닝메시지를 띄웠다. 심각한 수준은 아니지만 어쨌든 경고메시지니 한번 따라가며 청크사이즈를 줄여보자.
방법은 여러가지가 있다. 대표적인 코드 스플리팅 방법을 소개해보겠다.
비동기적으로 컴포넌트를 불러올 수 있다. 필요한(렌더링) 시점에 컴포넌트를 불러온다.
그리고 Suspense도 같이 적용하면 좋다. 결국 비동기 렌더링이기 때문에 네트워크 상태가 좋지 않거나 파일이 큰 경우 빈 컴포넌트를 보게된다.
const OtherComponent = React.lazy(() => import('./OtherComponent'));
...
<Suspense fallback={<Spinner/>}>
<OtherComponent/>
</Suspense>
React.lazy 적용 전
React.lazy 적용 후
청크가 쪼개지며 한 청크당 사이즈가 2045
에서 최대 869
로 50%이상 줄어들었다. 아직 개당 500kb는 넘지만, GameCode
내부 모듈들은 라우팅시 한번에 받아야 하기에 더 줄일수는 없어보인다.
...과연 그럴까!?
Vendor는 청크간 공통적으로 사용하는 모듈을 모아둔 것이다
rollup에서 지원하는 manualChunks도 마찬가지로 청크 간 공통적으로 사용하는 모듈을 청크로 뽑아내준다.
이 기능을 vite에서 플러그인으로 지원해주니 사용해보자
splitVendorChunkPlugin 적용 전
vendor라는 청크는 없다.
splitVendorChunkPlugin 적용 후
index에서 vendor로 청크를 분리하였다.
음...내가 원하는 GamePage와 GameCode의 청크사이즈를 줄이진 못했다. 그래도 일단 청크를 분리하였으니, 만족.
다음은 직접 코드 내에서 줄여보자!
런타임시 실제로 필요할때만 모듈을 불러온다. 마치 React.lazy
와 비슷하다!
dynamic import또한 Promise를 반환하기에 then, await
을 사용하여 내부 데이터를 꺼내 사용해야함.
//await
const module = await import(...);
//then
import(...).then(...)
어떤 장/단점이있을까? 생각만 해보자면 다음과 같다.
즉 초기 로딩속도와 사용됐을 시점의 로딩 속도를 트레이드 오프한다.
사용할때 즉각적으로 반응해야한다면, dynamic import를 피해야하지 않을까?
위와 같은 관점에서 어떤 모듈을 동적 import할지 정해보자.
참고로 Vite에서도 dynamic import를 지원해준다!
...생각해봐도 dynamic import가 필요한 부분이 보이지 않는다. 실시간 통신이 중점이고 인게임 컴포넌트라 무조건 사용자에게 노출되어야한다. 이 컴포넌트 자체는 이미 React.lazy
로 동적 렌더링 되어있어서...좀 더 고민해봐야할 것 같다.
정말로 비슷할까?
그렇다ㅎㅎ
lighthouse 점수는 어떻게 변화했을까?
한번 비교해보자!
각 측정항목의 색이 주황색이다. 나쁜 쪽은 아니지만, 엄청 좋다고 볼 순 없다.
특히 LCP가 오래걸린다.
이 노드는 SSE에서 데이터를 받아 그려준다.
데이터를 받기전에, DOM도 파싱하고...읽고...하는 작업을 하다가 늦어진게 아닐까?
작은 이미지인데 실제 크기는 어마어마하다. 이런 이미지 또한 용량을 절감할 수 있다.
점수가 녹색으로 변했다! 접근성과 검색엔진 최적화는 아직 그대로다.
LCP가 많이 줄었다. 청크를 나누고 dynamic import(React.lazy)로 아직 필요없는 컴포넌트를 늦게 렌더링 한게 도움 됐나보다.
실제로 2000ms에서 460ms로 줄었다. 생각보다 더 줄었구만!
시멘틱을 잘 지키려고 노력했지만, 이런 부분들이 부족했다.
검색엔진 최적화는 이렇다. 특히 robots.txt가 유효하지 않다. 당연하다. 아직 추가하지 않았음..ㅎㅎ
위 사항들은 따로 공부하여 수정사항에 반영해보겠다.
번들링 최적화는 lighthouse 점수향상에 도움이 된다.
실제 첫 페이지 로딩속도가 빨라진건 기분탓이겠지?ㅎㅎ
그리고 속도뿐만이 아니라접근성과 검색엔진 최적화도 중요하다는 걸 알았다.
청크 사이즈가 너무 크면 안된다는 것도 알았지만, 필요 이상으로 청크를 잘개 쪼개도 안된다는 걸 알았다.
또한 Suspense
가 React.lazy
와 함께 쓰일 수 있다는 것 도 알았다. 결국 비동기가 처리되는동안 보여지는 선언적 컴포넌트일 뿐이다!