해당 글은 우아한테크코스 5기 프로젝트 "동글"의 번들 사이즈를 최적화하면서 겪은 문제와 그 해결과정을 담은 글입니다.
1. highlight.js란?
프로젝트 동글은 글에 존재하는 코드블럭을 이쁘게 스타일링 해주어야 했다.
highlight.js 라이브러리를 통해 그 목적을 달성할 수 있다.
2. 개선 이유
동글의 production 번들의 패키지를 bundleAnalyzerPlugin로 분석한 결과 highlight.js가 번들 사이즈의 약 25%(286KB/1180KB)를 차지하고 있었다.
동글은 개발자가 타겟 유저층이므로 코드블럭을 꾸미는 것은 필수 기능에 해당한다.
하지만 너무 큰 사이즈로 인해 로딩이 길어져 사용자 경험에 좋지 않다.
3. 문제 상황 인식 및 해결과정
문제 상황
문제는 highlight.js를 사용하는 방식에 있다.
현재 highlight.js의 모든 코드를 한번에 불러오기 때문에,
유저는 gzip 기준 약 286KB에 달하는 리소스를 고스란히 요청하고있다(!)
node_modules에 있는 highlight.js 폴더에 들어가면 그 이유를 알 수 있다.
index.js에서 모든 언어를 등록해서 export 하고 있기 때문이다.
따라서 code spliting을 통해 필요한 언어에 대한 코드(js파일)만 들고오면 될 것이다.
요청하는 글에 있는 코드블럭의 언어만을 들고와야 하는데,
번들 과정에서는 요청하는 글이 어떤 코드블럭 언어를 이용하는지 알 수가 없기 때문에
글을 요청하는 런타임에서 동적 import를 이용해 필요한 언어에 해당하는 코드만 가져와보자.
해결 과정1: highlight.js에 동적 import 도입
highlight.js의 core만 들고온 뒤
필요한 언어만 동적으로 등록해주었다.
하지만 런타임에선 파일을 찾을 수 없다는 에러가 터졌다.
node_modules에 들어가서 highlight.js의 package.json을 까보니 exports에는 딱히 문제가 없는 것 같았다.
그래서 원인 파악을 계속 하다가..
webpack exports의 버그인 것 같았다. (관련 PR)
highlight.js와 webpack 레포지토리 둘 다 관련 이슈들이 많이 올라왔지만, 딱히 해결한 사람은 없었다.
따라서 대체 라이브러리로 `prismjs`를 찾아내었다.
해결 과정2: `prismjs` 도입
npmtrends에서 `prismjs`를 발견했다.
notion이 쓰고있고, 이전에 개발 블로그를 만들었을 때 도입한 기억이 있다.
`prismjs`는 `highlight.js`에 비해 매우 가벼운 번들 사이즈를 자랑한다.
기본적으로 `prismjs`는 필요한 언어의 모듈을 일일히 가져와서 하이라이팅 하도록 설계되었다.
각 언어 모듈은 즉시실행함수로 되어있었고, 동적 import를 통해 모듈을 가져올 수 있다.
해결 과정3: html string 파싱과 동적 import
동글의 글은 서버에서 string형식의 html 코드를 받아와서 바로 렌더링하고 있다.
각 코드 블럭은 `<code className="language-javascript">` 와 같은 형태로 감싸져있기 때문에,
`language-*`에서 *부분을 가져와야했다.
따라서 regex에 맞는 언어들을 뽑아낸 다음 해당 언어에 해당하는 prism 모듈을 동적 import 하였다.
4. 결과
요청 리소스 최적화
highlight.js (변경 전)
prism.js + dynamic import (변경 후)
요청 리소스가 2.0MB -> 1.6MB 로 약 400KB 감소하여 약 20%의 리소스를 절약하였다!
스타일 변경
코드블럭 스타일의 변경도 있다.
참고로 오른쪽 `prismjs`는 노션과 같은 스타일이다.
동글은 노션 연동을 제공하기 때문에, 노션을 익숙한 유저들의 사용자 경험을 그대로 이어준다는 부분에서도 의미가 있다!
5. 최적화 후기
간단할 줄 알았지만,, 생각보다 삽질을 많이했다.
사실 위에서 나열한 해결과정 1, 2, 3은 시간순서가 아니다.
실은 2, 3, 1 순으로 해결했고, highlight.js가 code spliting을 제공하지 않는다고 생각해서 `prismjs`를 바로 도입했었다.
즉 prismjs로 최적화 후 highlight.js를 이용하면서도 동적 import를 도입할 수 있을 것 같아 라이브러리를 까보면서 시도해본 흔적이다🙂
물론 webpack 설정 exports 필드의 버그때문에 목적달성은 못했지만, 단순 docs나 블로그들에 적혀있는 사용방법 외에 주도적으로 라이브러리 이용방법을 구상해봤다는 점에서 한단계 성장했다고 생각한다😎
'우아한테크코스 5기 프론트엔드' 카테고리의 다른 글
낙관적 업데이트를 통해 UX 개선하기 (0) | 2023.11.03 |
---|---|
MSW 잘 사용하기: 유저가 보는 부분에 따라 데이터 쪼개기 (0) | 2023.10.15 |
[프로젝트 동글] 서비스 타겟 환경 및 브라우저 지원 범위 (0) | 2023.08.30 |
[프로젝트 동글] 웹 접근성 관리 대상 선정 및 개선 (0) | 2023.08.29 |
[프로젝트 동글] 근거있는 Typescript 컨벤션 (0) | 2023.08.28 |