网页
综合
更新时间 2026-11-14 16:18:31
Code Splitting | Webpack
自动蜘蛛
webpack.kr
正文约 4021 字
이 가이드는 Getting Started에 제공된 예제를 기준으로 합니다. 해당 예제와 Output Management 챕터를 미리 알아두도록 합니다.
코드 스플리팅은 webpack의 가장 매력적인 기능 중 하나입니다. 이 기능을 사용하여 코드를 다양한 번들로 분할하고, 요청에 따라 로드하거나 병렬로 로드할 수 있습니다. 더 작은 번들을 만들고 리소스 우선순위를 올바르게 제어하기 위해서 사용하며, 잘 활용하면 로드 시간에 큰 영향을 끼칠 수 있습니다.
일반적으로 코드 스플리팅은 세 가지 방식으로 접근할 수 있습니다.
코드를 분할하는 가장 쉽고 직관적인 방법입니다. 그러나 다른 방법에 비해 수동적이며, 같이 살펴볼 몇 가지 함정이 있습니다. 메인 번들에서 다른 모듈을 어떻게 분리하는지 알아보겠습니다.
다음과 같은 빌드 결과가 생성됩니다.
언급했듯이 이 접근 방식에는 몇 가지 함정이 있습니다.
이 중 첫 번째 항목을 통해 지금 예제의 문제를 알 수 있습니다. 왜냐하면 ./src/index.js에서도 lodash를 가져오므로 양쪽 번들에서 중복으로 포함되기 때문입니다. 다음 섹션에서 중복된 것을 제거하겠습니다.
dependOn 옵션을 사용하면 청크간 모듈을 공유할 수 있습니다.
단일 HTML 페이지에서 여러 엔트리 포인트를 사용하는 경우 optimization.runtimeChunk: 'single'도 필요합니다. 그렇지 않으면 여기에서 설명하는 문제가 발생할 수 있습니다.
보시다시피 shared.bundle.js, index.bundle.js 및 another.bundle.js 외에 또 다른 runtime.bundle.js 파일이 생성됩니다.
webpack은 하나의 페이지에 여러 엔트리 포인트를 허용하지만, 가능하다면 entry: { page: ['./analytics', './app'] }처럼 여러 개의 import가 포함된 엔트리 포인트 사용을 피해야 합니다. 이는 async 스크립트 태그를 사용할 때 최적화에 용이하며 일관된 순서로 실행할 수 있도록 합니다.
SplitChunksPlugin을 사용하면 기존 엔트리 청크 또는 완전히 새로운 청크로 공통 의존성을 추출할 수 있습니다. 이를 활용하여 이전 예제의 lodash 중복을 제거해 보겠습니다.
optimization.splitChunks 설정 옵션을 적용하면 index.bundle.js와 another.bundle.js에서 중복 의존성이 제거된 것을 확인 할 수 있습니다. 플러그인은 lodash를 별도의 청크로 분리하고 메인 번들에서도 제거된 것을 알 수 있습니다. 그러나 공통 의존성은 webpack에서 지정한 크기 임계값을 충족하는 경우에만 별도의 청크로 추출된다는 점에 유의해야 합니다.
CSS도 같은 방식으로 분할됩니다. webpack이 청크별 스타일시트를 직접 추출하므로 지연 가져온 CSS 파일은 이를 필요로 하는 청크와 함께 전달됩니다. Native CSS를 참고하세요.
webpack은 동적 코드 스플리팅에 두 가지 유사한 기술을 지원합니다. 첫 번째이자 권장하는 접근 방식은 ECMAScript 제안을 준수하는 import()구문을 사용하는 방식입니다. 기존의 webpack 전용 방식은 require.ensure를 사용하는 것입니다. 이 두 가지 중 첫 번째를 사용해 보겠습니다.
import() 호출은 내부적으로 promises를 사용합니다. 이전 브라우저(예: IE 11)에서 import()를 사용하는 경우 es6-promise나 promise-polyfill과 같은 폴리필을 사용하여 Promise를 지원하도록 해야 합니다.
시작하기 전에 위 예제의 설정에서 추가 entry 및 optimization.splitChunks를 제거하겠습니다. 다음 데모에는 필요하지 않습니다.
또한 현재 사용하지 않는 파일을 프로젝트에서 제거하겠습니다.
이제 정적으로 가져오던 lodash를 동적으로 가져와서 청크를 분리해보겠습니다.
default가 필요한 이유는 webpack 4 이후로 CommonJS 모듈을 가져올 때 더 이상 module.exports 값 으로 해석되지 않으며 대신 CommonJS 모듈에 대한 인공 네임 스페이스 객체를 생성하기 때문입니다. 그 이유에 대한 자세한 내용은 webpack 4: import() 및 CommonJs를 참고하세요.
webpack을 실행하여 lodash가 별도의 번들로 분리되어 있는지 살펴보겠습니다.
또한 import()와 함께 매직 주석 webpackExports를 사용하여 동적으로 가져온 모듈의 특정 내보내기를 노출할 수 있습니다.
이렇게 하면 웹팩이 사용되지 않는 다른 내보내기를 트리 쉐이킹하는 데 도움이 될 수 있습니다. 자세한 내용은 매직 주석을 참고하세요.
import()는 프로미스를 반환하므로 async 함수와 함께 사용할 수 있습니다. 다음은 이를 사용하여 코드를 간소화하는 방법입니다.
나중에 계산된 변수를 기반으로 특정 모듈을 가져와야 할 경우 import()에 dynamic expression을 사용 할 수 있습니다.
동적 import() 또는 코드 분할을 사용할 때, Webpack은 런타임에 청크 로드에 실패하면 ChunkLoadError를 발생시킬 수 있습니다.
이 오류는 일반적으로 요청된 청크가 제대로 실행되거나 해결되지 못했음을 나타냅니다. 경우에 따라 브라우저의 기본 네트워크 오류 또는 스크립트 로딩 오류가 ChunkLoadError 메시지 자체에 완전히 반영되지 않을 수도 있습니다.
더 자세한 내용은 webpack 이슈 트래커의 관련 논의를 참조하세요.
Webpack 4.6.0+에서 프리페치 및 프리로드에 대한 지원이 추가되었습니다.
모듈을 가져올 때 인라인 지시문을 사용하면 webpack이 브라우저에 아래와 같은 "리소스 힌트"를 줄 수 있습니다.
간단한 프리페치의 예제를 들어보겠습니다. HomePage 컴포넌트에서 LoginButton 컴포넌트를 렌더링하고, 이 컴포넌트를 클릭하면 LoginModal 컴포넌트를 요청하여 로드하는 경우입니다.
이는 페이지 head에 <link rel="prefetch" href="login-modal-chunk.js">를 추가하고 브라우저에 login-modal-chunk.js를 유휴 시간에 미리 가져오도록 지시합니다.
webpack은 부모 청크가 로드된 후 프리페치 힌트를 추가합니다.
프리로드 지시문은 프리페치와 비교했을 때 여러 가지 차이점이 있습니다.
간단한 프리로드의 예로는, 별도의 청크에 있어야 하는 큰 라이브러리에 항상 의존하는 Component를 생각해 볼 수 있습니다.
거대한 ChartingLibrary가 필요한 ChartComponent를 상상해 봅시다. 렌더링 될 때 LoadingIndicator를 표시하고 즉시 ChartingLibrary를 요청하여 불러옵니다.
ChartComponent를 사용하는 페이지를 요청할 때 <link rel="preload">를 통해 charting-library-chunk도 요청됩니다. page-chunk가 더 작고 더 빨리 완료된다고 가정하면 이미 요청된 charting-library-chunk가 완료될 때까지 페이지에는 LoadingIndicator가 표시됩니다. 두 번이 아닌 한 번의 라운드 트립이 필요하므로 대기 시간이 긴 환경에서 로드 시간이 증가할 수 있습니다.
webpackPreload를 잘못 사용하면 실제로 성능이 저하 될 수 있으므로 사용 시 주의하세요.
때로는 프리로드에 대한 자신만의 제어가 필요합니다. 예를 들어 모든 동적 import의 프리로드는 비동기 스크립트를 통해 수행할 수 있습니다. 이는 서버사이드 랜더링을 스트리밍할 때 유용합니다.
Webpack이 해당 스크립트의 자체 로드를 시작하기 전에 스크립트 로드가 실패하면(Webpack은 해당 스크립트가 페이지에 없는 경우 해당 코드를 로드하기 위해 스크립트 태그를 생성함), 해당 catch 핸들러는 chunkLoadTimeout에 전달되지 않습니다. 이 동작은 예기치 않은 것일 수 있습니다. 하지만 설명 가능합니다. Webpack은 해당 스크립트가 실패했다는 것을 모르기 때문에 에러를 발생시킬 수 없습니다. Webpack은 에러가 발생한 후 즉시 onerror 핸들러를 스크립트에 추가합니다.
本页为82搜索生成的网页快照,内容来自站内索引;演示数据的原文链接仅作示例。