일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 쓰레드
- Cache
- react server component
- 개발자
- 리액트
- amplify
- 리액트쿼리
- next hydration
- CSS-in-JS
- Babel
- 기초
- Critical Rendering Path
- link
- mockoon
- 목킹
- JavaScript
- thread
- next.js
- Concurrent Mode
- 컴포넌트
- 아키텍처
- 리액트네이티브
- 최적화
- sprinkles
- vanilla-extract
- mock service worker
- Basic
- styled-component
- MSW
- SWC
- react-query
- front-end mocking
- 비동기
- 기본
- async
- React
- 자바스크립트
- 캐쉬
- react-native
- 동기
- Today
- Total
Don’t worry about failures
웹펙 - 번들사이즈 줄이기 본문
웹펙의 옵션들을 통해 번들 사이즈를 최적화를 하고자한다.
1. Webpack mode
1-1 none
- 모드를 설정하지 않은 경우에는 웹팩의 기본 동작에 따라 동작.
- 개발 모드나 프로덕션 모드와는 달리 추가적인 최적화나 디버깅 정보를 포함하지 않는다.
1-2. Development
개발에 초점이 맞춰져 있다.
- 코드 최적화 작업이 이루어지지 않음. 디버깅에 도움되는 추가 정보를 번들에 포함.
- 소스맵을 생성하여 원본 코드와 번들된 코드 간의 매핑을 제공하여 디버깅에 용이함.
- 빠른 빌드 시간을 위해 코드 최적화를 최소화하고, 개발자 경험을 향상시키기 위해 빌드된 번들에 추가 정보 포함.
1-3 Production
- 코드를 최적화하고 번들 파일 크기를 최소화하여 빠른 성능을 제공한다.
- 불필요한 주석이나 공백 등의 코드를 제거, 코드 난독화 수행한다.
- 소스맵 제거하여 빌드된 번들 크기의 최소화한다.
위의 옵션을 기준으로 웹펙으로 빌드를 해보자.
1. none
2. development
3.production
3개의 모드에 대해 살펴본 결과를 살펴보면,
확연하게 production환경에서 사이즈가 줄어든 것을 확인할 수 있다. 6키로바이트에서 728바이트 단위까지 많이 줄어든다.
내부 코드를 확인했을 때도, 주석 등 제거되는 것도 확인이 되었다.
none과 development를 비교해봤을 때는 사이즈 측면에서 봤을 때는 오히려 development가 더 크다. 그 이유는 디버깅을 위해 소스맵에 따라 원본 파일이 존재했기 때문이다.
2. 소스맵
위에서 잠깐 나온 소스맵은 웹펙, 바벨 등에 의해서 생성이 될 수 있다. 이는 압축된 형태로 배포된 javascript 파일과 개발 중에 작성한 원본 소스 코드 간의 매핑 정보를 제공하는 파일. 매핑 정보를 통해 개발자는 압축되거나 변환된 코드를 디버깅할 때 원본 소스를 찾아볼 수 있다.
- 디버깅 용이. 디버깅 시 원본 코드의 라인 및 열 정보를 제공.
- 성능 최적화. 프로덕션 환경에서는 보통 소스맵을 제거하여 번들 크기를 줄이고, 어플리케이션의 성능을 향상.
- 소스맵은 주로 빌드 도구(웹펙)에서 생성되며, 빌드 구성 옵션에서 활성화. 이렇게 생성된 소스맵은 브라우저의 개발자 도구에서 로드되어 디버깅 시 사용.
- 소스맵은 Typescript, babel과 같은 트랜스 파일러에서도 생성될 수 있음.
devtool을 통해 sourceMap 설정을 할 수 있다.
- none: 소스맵을 생성하지 않는다. 디버깅을 위한 소스맵이 필요하지 않은 경우에 사용. 소스맵을 생성하지 않으므로 빌드된 파일의 크기가 가장 작다.
- eval: 각 모듈을 eval 함수로 감싸고 해당 모듈의 소스맵 정보를 데이터 URL로 포함합니다. 빌드 시간이 빠르지만, 디버깅 품질은 낮을 수 있다.
- cheap-eval-source-map: 번들된 코드를 eval 함수로 감싸고, 컬럼 번호(column number) 없이 번들된 코드와 소스 파일을 매핑합니다. 번들 크기는 빠르고 디버깅은 상대적으로 빠르다.
- cheap-source-map: 소스맵에서 컬럼(column) 정보를 생략하여 번들된 코드와 소스 파일을 매핑한다. 번들 크기는 더 크지만, 디버깅 품질이 좋다.
- eval-source-map: 각 모듈을 eval 함수로 감싸고 소스맵을 별도의 파일로 생성한다. 디버깅 품질이 높으나 빌드 시간이 조금 더 걸릴 수 있다.
- cheap-module-eval-source-map: cheap-eval-source-map과 유사하지만, 모듈 간에 원시 소스 파일의 경로를 제공한다.
- cheap-module-source-map: cheap-source-map과 유사하지만, 모듈 간에 원시 소스 파일의 경로를 제공한다.
- source-map: 소스맵을 별도의 파일로 생성하고 모든 소스 코드와 소스맵 정보를 포함. 가장 높은 품질의 디버깅을 제공하지만, 빌드 시간과 번들 크기가 늘어난다.
devtool의 기본값은 mode에 따라 다르다.
development => devtool : eval
production => devtool : none
2. Code Splitting
애플리케이션의 코드를 여러 개의 작은 청크로 나누어 빌드하는 기술. 코드 분할을 사용하면 어플리케이션을 효율적으로 로드할 수 있으며, 초기 로드 시간을 줄이고 페이지 성능을 개선할 수 있다.
주요 분할 방법 및 사용
1. 동적 코드 분할
어플리케이션의 특정 부분이나 요청에 따라 코드를 동적으로 로드하는 기술.
방법1. import()함수 사용. 동적 코드분할 가장 일반적인 방법. 이 함수는 Promise를 반환.
import('./module').then(module => {
//load된 모듈 사용
});
방법2. 웹펙 설정에서 설정.
module.exports = {
// ...
optimization: {
splitChunks: {
chunks: 'all', // 모든 종류의 청크에 대해 공통 모듈을 추출
},
},
};
2. Entry Points로 코드 분할
어플리케이션의 여러 진입점(entry point)을 정의하여 각 진입점에 해당하는 코드를 분리하는 기술.
2-1. 웹펙 설정에서 Entry Points 정의.
module.exports = {
entry: {
main: './src/index.js',
admin: './src/admin.js',
},
// ...
};
웹팩은 위에서 정의된 진입점에 따라 각각의 번들을 생성한다.
dist/
├── main.bundle.js
└── admin.bundle.js
2-2 적절한 곳에서 동적으로 로드.
각각의 진입점에 해당하는 번들을 적절한 곳에서 동적으로 로드.
import('./admin.bundle.js').then(admin => {
// 'admin' 번들을 로드하고 로드된 모듈을 사용합니다.
});
3. SplitChunks 플러그인
중복된 코드를 감지하고 공통 모듈을 별도의 청크로 분리하여 번들을 최적화하는 기능을 제공한다.이를 통해 불필요한 코드의 중복을 줄이고 애플리케이션의 초기 로드 시간을 최소화 할 수 있다.
주요 특징
1. 공통 모듈 추출 : SplitChunks 플러그인은 번들링된 여러 모듈 중에서 공통된 부분을 식별하고 이를 별도의 청크로 분리. 이를 통해 공통 모듈을 한 번만 로드하여 캐싱하고 다른 페이지에서 재사용할 수 있음.
2. 웹팩 설정에서 사용 : SplitChunks 플러그인은 웹팩 설정 파일에서 사용. optimization.splitChunks 옵션을 통해 SplitChunks 플러그인을 활성화하고 최적화 옵션을 설정할 수 있음.
3. 다양한 설정
module.exports = {
// ...
optimization: {
splitChunks: {
chunks: 'all',
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
},
},
};