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

Bu codelab'de, aşağıdaki uygulama için 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ğini incelenmektedir.

Uygulama ekran görüntüsü

Ölçüm

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

  • Siteyi önizlemek için Uygulamayı Göster'e, ardından Tam Ekran'a tam ekran basın.

"Kullanılmayan kodu kaldırma" codelab'inde de ele alınan bu uygulama, favori yavru kedinize oy vermenize olanak tanır. 🐈

Şimdi bu uygulamanın büyüklüğüne bir bakın:

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

Ağ panelindeki orijinal paket boyutu

Bu paket boyutunu küçültmek için "Kullanılmayan kodu kaldırın" codelab'inde büyük ilerleme kaydedilmiş olsa da 225 KB hâlâ oldukça büyük bir boyuttur.

Küçültme

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 elde edilen kod aşağıdaki gibi görünür:

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

Dosya boyutu şimdi yaklaşık 83 B olur. Değişken adının uzunluğu azaltılarak ve bazı ifadeler değiştirilerek daha da karışırsa son kod aşağıdaki gibi görünebilir:

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

Dosya boyutu artık 62 B'ye ulaşır.

Her adımda, kodun okunması zorlaşmaktadır. Ancak, tarayıcının JavaScript motoru, bunların her birini tam olarak aynı şekilde yorumlar. Kodun bu şekilde kod karartması, dosya boyutunu küçültmenize yardımcı olabilir. 112 B başlangıç için pek fazla bir değer değildi, ancak boyutta bir %50 küçülme vardı!

Bu uygulamada webpack sürüm 4, modül paketleyici olarak kullanılır. Özel sürümü package.json adresinde görebilirsiniz.

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

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

Küçültülmüş kodun nasıl göründüğü hakkında fikir edinmek için Geliştirici Araçları panelinden main.bundle.js işaretini tıklayın. Şimdi Yanıt sekmesini tıklayın.

Küçültülmüş yanıt

Kod, küçültülmüş ve karıştırılmış hâlde son haliyle yanıt gövdesinde gösterilir. Paket küçültülmemiş olsaydı paketin 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 paket boyutu

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

Devam etmeden önce burada yapılan değişiklikleri geri aldığınızdan emin olun.

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

Uygulamanızda kodu küçültme işleminin dahil edilmesi, kullandığınız araçlara bağlıdır:

  • Webpack v4 veya sonraki sürümler kullanılıyorsa, üretim modunda kod varsayılan olarak küçültüldüğünden ek işlem yapılması gerekmez. 👍
  • Webpack'in eski bir sürümü kullanılıyorsa TerserWebpackPlugin öğesini yükleyin ve web paketi derleme işlemine dahil edin. Belgelerde bu durum ayrıntılı olarak açıklanmaktadır.
  • Bunun yerine, BabelMinifyWebpackPlugin ve ClosureCompilerPlugin gibi başka küçültme eklentileri de mevcuttur ve kullanılabilir.
  • Bir modül paketleyici hiç kullanılmıyorsa KSA aracı olarak Terser'ı kullanın veya doğrudan bağımlılık olarak ekleyin.

Sıkıştırma

Küçültme sürecinde kodun nasıl azaltıldığını açıklamak için bazen "sıkıştırma" terimi genel olarak kullanılsa da gerçekte tam anlamıyla 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. Tamamen geçerli bir kod sağlayan küçültmenin aksine, sıkıştırılmış kodun kullanılmadan önce sıkıştırması açılmalıdır.

Her HTTP isteği ve yanıtında tarayıcılar ve web sunucuları, getirilen veya alınan öğe hakkında ek bilgi eklemek için headers ekleyebilir. Bu, DevTools Network (Ağ) panelindeki Headers sekmesinde üç tür gösterilir:

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

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

Kodlama başlığını kabul et

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

  • Gzip (gzip): Sunucu ve istemci etkileşimleri için en yaygın kullanılan sıkıştırma biçimi. Deflate algoritmasını temel alır ve mevcut tüm tarayıcılarda desteklenir.
  • Söndür (deflate): Yaygın olarak kullanılmaz.
  • Brotli (br): Sıkıştırma oranlarını daha da iyileştirerek sayfaların daha da hızlı yüklenmesini sağlamayı amaçlayan yeni bir sıkıştırma algoritması. Ç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 incelenecektir.

Dinamik sıkıştırma

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

Artıları

  • Öğelerin kaydedilmiş sıkıştırılmış sürümlerini oluşturma ve güncelleme işlemlerinin yapılması gerekmez.
  • Anında 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ı öğelerin sunucu tarafından gönderilmeden önce sıkıştırılmasını beklerken bir performans isabetine neden olabilir.

Düğüm/Ekspres ile dinamik sıkıştırma

server.js dosyası, uygulamayı barındıran Düğüm sunucusunu kurmaktan 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 tüm bu işlem, express dosyasını içe aktarmak ve public/ dizinindeki tüm statik HTML, JS ve CSS dosyalarını yüklemek için express.static ara katman yazılımını kullanmaktır (ve bu dosyalar her derlemede webpack tarafından oluşturulur).

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

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

Ve bu değeri sunucu dosyasına (server.js) aktarın:

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

Ayrıca, express.static eklenmeden önce bunu bir ara katman 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'tan 61,6 KB'a! Şimdi Response Headers içindeki content-encoding üst bilgisi, sunucunun bu dosyayı gzip ile kodlanmış olarak gönderdiğini gösterir.

İçerik kodlama başlığı

Statik sıkıştırma

Statik sıkıştırmanın amacı, öğelerin önceden sıkıştırılarak zamandan tasarruf edilmesini sağlamaktır.

Artıları

  • Yüksek sıkıştırma seviyelerinden kaynaklanan gecikme artık sorun değil. Sıkıştırma işlemi sırasında dosyalar doğrudan alınabileceğinden, anında sıkıştırı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ın önceden sıkıştırılmasını gerektirdiğinden web paketi ayarları, derleme adımının bir parçası olarak öğeleri sıkıştıracak şekilde değiştirilebilir. Bunun için CompressionPlugin kullanılabilir.

package.json alanına devDependency olarak ekleyerek başlayın:

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

Diğer tüm web paketi eklentileri gibi, bu eklenti de yapılandırma dosyasına webpack.config.js: içe aktarın.

const path = require("path");

//...

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

Ve bunu plugins dizisine ekleyin:

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

Varsayılan olarak eklenti, derleme dosyalarını gzip kullanarak sıkıştırır. Farklı bir algoritma kullanmak veya belirli dosyaları dahil etmek/hariç tutmak amacıyla nasıl seçenek ekleyeceğinizi öğrenmek için belgelere göz atın.

Uygulama yeniden yüklenip yeniden oluşturulduğunda ana paketin sıkıştırılmış bir sürümü oluşturulur. Düğüm sunucusu tarafından sunulan son public/ dizininde ne olduğuna bakmak için Glitch Console'u açın.

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

Ortak dizinde çıktısı son dosyalar

Paketin gzip'lenmiş sürümü olan main.bundle.js.gz artık buraya da kaydedildi. CompressionPlugin ayrıca varsayılan olarak index.html sıkıştırır.

Yapılması gereken bir sonraki şey, sunucuya orijinal JS sürümleri istendiğinde bu gzip biçiminde sıkıştırılmış dosyaları göndermesini söylemektir. Bu işlem, dosyalar express.static ile sunulmadan önce server.js içinde yeni bir rota tanımlanarak 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ç nokta için GET isteğine nasıl yanıt vereceğini bildirmek için kullanılır. Daha sonra, 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' belirtilmesi, bunun bir JS dosyası getirmek üzere tetiklenen her uç nokta için kullanılacağı anlamına gelir.
  • Geri çağırmaya .gz, isteğin URL'sine eklenmiş ve Content-Encoding yanıt başlığı gzip olarak ayarlanmıştır.
  • Son olarak next(), sıranın bir sonraki geri çağırmaya devam etmesini sağlar.

Uygulama yeniden yüklendikten sonra Network paneline bir kez daha bakın.

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

Daha önce olduğu gibi, paket boyutunda önemli bir küçülme!

Sonuç

Bu codelab'de, kaynak kodu küçültme ve sıkıştırma süreci ele alınmıştır. Bu tekniklerin her ikisi de günümüzde kullanılan araçların çoğunda varsayılan haline gelmektedir. Bu nedenle araç zincirinizin bunları zaten destekleyip desteklemediğini veya her iki süreci de kendiniz uygulamaya başlamanız gerekip gerekmediğini öğrenmek önemlidir.