gzip으로 네트워크 페이로드 축소 및 압축

이 Codelab에서는 JavaScript를 축소하고 압축하는 방법을 살펴봅니다. 다음 애플리케이션의 번들을 지정하면 앱의 요청 크기

앱 스크린샷

측정

최적화를 추가하기 전에 항상 먼저 최적화 작업을 현재 상태를 나타냅니다

  • 사이트를 미리 보려면 앱 보기를 누릅니다. 그런 다음 전체 화면 전체 화면입니다.

이 앱은 '사용하지 않는 앱 삭제' 코드' Codelab을 사용하면 가장 마음에 드는 코드에 투표할 수 있습니다. 있습니다. 🐈

이제 이 애플리케이션의 크기를 살펴보겠습니다.

  1. `Control+Shift+J` (또는 Mac의 경우 `Command+Option+J`)를 눌러 DevTools를 엽니다.
  2. 네트워크 탭을 클릭합니다.
  3. 캐시 사용 중지 체크박스를 선택합니다.
  4. 앱을 새로고침합니다.

네트워크 패널의 원래 번들 크기

'사용하지 않는 코드 삭제' Codelab을 통해 이 번들 크기를 줄이면 225KB는 여전히 상당히 큽니다.

축소

다음 코드 블록을 생각해 보세요.

function soNice() {
  let counter = 0;

  while (counter < 100) {
    console.log('nice');
    counter++;
  }
}

이 함수가 자체 파일에 저장되는 경우 파일 크기는 다음과 같습니다. 112B (바이트).

공백을 모두 삭제하면 결과 코드는 다음과 같습니다.

function soNice(){let counter=0;while(counter<100){console.log("nice");counter++;}}

이제 파일 크기는 약 83B입니다. 2012년 4월 31일까지 변수 이름의 길이와 일부 표현식을 수정하는 경우 최종 코드는 다음과 같이 표시됩니다.

function soNice(){for(let i=0;i<100;)console.log("nice"),i++}

이제 파일 크기가 62B에 도달합니다.

단계를 수행할 때마다 코드를 읽기가 점점 더 어려워지고 있습니다. 하지만 브라우저의 JavaScript 엔진은 이들 각각을 완전히 동일한 방식으로 해석합니다. 이 이러한 방식으로 코드를 난독화하면 더 작은 파일을 달성하는 데 도움이 될 수 있습니다. 있습니다. 1, 120억 개라는 것은 사실은 별로 시작해서 크기 감소

이 애플리케이션에서는 webpack 버전 4가 모듈 번들러 구체적인 버전은 package.json에서 확인할 수 있습니다.

"devDependencies": {
  //...
  "webpack": "^4.16.4",
  //...
}

버전 4는 프로덕션 모드 중에 기본적으로 번들을 축소하고 있습니다. 사용 TerserWebpackPlugin: Terser용 플러그인입니다. Terser는 JavaScript 코드를 압축하는 데 널리 사용되는 도구입니다.

축소된 코드가 어떤 모습인지 알아보려면 DevTools Network 패널에 있는 동안 main.bundle.js를 선택합니다. 이제 왼쪽 상단의 응답

대답 최소화

축소되고 손상된 최종 형태의 코드가 응답 본문에 표시됩니다. 축소되지 않은 번들의 크기를 확인하려면 번들을 여세요. webpack.config.js하고 mode 구성을 업데이트합니다.

module.exports = {
  mode: 'production',
  mode: 'none',
  //...

애플리케이션을 새로고침하고 DevTools Network 패널

번들 크기: 767KB

상당한 차이가 있습니다. 😅

계속하기 전에 여기에서 변경사항을 되돌려야 합니다.

module.exports = {
  mode: 'production',
  mode: 'none',
  //...

애플리케이션에 코드를 축소하는 프로세스를 포함하는 방법은 도구에 따라 다릅니다. 다음과 같습니다.

  • webpack v4 이상을 사용하는 경우 추가 작업을 수행할 필요가 없습니다. 프로덕션 모드에서 코드가 기본적으로 축소되기 때문입니다. 👍
  • 이전 버전의 webpack을 사용하는 경우 TerserWebpackPlugin을 설치하고 포함합니다. 설치할 수 있습니다. 문서 에서 자세히 설명합니다.
  • 다른 압축 플러그인도 존재하며 대신 (예: BabelMinifyWebpackPlugin) 및 ClosureCompilerPlugin을 사용합니다.
  • 모듈 번들러가 전혀 사용되지 않는 경우 Terser를 사용합니다. Cloud Functions를 CLI 도구로 사용하거나 종속 항목으로 직접 포함할 수 있습니다

압축

'압축'이라는 용어는 때때로 코드가 어떻게 작동하는지 설명하는 데 느슨하게 사용됩니다. 압축하는 동안 압축되지만 있습니다.

압축은 일반적으로 데이터를 사용하여 수정된 코드를 나타냄 압축 알고리즘입니다. 축소와는 달리 완벽한 이미지를 사용하려면 압축된 코드를 사용하기 전에 압축을 해제해야 합니다.

모든 HTTP 요청과 응답에서 브라우저와 웹 서버는 포함할 헤더 가져오거나 수신하는 애셋에 대한 추가 정보가 필요합니다. 이는 DevTools Network 패널의 Headers 탭에 표시되며 표시됩니다.

  • 일반은 전체 요청-응답과 관련된 일반 헤더를 나타냅니다. 상호작용하지 않습니다.
  • 응답 헤더는 실제 응답과 관련된 헤더 목록을 표시합니다. 서버로부터 얻습니다.
  • 요청 헤더에는 있습니다

Request Headersaccept-encoding 헤더를 확인합니다.

인코딩 헤더 수락

accept-encoding는 브라우저에서 사용할 콘텐츠를 지정하는 데 사용됩니다. 또는 압축 알고리즘을 기반으로 하는 경우 이를 지원합니다. 다양한 텍스트 압축 알고리즘이 있지만 실제로 사용하는 HTTP 네트워크 요청의 압축 (및 압축 해제)을 위해 여기에서 지원됩니다.

  • Gzip (gzip): 가장 널리 사용되는 압축입니다. 서버 및 클라이언트 상호 작용을 위한 형식입니다. Deflate를 기반으로 구축됩니다. 모든 최신 브라우저에서 지원됩니다.
  • Deflate (deflate): 일반적으로 사용되지 않습니다.
  • Brotli (br): 최신 압축입니다. 압축비를 더욱 개선하는 것을 목표로 하는 알고리즘입니다. 페이지 로드 속도도 더 빨라졌습니다. 지원되는 최신 버전을 사용하는 것이 좋습니다.

이 튜토리얼의 샘플 애플리케이션은 '사용하지 않는 코드 삭제' Codelab에서는 Express는 이제 서버 프레임워크로 사용됩니다. 다음 정적 및 동적 압축을 모두 살펴봅니다.

동적 압축

동적 압축은 애셋을 가져오는 즉시 압축하는 것입니다. 브라우저에서 요청합니다.

장점

  • 압축된 버전의 애셋을 만들고 업데이트할 필요가 없습니다. 완료되었습니다.
  • 즉석 압축은 생성됩니다.

단점

  • 더 나은 압축률을 얻기 위해 더 높은 수준에서 파일 압축 시간이 더 오래 걸립니다. 이로 인해 사용자가 애셋이 표시되기를 기다리면서 성능 저하가 발생할 수 있습니다. 압축해야 합니다

Node/Express를 사용한 동적 압축

server.js 파일은 다음을 호스팅하는 노드 서버 설정을 담당합니다. 지정할 수 있습니다

const express = require('express');

const app = express();

app.use(express.static('public'));

const listener = app.listen(process.env.PORT, function() {
  console.log('Your app is listening on port ' + listener.address().port);
});

현재 이 모든 작업은 express를 가져오고 express.static 정적 HTML, JS 및 CSS 파일을 모두 로드하여 public/ 디렉터리에 있습니다 (이러한 파일은 모든 빌드에서 webpack에 의해 생성됨).

모든 애셋이 요청될 때마다 압축되도록 하기 위해 compression 미들웨어 라이브러리를 통해 사용됩니다. 먼저 package.jsondevDependency로 추가합니다.

"devDependencies": {
  //...
  "compression": "^1.7.3"
},

그런 다음 서버 파일 server.js로 가져옵니다.

const express = require('express');
const compression = require('compression');

express.static가 마운트되기 전에 미들웨어로 추가합니다.

//...

const app = express();

app.use(compression());

app.use(express.static('public'));

//...

이제 앱을 새로고침하고 Network 패널에서 번들 크기를 확인합니다.

동적 압축을 사용한 번들 크기

225KB에서 61.6KB로 현재 Response Headers에서 content-encoding 헤더는 서버가 gzip로 인코딩된 이 파일을 전송하고 있음을 보여줍니다.

콘텐츠 인코딩 헤더

정적 압축

정적 압축의 기본 개념은 애셋을 압축하고 저장하는 것입니다. 진행해야 합니다

장점

  • 높은 압축 수준으로 인한 지연 시간은 더 이상 문제가 되지 않습니다. 이제 파일을 직접 가져올 수 있으므로 즉시 파일을 압축할 필요가 없습니다.

단점

  • 애셋은 모든 빌드에서 압축되어야 합니다. 빌드 시간이 늘어날 수 있음 높은 압축 수준을 사용하면 크게 높아집니다.

Node/Express 및 webpack을 사용한 정적 압축

정적 압축에는 파일을 미리 압축하는 작업이 포함되므로 webpack 설정은 빌드 단계에서 애셋을 압축하도록 수정될 수 있습니다. CompressionPlugin 드림 사용할 수 있습니다

먼저 package.jsondevDependency로 추가합니다.

"devDependencies": {
  //...
  "compression-webpack-plugin": "^1.1.11"
},

다른 webpack 플러그인과 마찬가지로, 구성 파일에서 이를 가져옵니다. webpack.config.js:

const path = require("path");

//...

const CompressionPlugin = require("compression-webpack-plugin");

그리고 plugins 배열 내에 포함합니다.

module.exports = {
  //...
  plugins: [
    //...
    new CompressionPlugin()
  ]
}

기본적으로 플러그인은 gzip를 사용하여 빌드 파일을 압축합니다. 살펴보기 자세한 내용은 문서 다른 알고리즘을 사용하거나 포함/제외하는 옵션을 추가하는 방법을 알아보세요. 특정 파일이 포함될 수 있습니다

앱이 새로고침되고 다시 빌드될 때 기본 번들의 압축된 버전은 되었습니다. Glitch Console을 열고 노드 서버에서 제공하는 최종 public/ 디렉터리

  • 도구 버튼을 클릭합니다.
  • 콘솔 버튼을 클릭합니다.
  • 콘솔에서 다음 명령어를 실행하여 public로 변경합니다. 디렉터리의 모든 파일을 확인합니다.
cd public
ls

공개 디렉터리의 최종 출력 파일

번들의 gzip 버전 main.bundle.js.gz은 이제 다음과 같이 여기에 저장됩니다. 있습니다. CompressionPlugin는 기본적으로 index.html도 압축합니다.

다음으로 해야 할 일은 이 파일을 gzip으로 압축하여 전송하도록 서버에 원본 JS 버전이 요청될 때마다 파일을 캐시합니다. 이 작업은 파일이 제공되기 전에 server.js에서 새 경로를 정의하여 express.static

const express = require('express');
const app = express();

app.get('*.js', (req, res, next) => {
  req.url = req.url + '.gz';
  res.set('Content-Encoding', 'gzip');
  next();
});

app.use(express.static('public'));

//...

app.get는 지정할 수 있습니다 그런 다음 콜백 함수를 사용하여 합니다. 경로는 다음과 같이 작동합니다.

  • '*.js'를 첫 번째 인수로 지정하면 JS 파일을 가져오기 위해 실행되는 엔드포인트입니다.
  • 콜백 내에서 .gz는 요청의 URL에 연결되며 Content-Encoding 응답 헤더가 gzip로 설정되었습니다.
  • 마지막으로 next()는 시퀀스가 모든 콜백으로 계속 진행되도록 합니다. 살펴봤습니다

앱이 새로고침되면 Network 패널을 한 번 더 확인합니다.

정적 압축을 사용한 번들 크기 축소

이전과 마찬가지로 번들 크기가 크게 감소했습니다.

결론

이 Codelab에서는 소스 코드를 축소하고 압축하는 프로세스를 다뤘습니다. 이 두 가지 기법은 많은 도구에서 기본으로 사용되고 있습니다. 이미 사용 중인 도구 모음이 이미 사용 가능한지 확인하는 것이 중요합니다. 두 프로세스를 모두 적용해야 하는지 확인하세요.