페이지 로드 속도를 높이기 위해 최신 브라우저에 최신 코드 제공하기

모든 주요 브라우저에서 잘 작동하는 웹사이트를 빌드하는 것은 개방형 웹 생태계의 핵심 원칙입니다. 그러나 이렇게 하면 작성한 모든 코드가 타겟팅하려는 각 브라우저에서 지원되도록 하는 추가 작업이 필요합니다. 새 JavaScript 언어 기능을 사용하려면 아직 이러한 기능을 지원하지 않는 브라우저를 위해 이러한 기능을 하위 호환 형식으로 트랜스파일해야 합니다.

Babel은 최신 문법이 포함된 코드를 여러 브라우저와 환경(예: Node)에서 이해할 수 있는 코드로 컴파일하는 데 가장 널리 사용되는 도구입니다. 이 가이드에서는 Babel을 사용한다고 가정합니다. 따라서 아직 Babel을 애플리케이션에 포함하지 않았다면 설정 안내에 따라 Babel을 애플리케이션에 포함해야 합니다. 앱에서 webpack을 모듈 번들러로 사용하는 경우 Build Systems에서 webpack를 선택합니다.

Babel을 사용하여 사용자에게 필요한 항목만 컴파일하려면 다음을 실행해야 합니다.

  1. 타겟팅할 브라우저를 식별합니다.
  2. 적절한 브라우저 타겟과 함께 @babel/preset-env를 사용합니다.
  3. <script type="module">를 사용하여 트랜스파일된 코드가 필요하지 않은 브라우저에 트랜스파일된 코드를 전송하지 않도록 합니다.

타겟팅할 브라우저 식별

애플리케이션의 코드가 트랜스파일되는 방식을 수정하기 전에 애플리케이션에 액세스하는 브라우저를 식별해야 합니다. 사용자가 현재 사용 중인 브라우저와 타겟팅할 브라우저를 분석하여 정보에 입각한 결정을 내립니다.

@babel/preset-env 사용

코드를 트랜스파일하면 일반적으로 원래 형식보다 파일 크기가 더 큰 파일이 생성됩니다. 컴파일 양을 최소화하면 번들 크기를 줄여 웹페이지의 성능을 개선할 수 있습니다.

Babel은 사용 중인 특정 언어 기능을 선택적으로 컴파일하는 특정 플러그인을 포함하는 대신 플러그인을 번들로 묶는 여러 사전 설정을 제공합니다. @babel/preset-env를 사용하여 타겟팅하려는 브라우저에 필요한 변환과 폴리필만 포함합니다.

Babel 구성 파일(.babelrc)의 presets 배열 내에 @babel/preset-env를 포함합니다.

{
 "presets": [
   [
     "@babel/preset-env",
     {
       "targets": ">0.25%"
     }
   ]
 ]
}

targets 필드를 사용하여 browsers 필드에 적절한 쿼리를 추가하여 포함할 브라우저 버전을 지정합니다. @babel/preset-env는 브라우저 타겟팅을 위해 여러 도구 간에 공유되는 오픈소스 구성인 browserslist와 통합됩니다. 호환되는 쿼리의 전체 목록은 browserslist 문서를 참고하세요. 또 다른 방법은 .browserslistrc 파일을 사용하여 타겟팅하려는 환경을 나열하는 것입니다.

">0.25%" 값은 전 세계 사용량의 0.25% 를 차지하는 브라우저를 지원하는 데 필요한 변환만 포함하도록 Babel에 지시합니다. 이렇게 하면 매우 적은 비율의 사용자가 사용하는 브라우저용으로 불필요하게 변환된 코드가 번들에 포함되지 않습니다.

대부분의 경우 다음 구성을 사용하는 것보다 이 방법이 더 좋습니다.

  "targets": "last 2 versions"

"last 2 versions" 값은 모든 브라우저의 마지막 두 버전에 맞게 코드를 트랜스파일합니다. 즉, Internet Explorer와 같이 지원 중단된 브라우저도 지원됩니다. 이러한 브라우저가 애플리케이션에 액세스하는 데 사용되지 않을 것으로 예상되는 경우 불필요하게 번들 크기가 커질 수 있습니다.

궁극적으로는 필요에 맞는 브라우저만 타겟팅할 수 있도록 적절한 쿼리 조합을 선택해야 합니다.

최신 버그 수정 사용 설정

@babel/preset-env는 여러 JavaScript 문법 기능을 컬렉션으로 그룹화하고 지정된 대상 브라우저에 따라 사용 설정/사용 중지합니다. 이 방법은 잘 작동하지만 타겟팅된 브라우저에 단일 기능의 버그가 포함된 경우 전체 문법 기능 모음이 변환됩니다. 이로 인해 필요한 것보다 더 많은 코드가 변환되는 경우가 많습니다.

원래 별도의 사전 설정으로 개발된 @babel/preset-env버그 수정 옵션은 일부 브라우저에서 손상된 최신 문법을 이러한 브라우저에서 손상되지 않은 가장 가까운 등가 문법으로 변환하여 이 문제를 해결합니다. 그 결과는 모든 대상 브라우저에서 호환성을 보장하는 몇 가지 작은 문법 조정을 제외하고 거의 동일한 최신 코드입니다. 이 최적화를 사용하려면 @babel/preset-env 7.10 이상이 설치되어 있는지 확인한 다음 bugfixes 속성을 true로 설정합니다.

{
 "presets": [
   [
     "@babel/preset-env",
     {
       "bugfixes": true
     }
   ]
 ]
}

Babel 8에서는 bugfixes 옵션이 기본적으로 사용 설정됩니다.

<script type="module"> 사용

JavaScript 모듈 또는 ES 모듈은 모든 주요 브라우저에서 지원되는 비교적 새로운 기능입니다. 모듈을 사용하여 다른 모듈에서 가져오고 내보낼 수 있는 스크립트를 만들 수 있지만 @babel/preset-env와 함께 사용하여 이를 지원하는 브라우저만 타겟팅할 수도 있습니다.

특정 브라우저 버전이나 시장 점유율을 쿼리하는 대신 .babelrc 파일의 targets 필드 내에 "esmodules" : true를 지정하는 것이 좋습니다.

{
   "presets":[
      [
         "@babel/preset-env",
         {
            "targets":{
               "esmodules": true
            }
         }
      ]
   ]
}

Babel로 컴파일된 많은 최신 ECMAScript 기능은 JavaScript 모듈을 지원하는 환경에서 이미 지원됩니다. 이렇게 하면 실제로 필요한 브라우저에 트랜스파일된 코드만 사용되도록 하는 프로세스를 간소화할 수 있습니다.

모듈을 지원하는 브라우저는 nomodule 속성이 있는 스크립트를 무시합니다. 반대로 모듈을 지원하지 않는 브라우저는 type="module"가 있는 스크립트 요소를 무시합니다. 즉, 모듈과 컴파일된 대체 값을 모두 포함할 수 있습니다.

이상적으로 애플리케이션의 두 버전 스크립트는 다음과 같이 포함됩니다.

  <script type="module" src="main.mjs"></script>
  <script nomodule src="compiled.js" defer></script>

모듈을 지원하는 브라우저는 main.mjs를 가져와 실행하고 compiled.js는 무시합니다. 모듈을 지원하지 않는 브라우저는 그 반대의 방식을 사용합니다.

webpack을 사용하는 경우 구성에서 애플리케이션의 두 가지 버전에 대해 서로 다른 타겟을 설정할 수 있습니다.

  • 모듈을 지원하는 브라우저 전용 버전입니다.
  • 기존 브라우저에서 작동하는 컴파일된 스크립트가 포함된 버전입니다. 트랜스파일링은 더 광범위한 브라우저를 지원해야 하므로 파일 크기가 더 큽니다.

리뷰를 제공해 주신 Connor Clark님과 Jason Miller님께 감사드립니다.