번들 사이즈 최적화

heyhey·2023년 10월 24일
0

frontend

목록 보기
14/14

번들 사이즈 최적화에 앞서 번들링을 왜 해야할까요?

예전의 단순한 html에서 SPA 로 넘어오면서 파일들이 많아지기 시작했습니다.
-> 파일들을 보내야 하는데 양이 많아서 로딩 속도가 저하되었습니다.
-> 이 파일들을 모아 하나의 파일로 만드는 것이 번들러입니다.

많은 파일을 합쳐줌으로써 초기 로딩 속도가 빨라집니다.
하지만 그 양도 많아진다면 점점 느려질 것입니다.

이것을 두가지 방법으로 해결해보도록 하겠습니다.
1. Code Spliting
2. Tree Shaking


Code Spliting

번들을 거대해지는 것을 방지하기 위한 좋은 방법은 번들을 나누는 것입니다.
큰 코드를 여러개의 청크로 나누겠습니다.

  1. Webpack에서 직접 입력하여 나눌 수 있고
  2. React 코드에서 직접 나누는 방법도 있습니다.

webpack에서는 config 파일에서 entry 포인트에서 나눕니다.

const path = require('path')
module.exports = {
	mode:'development',
	entry:{
		index:'./src/index.js',
		another:'./src/another-module.js'
	}
	...
}

React에서는 lazy() , Suspense 를 사용합니다.

React.lazy 를 사용하면 동적 import 를 사용해 컴포넌트를 렌더링합니다.
lazy 는 동적 import()를 호출하는 함수를 인자로 가집니다.
이 함수는 Promise를 반환하게 됩니다.

lazy 컴포넌트는 Suspense 컴포넌트 하위에서 렌더링되어야 합니다.
Suspense는 lazy 컴포넌트가 로드되길 기다리는 동안 fallback 의 내용을 보여줄 수 있습니다.


const Home = lazy(()=>import('./pages/Home'))
const Good = lazy(()=>import('./pages/Good'))

const App = ()=>{
	return (
		<Suspense fallback={<div>loading...</div>}>
			<Home/>
			<Good/>
		</Suspense>
		
	)
}

이런식으로 lazy 를 이용해 들고오고 Suspense를 감싸서 코드스플리팅을 사용합니다. 여러개도 사용 가능합니다.

번들링 결과 입니다. 처음은 파일이 하나였는데, 우측과 같이 lazy로 감싼 컴포넌트들이 여러개의 파일로 번들이 쪼개지게 되었습니다.

이렇게 여러개의 청크 파일이 생기게 되었는데, 그 파일에서 사용하는 함수는 중복이 있을 수 있습니다.

이 함수를 중복해서 사용하게 되면 두번의 함수를 만들게 됩니다.

이건 webpack의 splitChunks 설정으로 처리가 가능합니다.

optimization :{
	splitChunks:{
		chunks:'all',
		minSize : 100 // 기존 20000 => 사이즈가 20000이 넘겨야 실행
		...
	}
}

이렇게 하면 중복 함수는 split 되게 됩니다.


Tree Shaking

Webpack에서는 ESM으로 구성되어 있다면 자동으로 합니다.

사이드 이펙트가 있다고 판단하는 경우는 진행하지 않는데,
package.json 파일을 수정해서 설정이 가능합니다.

사이드 이펙트가 특정 경로에서 있을 경우는 특정 파일을 지정해줍니다.

{
	"name": "hi",
	"sideEffects":[
		"./src/a.js",
		"*.css*"
	] 
}

사이드 이펙트가 없는경우는 false 로 두면 됩니다.

{
	"name": "hi",
	"sideEffects":false
}

이렇게 했는데도 트리쉐이킹이 되지 않을 때가 있습니다.
a, b, c 함수를 index.js 파일에서 생성하고 다른 파일에서 a만 import 했지만 b,c 또한 생성되어 있을 수 있다 이럴때는 re-export를 사용합니다.

re-export란, 함수를 한 파일에서 불러와서 export 하는 방식입니다.

a 를 a.js 에서 , b를 b.js 에서 , c를 c.js 에서 만들어 준뒤
index.js 에서 export 한다.

export {a} from './a.js'
export {b} from './b.js'
export {c} from './c.js'

이렇게 하면 a 함수만 사용할때 번들링하면 a만 생성되게 됩니다.

참고 :
https://www.youtube.com/watch?v=ut10rvh1vug&t=302s
https://ko.legacy.reactjs.org/docs/code-splitting.html#avoiding-fallbacks

profile
주경야독

0개의 댓글