gzip ile ağ yüklerini küçültün ve sıkıştırın

Bu kod laboratuvarında, aşağıdaki uygulamanın JavaScript paketinin hem küçültülmesinin hem de sıkıştırılmasının, uygulamanın istek boyutunu azaltarak sayfa performansını nasıl iyileştirdiği incelenmektedir.

Uygulama ekran görüntüsü

Ölçüm

Optimizasyon eklemeye başlamadan önce, uygulamanın mevcut durumunu analiz etmek her zaman iyi bir fikirdir.

  • Siteyi önizlemek için Uygulamayı Görüntüle'ye, ardından Tam Ekran'a tam ekran basın.

"Kullanılmayan kodu kaldırma" codelab'inde de ele alınan bu uygulama, en sevdiğiniz kediye oy vermenize olanak tanır. 🐈

Şimdi bu uygulamanın ne kadar büyük olduğuna göz atın:

  1. Geliştirici Araçları'nı açmak için "Kontrol+Üst Karakter+J" (veya Mac'te "Komut+Option+J") tuşlarına basın.
  2. sekmesini tıklayın.
  3. Önbelleği devre dışı bırak onay kutusunu işaretleyin.
  4. Uygulamayı yeniden yükleyin.

Ağ panelinde orijinal paket boyutu

"Kullanılmayan kodu kaldırın" kod laboratuvarında bu paket boyutunu küçültmek için çok ilerleme kaydedilmiş olsa da 225 KB hâlâ oldukça büyük.

Sadeleştirme

Aşağıdaki kod bloğunu ele alalım.

function soNice() {
  let counter = 0;

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

Bu işlev kendi dosyasına kaydedilirse dosya boyutu yaklaşık 112 B (bayt) olur.

Tüm boşluklar kaldırılırsa ortaya çıkan kod şu şekilde görünür:

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

Dosya boyutu yaklaşık 83 B olur. Değişken adının uzunluğu azaltılarak ve bazı ifadeler değiştirilerek daha da bozulursa nihai kod şu şekilde görünebilir:

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

Dosya boyutu artık 62 B'a ulaştı.

Her adımda kodun okunması daha da zorlaşıyor. Ancak tarayıcının JavaScript motoru bunların her birini tam olarak aynı şekilde yorumlar. Kodu bu şekilde karartmanın avantajı, daha küçük dosya boyutları elde etmenize yardımcı olabilir. 112 B başlangıçta çok büyük bir boyut değildi ancak yine de boyutta %50 oranında bir azalma elde edildi.

Bu uygulamada, modül paketleyici olarak webpack 4 sürümü kullanılmaktadır. Belirli sürümü package.json'te görebilirsiniz.

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

4. sürüm, üretim modunda varsayılan olarak paketi küçültür. TerserWebpackPluginTerser için bir eklenti kullanır. Terser, JavaScript kodunu sıkıştırmak için kullanılan popüler bir araçtır.

Kodun sıkıştırılmış hâlinin nasıl göründüğüne dair fikir edinmek için DevTools panelindeyken main.bundle.js simgesini tıklayın. Ardından Yanıt sekmesini tıklayın.

Minified response

Kod, son biçiminde, sıkıştırılmış ve bozulmuş olarak yanıt gövdesinde gösterilir. Paket, sıkıştırılmamış olsaydı ne kadar büyük olabileceğini öğrenmek için webpack.config.js dosyasını açıp mode yapılandırmasını güncelleyin.

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

Uygulamayı yeniden yükleyin ve DevTools panelinden paket boyutuna tekrar göz atın.

767 KB&#39;lık paket boyutu

Bu oldukça büyük bir fark. 😅

Devam etmeden önce buradaki değişiklikleri geri almanız gerekir.

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

Uygulamanıza kod sıkıştırma işlemi eklemek, kullandığınız araçlara bağlıdır:

  • Webpack 4 veya sonraki bir sürüm kullanılıyorsa kod üretim modunda varsayılan olarak küçültüldüğünden ek işlem yapılması gerekmez. 👍
  • Web paketinin daha eski bir sürümü kullanılıyorsa TerserWebpackPlugin uygulamasını yükleyin ve web paketi derleme işlemine ekleyin. Bu konu dokümanlarda ayrıntılı olarak açıklanmıştır.
  • BabelMinifyWebpackPlugin ve ClosureCompilerPlugin gibi diğer küçültme eklentileri de kullanılabilir.
  • Hiçbir modül paketleyici kullanılmıyorsa CLI aracı olarak Terser'i kullanın veya doğrudan bağımlılık olarak ekleyin.

Sıkıştırma

"Sıkıştırma" terimi, bazen kod azaltma işlemi sırasında kodun nasıl azaltıldığını açıklamak için gevşek bir şekilde kullanılsa da kod, gerçek anlamda sıkıştırılmaz.

Sıkıştırma, genellikle bir veri sıkıştırma algoritması kullanılarak değiştirilmiş kodu ifade eder. Mükemmel şekilde geçerli kod sağlayan sıkıştırmanın aksine, sıkıştırılmış kodun kullanılmadan önce sıkıştırmasının çözülmesi gerekir.

Tarayıcılar ve web sunucuları, her HTTP isteği ve yanıtıyla birlikte getirilen veya alınan öğe hakkında ek bilgi içeren başlıklar ekleyebilir. Bu durum, üç türün gösterildiği DevTools Ağ panelindeki Headers sekmesinde görülebilir:

  • Genel, istek-yanıt etkileşiminin tamamıyla ilgili genel üstbilgileri temsil eder.
  • Yanıt Başlıkları, sunucudan gelen gerçek yanıta özgü başlıkların listesini gösterir.
  • İstek Üst Bilgileri, istemci tarafından isteğe eklenen üst bilgilerin listesini gösterir.

Request Headers'daki accept-encoding başlığına göz atın.

Accept-Encoding üstbilgisi

accept-encoding, tarayıcı tarafından desteklediği içerik kodlama biçimlerini veya sıkıştırma algoritmalarını belirtmek için kullanılır. Birçok metin sıkıştırma algoritması vardır ancak HTTP ağ isteklerinin sıkıştırılması (ve sıkıştırmanın açılması) için burada yalnızca üçü desteklenir:

  • Gzip (gzip): Sunucu ve istemci etkileşimleri için en yaygın olarak kullanılan sıkıştırma biçimidir. Deflate algoritmasını temel alır ve mevcut tüm tarayıcılarda desteklenir.
  • Sıkıştır (deflate): Genellikle kullanılmaz.
  • Brotli (br): Sıkıştırma oranlarını daha da iyileştirmeyi amaçlayan daha yeni bir sıkıştırma algoritması. Bu algoritma, sayfaların daha da hızlı yüklenmesine neden olabilir. Çoğu tarayıcının en son sürümlerinde desteklenir.

Bu eğitimdeki örnek uygulama, Express'in artık sunucu çerçevesi olarak kullanılması dışında "Kullanılmayan kodu kaldırma" codelab'inde tamamlanan uygulamayla aynıdır. Sonraki birkaç bölümde hem statik hem de dinamik sıkıştırma incelenmektedir.

Dinamik sıkıştırma

Dinamik sıkıştırma, öğelerin tarayıcı tarafından istendiği anda sıkıştırılmasını içerir.

Artıları

  • Öğelerin sıkıştırılmış ve kayıtlı sürümlerini oluşturmak ve güncellemek gerekmez.
  • Anlık sıkıştırma, özellikle dinamik olarak oluşturulan web sayfalarında iyi sonuç verir.

Eksileri

  • Daha iyi sıkıştırma oranları elde etmek için dosyaları daha yüksek düzeylerde sıkıştırmak daha uzun sürer. Bu durum, kullanıcı sunucu tarafından gönderilmeden önce öğelerin sıkıştırılmasını beklerken performans düşüşüne neden olabilir.

Node/Express ile dinamik sıkıştırma

server.js dosyası, uygulamayı barındıran Node sunucusunu oluşturmaktan sorumludur.

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);
});

Şu anda bu işlem yalnızca express dosyasını içe aktarır ve public/ dizinindeki tüm statik HTML, JS ve CSS dosyalarını yüklemek için express.static aracıyı kullanır (bu dosyalar her derlemede webpack tarafından oluşturulur).

Tüm öğelerin istendiğinde sıkıştırıldığından emin olmak için sıkıştırma orta katman kitaplığı kullanılabilir. package.json'a devDependency olarak ekleyerek başlayın:

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

Ardından, server.js sunucu dosyasına aktarın:

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

Ardından, express.static monte edilmeden önce ara yazılım olarak ekleyin:

//...

const app = express();

app.use(compression());

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

//...

Şimdi uygulamayı yeniden yükleyin ve panelindeki paket boyutuna göz atın.

Dinamik sıkıştırma ile paket boyutu

225 KB'dan 61,6 KB'ya düştü. Response Headers şimdi, content-encoding başlığı, sunucunun bu dosyayı gzip ile kodlanmış olarak gönderdiğini gösterir.

İçerik kodlama üstbilgisi

Statik sıkıştırma

Statik sıkıştırmanın amacı, öğelerin önceden sıkıştırılıp kaydedilmesidir.

Artıları

  • Yüksek sıkıştırma seviyelerinden kaynaklanan gecikme artık sorun olmaktan çıktı. Artık dosyalar doğrudan getirilebildiğinden, sıkıştırmak için anında bir işlem yapılması gerekmez.

Eksileri

  • Öğelerin her derlemede sıkıştırılması gerekir. Yüksek sıkıştırma seviyeleri kullanılırsa derleme süreleri önemli ölçüde artabilir.

Node/Express ve webpack ile statik sıkıştırma

Statik sıkıştırma, dosyaları önceden sıkıştırmayı içerdiğinden webpack ayarları, derleme adımı kapsamında öğeleri sıkıştıracak şekilde değiştirilebilir. CompressionPlugin bu amaçla kullanılabilir.

package.json'a devDependency olarak ekleyerek başlayın:

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

Diğer tüm webpack eklentileri gibi, bu eklentiyi de yapılandırmalar dosyasına aktarın. webpack.config.js:

const path = require("path");

//...

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

Ardından plugins dizisine ekleyin:

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

Eklenti, varsayılan olarak derleme dosyalarını gzip kullanarak sıkıştırır. Farklı bir algoritma kullanma veya belirli dosyaları dahil etme/hariç tutma seçeneklerini nasıl ekleyeceğinizi öğrenmek için belgelere göz atın.

Uygulama yeniden yüklendiğinde ve yeniden oluşturulduğunda ana paketin sıkıştırılmış bir sürümü oluşturulur. Node sunucusu tarafından sunulan nihai public/ dizininin içeriğine göz atmak için Glitch Console'u açın.

  • Araçlar düğmesini tıklayın.
  • Konsol düğmesini tıklayın.
  • Konsolda public dizinine gidip tüm dosyalarını görmek için aşağıdaki komutları çalıştırın:
cd public
ls

Herkese açık dizinde oluşturulan nihai çıkış dosyaları

Paketin sıkıştırılmış sürümü (main.bundle.js.gz) de buraya kaydedilir. CompressionPlugin, varsayılan olarak index.html'u da sıkıştırır.

Ardından, sunucuya orijinal JS sürümleri istendiğinde bu sıkıştırılmış dosyaları göndermesini söylemeniz gerekir. Bu, dosyalar express.static ile sunulmadan önce server.js içinde yeni bir rota tanımlayarak yapılabilir.

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, sunucuya belirli bir uç noktayla ilgili GET isteğine nasıl yanıt vereceğini bildirmek için kullanılır. Ardından, bu isteğin nasıl işleneceğini tanımlamak için bir geri çağırma işlevi kullanılır. Rota şu şekilde çalışır:

  • İlk bağımsız değişken olarak '*.js' belirtildiğinde bu, bir JS dosyası almak için tetiklenen her uç nokta için geçerli olur.
  • Geri çağırma içinde .gz, isteğin URL'sine eklenir ve Content-Encoding yanıt başlığı gzip olarak ayarlanır.
  • Son olarak next(), sıranın bir sonraki geri çağırma işlevine devam etmesini sağlar.

Uygulama yeniden yüklendikten sonra Network paneline tekrar göz atın.

Statik sıkıştırma ile paket boyutunu küçültme

Önceki gibi, paket boyutunda önemli bir düşüş elde ettik.

Sonuç

Bu kod laboratuvarında, kaynak kodunu küçültme ve sıkıştırma süreci ele alındı. Bu iki teknik de günümüzde mevcut olan birçok araçta varsayılan olarak kullanılıyor. Bu nedenle, araç zincirinizin bunları destekleyip desteklemediğini veya her iki süreci de kendiniz uygulamaya başlamanız gerekip gerekmediğini öğrenmeniz önemlidir.