코드 분할 자바스크립트

대규모 JavaScript 리소스를 로드하면 페이지 속도에 큰 영향을 미칩니다. 분할 JavaScript를 더 작은 청크로 나누고 시작 시 페이지가 작동하도록 하면 페이지의 로드를 크게 개선할 수 있습니다. 응답성, 이를 통해 페이지의 다음 페이지 상호작용을 개선할 수 있습니다. 페인트 (INP).

페이지에서 대용량 JavaScript 파일을 다운로드, 파싱 및 컴파일할 때 지속적으로 반응하지 않습니다. 페이지 요소는 페이지의 초기 HTML에 생성되며 CSS에 의해 스타일이 지정됩니다. 하지만 JavaScript가 는 물론 대화식 요소에 의해 로드되는 기타 스크립트를 지원하는 데 필요한 JavaScript를 파싱하고 실행하여 제대로 작동할 수 있습니다. 이 결과적으로 사용자는 상호 작용이 상당히 이뤄졌다고 느낀다는 것을 배송이 지연되거나 심지어 전혀 작동하지 않을 수도 있습니다.

이 문제는 주로 JavaScript가 파싱되어 기본 스레드가 차단되어 발생합니다. 기본 스레드에서 컴파일됩니다. 이 프로세스가 너무 오래 걸리면 페이지 요소가 사용자 입력에 충분히 빠르게 반응하지 않을 수 있습니다. 이 문제를 해결하는 한 가지 방법은 페이지가 작동하는 데 필요한 JavaScript만 로드하는 것이고 코드라는 기술을 통해 나중에 로드하도록 다른 JavaScript 지연 있습니다. 이 모듈에서는 이 두 가지 기법 중 후자에 중점을 둡니다.

코드 분할을 통해 시작 시 JavaScript 파싱 및 실행을 줄입니다.

Lighthouse에서 JavaScript 실행 시간이 2보다 오래 걸리면 경고를 표시함 3.5초 넘게 걸리면 실패합니다. 과도한 자바스크립트 페이지의 어느 지점에서든 파싱 및 실행이 발생할 수 있는 잠재적인 문제임 상호작용의 입력 지연을 늘릴 수 있기 때문에 사용자가 페이지와 상호작용하는 시간이 사용자가 광고를 클릭한 순간과 일치하는 경우 JavaScript 처리 및 실행을 담당하는 기본 스레드 작업은 있습니다

그뿐만 아니라 과도한 JavaScript 실행과 파싱은 특히 이 지점이 초기 페이지 로드 중 문제가 될 수 있습니다. 사용자가 페이지와 상호작용할 가능성이 높은 수명 주기를 의미합니다 실제로 로드 반응성 측정항목인 총 차단 시간 (TBT)관련성이 높음 INP와 비교했을 때 이는 사용자가 상호작용을 시도하는 경향이 높음을 시사합니다. 자동으로 렌더링됩니다.

각 JavaScript 파일을 실행하는 데 걸린 시간을 보고하는 Lighthouse 감사 어떤 요청을 보낼 수 있는지 정확하게 파악할 수 있다는 점에서 스크립트는 코드 분할 후보가 될 수 있습니다. 그런 다음 Chrome DevTools의 범위 도구를 사용하여 애플리케이션의 어떤 부분을 페이지가 로드되는 동안 사용되지 않을 수 있습니다.

코드 분할은 페이지의 초기 자바스크립트를 지원합니다 이를 통해 JavaScript 번들을 다음 두 부분으로 분할할 수 있습니다.

  • 페이지 로드 시 JavaScript가 필요하므로 다른 위치에서 로드할 수 없음 있습니다.
  • 나중에 로드할 수 있는 나머지 JavaScript(대부분의 경우) 사용자가 특정 상호작용 요소와 상호작용하는 지점 있습니다.

코드 분할은 동적 import() 구문을 사용하여 수행할 수 있습니다. 이 문법: 지정된 JavaScript 리소스를 요청하는 <script> 요소와는 다름 시작 중 - 시작 작업 중에 나중에 JavaScript 리소스를 애플리케이션입니다.

<ph type="x-smartling-placeholder">
document.querySelectorAll('#myForm input').addEventListener('blur', async () => {
  // Get the form validation named export from the module through destructuring:
  const { validateForm } = await import('/validate-form.mjs');

  // Validate the form:
  validateForm();
}, { once: true });

앞의 JavaScript 스니펫에서 validate-form.mjs 모듈은 다음과 같습니다. 사용자가 양식의 특정 부분을 흐리게 처리하는 경우에만 다운로드, 파싱, 실행 <input> 필드입니다. 이 경우 양식의 유효성 검사 로직을 구동하는 것은 사용될 가능성이 가장 높습니다.

webpack, Parcel, Rollup, esbuild와 같은 JavaScript 번들러는 자바스크립트 번들을 더 작은 청크로 분할하도록 소스 코드에서 동적 import() 호출이 발생할 수 있습니다. 이러한 도구의 대부분은 자동으로 적용되지만 특히 esbuild의 경우 이 옵션을 사용하도록 선택해야 합니다. 있습니다.

<ph type="x-smartling-placeholder">

코드 분할 관련 유용한 참고 사항

코드 분할은 기본 스레드 경합을 줄이는 효과적인 방법이지만 페이지 로드를 늘리기 위해 페이지를 로드하기로 결정한 경우 자바스크립트 소스 코드를 감사하여 코드 분할 기회를 찾아보세요.

가능한 경우 번들러 사용

개발자들은 일반적으로 JavaScript 모듈을 개발 프로세스입니다. 이 것은 뛰어난 개발자 환경 개선으로 코드 가독성과 유지관리성을 개선합니다. 하지만 몇 가지 JavaScript를 제공할 때 발생할 수 있는 최적화되지 않은 성능 특성 배포할 수 있습니다

가장 중요한 점은 번들러를 사용하여 소스를 처리하고 최적화해야 한다는 것입니다. 여기에는 코드를 분할하려는 모듈이 포함됩니다. Bundler는 JavaScript 소스 코드에 최적화를 적용하는 것뿐만 아니라 번들 크기와 같은 성능 고려사항의 균형을 맞추는 데 매우 효과적입니다. 압축률과 비교합니다. 압축 효과는 번들 크기에 따라 증가합니다. 하지만 번들러는 번들이 너무 크지 않은지 확인하여 스크립트 평가로 인해 시간이 매우 오래 걸릴 수 있습니다.

또한 번들러는 번들로 묶이지 않은 여러 모듈을 배송해야 하는 문제를 방지합니다. 데이터를 전송할 수 있습니다. JavaScript 모듈을 사용하는 아키텍처는 사용할 수 있습니다 모듈 트리가 번들로 묶이지 않으면 각 모듈은 별도의 HTTP 요청이 필요하며, 웹 앱에서의 상호작용이 지연될 경우 모듈을 번들화하지 않습니다 Cloud Shell에서 큰 모듈 트리를 조기에 로드하기 위한 <link rel="modulepreload"> 리소스 힌트 자바스크립트 번들이 로드 성능보다는 선호됨 할 수 있습니다.

실수로 스트리밍 컴파일을 사용 중지하지 마세요.

Chromium의 V8 JavaScript 엔진은 즉시 사용 가능한 다양한 최적화를 제공합니다. 프로덕션 JavaScript 코드가 최대한 효율적으로 로드되도록 하는 것이 중요합니다. 이러한 최적화 중 하나를 스트리밍 컴파일이라고 하며 다음과 같이 스트리밍 컴파일합니다. 브라우저에 스트리밍된 HTML의 증분 파싱을 통해 스트리밍된 청크를 컴파일합니다. 도착할 때 자바스크립트에 전달됩니다.

스트리밍 컴파일이 실행되는지 확인하는 몇 가지 방법이 있습니다. 웹 애플리케이션:

  • JavaScript 모듈을 사용하지 않도록 프로덕션 코드를 변환합니다. 번들러 컴파일 타겟을 기반으로 JavaScript 소스 코드를 변환할 수 있습니다. 표적은 종종 특정 환경에 국한됩니다. V8이 스트리밍을 적용합니다. 모듈을 사용하지 않는 JavaScript 코드로 컴파일할 수 있으며, JavaScript 모듈 코드를 구문으로 변환하도록 번들러 구성 사용하지 않는 자바스크립트 모듈입니다.
  • JavaScript 모듈을 프로덕션에 제공하려면 .mjs 확장 프로그램 프로덕션 JavaScript에서 모듈을 사용하든 사용하지 않든 모듈과 JavaScript를 사용하는 JavaScript를 위한 특별한 콘텐츠 유형이 없음 그렇지 않습니다. V8의 경우 스트리밍을 효과적으로 선택 해제할 수 있습니다. .js를 사용하여 프로덕션에 JavaScript 모듈을 출시할 때 컴파일을 실행합니다. 확장자가 포함됩니다. JavaScript 모듈에 .mjs 확장 프로그램을 사용하는 경우 V8은 모듈 기반 JavaScript 코드에 대한 스트리밍 컴파일이 깨진 것 같습니다.

이러한 고려로 인해 코드 분할 사용을 망설이지 마세요. 코드 분할은 사용자의 초기 JavaScript 페이로드를 줄이는 효과적인 방법이지만, 하지만 번들러를 사용하고 V8의 스트리밍을 보존할 수 있는 방법을 아는 것은 코드가 올바르게 컴파일되도록 하려면 프로덕션 JavaScript 코드가 빠른 속도를 낼 수 있습니다.

동적 가져오기 데모

webpack

webpackSplitChunksPlugin라는 플러그인과 함께 제공됩니다. 이 플러그인을 사용하면 번들러가 JavaScript 파일을 분할하는 방법을 구성합니다. webpack은 동적 import() 및 정적 import 문을 사용합니다. 동작 SplitChunksPluginchunks 옵션을 지정하여 수정할 수 있습니다. 구성:

  • chunks: async는 기본값이며 동적 import() 호출을 나타냅니다.
  • chunks: initial는 정적 import 호출을 나타냅니다.
  • chunks: all는 동적 import() 및 정적 가져오기를 모두 처리하므로 asyncinitial 가져오기 간에 청크를 공유합니다.

기본적으로 webpack에서 동적 import() 문을 만날 때마다 이 항목 해당 모듈을 위한 별도의 청크를 만듭니다.

/* main.js */

// An application-specific chunk required during the initial page load:
import myFunction from './my-function.js';

myFunction('Hello world!');

// If a specific condition is met, a separate chunk is downloaded on demand,
// rather than being bundled with the initial chunk:
if (condition) {
  // Assumes top-level await is available. More info:
  // https://v8.dev/features/top-level-await
  await import('/form-validation.js');
}

위 코드 스니펫의 기본 webpack 구성으로 두 개의 여러 개의 개별 청크로 분할합니다.

  • webpack이 initial 청크로 분류되는 main.js 청크는 main.js./my-function.js 모듈을 포함합니다.
  • form-validation.js만 포함된 async 청크( 파일 해시(구성된 경우) 이 청크는 conditiontrue인 경우와

이 구성을 사용하면 다음 시점까지 form-validation.js 청크 로드를 연기할 수 있습니다. 실제로 필요합니다 이렇게 하면 스크립트를 줄임으로써 로드 응답성을 개선할 수 평가 시간을 측정합니다. 스크립트 다운로드 및 평가 form-validation.js 청크는 동적으로 가져온 모듈이 다운로드됩니다. 한 가지 예는 또는 가져온 모듈이 사용자 상호작용에 필요합니다.

반면에 SplitChunksPlugin 구성을 변경하여 chunks: initial는 코드가 초기 청크에서만 분할되도록 합니다. 이는 정적으로 가져오거나 webpack의 entry에 나열된 것과 같은 청크 속성을 사용합니다. 앞의 예를 보면 결과 청크는 단일 스크립트 파일에서 form-validation.js main.js 조합 초기 페이지 로드 성능이 저하될 수 있습니다.

SplitChunksPlugin의 옵션을 구성하여 더 큰 광고 단위를 분리할 수도 있습니다. 여러 개의 작은 스크립트로 분할(예: maxSize 옵션 사용) 청크가 청크를 초과하는 경우 maxSize에 의해 지정됩니다. 큰 스크립트 파일을 더 작은 파일로 나누면 로드 응답성을 개선할 수 있습니다. 작업이 작은 태스크로 분할되어 주요 작업을 차단할 가능성이 할 수 있습니다.

또한 더 큰 자바스크립트 파일을 생성하면 스크립트가 캐시 무효화가 발생할 가능성이 높습니다 예를 들어 대량의 큰 스크립트를 사용하려면 프레임워크와 자사 애플리케이션 코드가 모두 포함된 프레임워크만 업데이트되고 그 외에는 없는 경우에만 번들이 무효화될 수 있습니다. 리소스입니다

반면에 스크립트 파일의 크기가 작을수록 캐시에서 리소스를 검색하여 사이트에서 재방문 하지만 작은 파일은 큰 파일보다 압축하는 것이 더 유리합니다. 가공되지 않은 프레임으로 페이지 로드 시 네트워크 왕복 시간을 있습니다. 캐싱 간의 균형을 유지하기 위해 주의를 기울여야 함 효율, 압축 효과, 스크립트 평가 시간 등의 측정항목을 기준으로 삼을 수 있습니다.

<ph type="x-smartling-placeholder">

webpack 데모

<ph type="x-smartling-placeholder">

webpack SplitChunksPlugin 데모

학습한 내용 테스트

코드를 실행할 때 사용되는 import 문 유형은 무엇인가요? 어떻게 해야 할까요?

동적 import().
정답입니다.
정적 import.
다시 시도하세요.

다음 중 상단에 있어야 하는 import 문 유형은 무엇인가요? 다른 위치에 있지 않나요?

동적 import().
다시 시도하세요.
정적 import.
정답입니다.

Webpack에서 SplitChunksPlugin를 사용할 때 async 청크와 단일 덩어리의 차이를 청크 initial개를 삭제하시겠습니까?

async 청크가 동적 import()를 사용하여 로드됩니다. 및 initial 청크는 정적 import입니다.
정답입니다.
async 청크가 정적 import를 사용하여 로드됩니다. 및 initial 청크는 동적 import()입니다.
다시 시도하세요.

다음: 이미지 및 <iframe> 요소 지연 로드

JavaScript는 상당히 비싼 리소스 유형인 경향이 있지만 JavaScript는 유일하게 리소스 유형을 지정할 수 있습니다. 이미지 및 <iframe> 요소 그 자체로 잠재적으로 비용이 많이 드는 리소스입니다 JavaScript와 마찬가지로 지연 로드를 통해 이미지 및 <iframe> 요소의 로드를 지연시킬 수 있음 에 관해서는 이 과정의 다음 모듈에서 설명합니다.