>웹 프론트엔드 >JS 튜토리얼 >JavaScript의 성능 최적화에 대한 자세한 설명

JavaScript의 성능 최적화에 대한 자세한 설명

亚连
亚连원래의
2018-06-21 16:10:081308검색

이제 JavaScript 기반 성능 최적화 기술에 대한 기사를 공유하겠습니다. 좋은 참고 가치가 있으며 모든 사람에게 도움이 되기를 바랍니다. 에디터를 따라가서 살펴보겠습니다

JavaScript는 현재 가장 일반적인 문자 그대로의 스크립트 언어로 웹 애플리케이션 개발에 널리 사용되고 있습니다. 웹 애플리케이션의 성능을 향상시키기 위해서는 자바스크립트 성능 최적화부터 시작하는 것이 좋은 선택이 될 것입니다.

이 기사에서는 더 많은 프런트엔드 개발자가 이 지식을 익힐 수 있도록 로딩, 컨텍스트, 구문 분석, 컴파일, 실행 및 번들링과 같은 여러 측면에서 JavaScript 성능 최적화 기술을 설명합니다.

고성능 JavaScript 코드란 무엇인가요?

현재 고성능 코드에 대한 절대적인 정의는 없지만 참고할 수 있는 사용자 중심의 성능 모델이 있습니다. 바로 RAIL 모델입니다.

Response

애플리케이션이 100밀리초 이내에 사용자의 작업에 응답할 수 있다면 사용자는 응답을 즉각적인 것으로 인식합니다. 이는 스크롤이나 드래그 작업이 아닌 클릭 가능한 요소에 적용됩니다.

Animation

60Hz 모니터에서 애니메이션 및 스크롤 시 초당 60프레임이 필요합니다. 이 경우 각 프레임은 약 16ms입니다. 16ms 중에서 모든 작업을 수행하는 데 실제로는 8~10ms만 있고 나머지 시간은 브라우저 내부 및 기타 차이점으로 인해 사용됩니다.

유휴 작업

오랜 시간이 걸리고 지속적으로 실행해야 하는 작업이 있는 경우, 메인 스레드가 사용자 입력에 반응할 수 있도록 작은 덩어리로 나누어야 합니다. 사용자 입력을 50ms 이상 지연시키는 작업이 있어서는 안 됩니다.

Loading

페이지 로딩은 1000ms 이내에 완료되어야 합니다. 모바일 장치에서는 단순히 화면을 렌더링하고 스크롤하는 것이 아니라 페이지와의 상호 작용을 포함하기 때문에 달성하기 어려운 목표입니다.

최신 로딩 모범 사례(Chrome Dev Summit 2017)

53%의 사용자는 로딩하는 데 3초 이상 걸리면 모바일 사이트를 이탈합니다.

50%의 사용자는 2초 이내에 로딩하기를 원합니다. 시간 내에 페이지 로드를 완료하세요

77%의 모바일 웹사이트가 3G 네트워크에서 로드하는 데 10초 이상이 걸립니다

19초는 3G 네트워크에서 모바일 사이트의 평균 로드 시간입니다

코드 콘텐츠

지금 가장 큰 병목 현상은 웹 사이트를 로드하는 데 걸리는 시간입니다. 구체적으로는 JavaScript의 다운로드, 구문 분석, 컴파일 및 실행 시간입니다. 더 적은 수의 JavaScript 파일을 로드하거나 더 유연하게 로드하는 것 외에는 다른 방법이 없는 것 같습니다.

웹사이트를 시작하는 것 외에 JavaScript 코드는 실제로 어떻게 작동하나요?

코드 최적화를 수행하기 전에 현재 빌드 중인 항목을 고려하세요. 프레임워크를 구축하고 있습니까, 아니면 VDOM 라이브러리를 구축하고 있습니까? 코드가 초당 수천 개의 작업을 수행해야 합니까? 사용자 입력 및/또는 애니메이션을 처리하는 시간 결정적 라이브러리를 만들고 있습니까? 그렇지 않다면 시간과 에너지를 보다 영향력 있는 영역으로 전환해야 합니다.

성능 코드를 작성하는 것은 일반적으로 전체적인 계획에 거의 영향을 미치지 않기 때문에 그다지 중요하지 않습니다. 50,000 ops/s가 1,000 ops/s보다 더 좋게 들리지만 대부분의 경우 전체 시간은 변하지 않습니다.

파싱, 컴파일 및 실행

기본적으로 대부분의 JavaScript 성능 문제는 코드 자체를 실행하는 데 있는 것이 아니라 코드가 실행되기 전에 수행해야 하는 일련의 단계에 있습니다.

여기서는 추상화 수준에 대해 논의하고 있습니다. 컴퓨터에서 실행되는 대부분의 코드는 컴파일된 바이너리 형식입니다. 이는 모든 운영 체제 수준 추상화를 제외하고 코드가 준비 없이 하드웨어에서 기본적으로 실행될 수 있음을 의미합니다.

JavaScript 코드는 미리 컴파일되어 있지 않으며 브라우저에서 읽을 수 있습니다.

JavaScript 코드는 먼저 파싱됩니다. 즉, 컴퓨터 인덱스 컴파일에 사용할 수 있는 구조로 읽고 변환한 다음 바이트코드로 컴파일하고 마지막으로 장치/브라우저 실행을 위한 기계어 코드로 컴파일합니다.

또 다른 매우 중요한 측면: JavaScript는 단일 스레드이며 브라우저의 기본 스레드에서 실행됩니다. 이는 한 번에 하나의 프로세스만 실행할 수 있음을 의미합니다. DevTools 성능 타임라인이 노란색 스파이크로 채워지고 CPU 사용량이 100%에 도달하면 프레임 손실이 발생합니다. 이는 스크롤할 때 일반적이고 짜증나는 상황입니다.

이 모든 구문 분석, 컴파일 및 실행 작업은 JavaScript 코드가 실행되기 전에 완료되어야 합니다. ChromeV8 엔진에서 구문 분석 및 컴파일은 전체 JavaScript 실행 시간의 약 50%를 차지합니다.

이 부분에서는 다음 두 가지를 이해해야 합니다.

1 JavaScript 구문 분석 시간과 패킷 크기가 완전히 선형적이지는 않지만 처리해야 하는 JavaScript가 적습니다. , 더 좋습니다. 시간을 덜 쓰세요.

2. 사용하는 모든 JavaScript 프레임워크(React, Vue, Angular, Preact...)는 또 다른 추상화 수준입니다(미리 컴파일된 프레임워크가 아닌 경우). 이렇게 하면 번들 크기가 커질 뿐만 아니라 브라우저와 직접 통신하지 않기 때문에 코드 속도도 느려집니다.

서비스 워커를 사용하여 백그라운드의 다른 스레드에서 작업의 일부를 수행하거나 asm.js를 사용하여 기계 명령어로 더 쉽게 컴파일할 수 있는 코드를 작성하는 등 이를 완화할 수 있는 방법이 있습니다.

우리가 할 수 있는 일은 JavaScript 애니메이션 라이브러리를 사용하지 않는 것뿐입니다. 일반 CSS 전환 및 애니메이션을 사용하여 달성하는 것이 완전히 불가능한 경우에만 이러한 라이브러리를 사용하십시오.

이러한 JavaScript 애니메이션 라이브러리는 CSS 변환, 복합 속성 및 requestAnimationFrame()을 사용하더라도 여전히 JavaScript의 기본 스레드에서 실행됩니다. 기본적으로 이러한 라이브러리는 인라인 스타일을 사용하여 16ms마다 DOM에 액세스합니다. 애니메이션의 부드러움을 유지하려면 각 프레임의 8ms 이내에 모든 JavaScript가 완료되도록 해야 합니다.

반면에 CSS 애니메이션과 전환은 메인 스레드에서 실행됩니다. 효율적으로 실행될 수 있으면 릴레이아웃/리플로우를 피할 수 있습니다.

대부분의 애니메이션이 로딩 또는 사용자 상호 작용 중에 실행된다는 점을 고려하면 웹 애플리케이션에 몇 가지 매우 중요한 조정이 가능합니다.

웹 애니메이션 API는 고성능 JavaScript 애니메이션을 메인 스레드에서 실행할 수 있게 해주는 곧 출시될 기능 세트입니다. 그러나 현재로서는 CSS 전환과 같은 기술을 계속 사용해야 합니다.

번들 크기는 매우 중요합니다

36cc49f0c466276486e50c850b7e4956 닫기 태그 앞에 여러 개의 3f1c4e4b6b16bbbd69b2ee476dc4f83a를 사용하는 시대는 지났습니다. 이제 npm에서 다양한 툴킷을 찾을 수 있으며, 이러한 툴킷은 단일 1MB JavaScript 파일로 Webpack과 함께 번들로 제공되어 데이터 계획이 완료되면 사용자 브라우저에 크롤링하도록 경고할 수 있습니다.

이것은 JavaScript를 덜 사용하므로 프로젝트에 더 이상 전체 Lodash 라이브러리가 필요하지 않을 수도 있습니다. JavaScript 라이브러리를 사용해야 한다면 React 크기의 1/20에 불과한 Preact 또는 HyperHTML과 같은 React 이외의 다른 것을 사용하는 것이 좋습니다.

Webpack 3에는 코드 분할 및 동적 가져오기라는 놀라운 기능이 있습니다. 모든 JavaScript 모듈을 단일 app.js 패키지로 묶지는 않지만 import() 구문을 사용하여 자동으로 코드를 분할하고 비동기적으로 로드합니다.

이러한 이점을 얻기 위해 프레임워크, 구성 요소 및 클라이언트 측 라우팅을 사용할 필요는 없습니다. 기본 JavaScript 파일에 다음을 작성하기만 하면 됩니다.

if (document.querySelector('.mega-widget')) {
 import('./mega-widget');
}

애플리케이션에 페이지에 이 위젯이 필요한 경우 필요한 지원 코드가 동적으로 로드됩니다.

또한 Webpack이 작동하고 생성되는 모든 .js 파일에 삽입하려면 런타임이 필요합니다. commonChunks 플러그인을 사용하는 경우 다음을 사용하여 런타임을 청크로 추출할 수 있습니다:

new webpack.optimize.CommonsChunkPlugin({
 name: 'runtime',
}),

Webpack이 기본 JavaScript 번들 전에 로드를 완료했는지 확인하세요. 그러면 다른 모든 청크의 런타임이 자체 파일로 제거됩니다. 이 상황을 Runtime.js라고도 합니다. 예:

<script src="runtime.js">
<script src="main-bundle.js">

다음은 코드와 폴리필을 컴파일하는 부분입니다. 최신 JavaScript 코드(ES6+)를 작성하는 경우 Babel을 사용하여 이를 ES5 호환 코드로 변환할 수 있습니다. 컴파일은 파일 크기를 증가시킬 뿐만 아니라 복잡성을 가중시키고 기본 ES6+ 코드에 비해 성능 저하를 겪는 경우가 많습니다.

이 외에도 이전 브라우저에서 누락된 기능을 수정하기 위해 babel-polyfill 패키지와 whatwg-fetch를 사용할 가능성이 높습니다. 따라서 async/await를 작성하는 경우 생성기 패키지 regenerator-runtime을 사용하여 컴파일해야 합니다.

문제는 JavaScript 패키지에 거의 100KB를 추가한다는 것입니다. 이는 거대한 파일일 뿐만 아니라 이전 브라우저를 지원하기 위한 구문 분석 및 실행에 막대한 오버헤드를 나타냅니다.

一种方法是创建两个独立的 bundle,并根据实际条件来加载它们。Babel 转换编译器在 babel-preset-env 的帮助下,会使同时面临新旧两种浏览器的情况更加容易处理。

一个并不规范但行之有效的方法,是将以下内容放在一个内联脚本中:

(function() {
 try {
 new Function(&#39;async () => {}&#39;)();
 } catch (error) {
 // create script tag pointing to legacy-bundle.js;
 return;
 }
 // create script tag pointing to modern-bundle.js;;
})();

如果浏览器无法识别 async 函数,则会被认为是旧版本的浏览器,此时就会用到 polyfill 包。如果能识别,用户则将得到现代浏览器的处理。

结论

想要提高网站的运行速度,就需要确保网站能快速的加载 JavaScript 文件,以实现快速的互动。你的 JavaScript 代码应该被分成更小的、可管理的 bundle,同时尽可能地进行异步加载。在服务器端,请确保启用了 HTTP 2.0,以便实现更快的并行传输和 gzip/Brotli 压缩,从而大大减少了 JavaScript 的传输大小。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

使用JQUERY如何实现多个AJAX请求

使用js如何实现焦点图效果

在微信小程序中如何实现图片懒加载

위 내용은 JavaScript의 성능 최적화에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.