Webpack: Modül Paketleyici

Merhaba,

JavaScript çalışmalarımda sıkça kullandığım ve neredeyse JavaScript çatılarında kullanılması elzem paketlerden birisinin kullanımına dair elimden geldiğince Türkçe içerik oluşturmaya gayret edeceğim. Bu konuda Türkçe kaynak olmadığı için bazı terimlerin Türkçe kullanımında kararsız kaldım. Bu konuda yardımcı olursanız ve katkı gösterirseniz sevinirim.

Öncelikle, Webpack‘i nasıl tanımlarız? Şöyle yaklaşalım; elimizde birden fazla dizinde bulunan birden fazla modül bulunmakta. Bir JS dosyası, birden fazla JS dosyasını içerisine çağırıyor, çalıştırıyor ve HTML etiketine ilgili çıktıyı basıyor. Tüm bunlar olurken bir de CSS ve diğer modüller yükleniyor. Burada tarayıcının önyükleme süresinin ne denli arttığını ve şişmiş dosya boyutlarını fark ettiniz mi?

Evet, tam da burada Webpack; bizim kullanacağımız kısa açıklama tabiri ile Modül Paketleyicimiz devreye girmekte. Webpack, ilk olarak 2013’te Tobias Koppers tarafından oluşturulmuştur. Süregelen zamanda ekibe dört yeni kişi daha eklenmiş ve açık kaynak olarak geliştirilmeye devam etmiştir.

Peki, Webpack sadece kendisine gelen dağınık modülleri paketlemeye mi yarar? Buna dolaylı yoldan hayır cevabını verebilirim. Webpack‘e bağımlı aynı zamanda Webpack Dev Server paketini kullanmaktayız. Burada dikkat edilmesi gereken tek nokta sadece geliştirme ortamında kullandığımızdır. Kısaca bahsetmek gerekirse; geliştirme ortamında uygulamanızı hem paketler hem de sanal bir ortamda gerçek zamanlı olarak size sunar. Siz uygulamanızda değişiklikleri yaptığınızda ve her kaydettiğinizde paketler ve yeniden size sunar. Bu işlemi uyglamanız canlıda hizmet verdiğinizde Next JS gibi popüler server side render paketleri ile ya da Express JS ile çözebilirsiniz.

Bu yazının devamında Webpack kullanımıi eklentilerini ve örnek kod bloklarını inceleyeceğiz.

Başlangıç

JavaScript paketleri için kullanılan iki adet paket yöneticisi bulunmakta. Bunlar yarn ve npm olmak üzere ikiye ayrılmaktadırlar. Ben çalışma boyunca npm kullanarak devam edeceğim.

Linux kullanıcısı olduğum için Windows kullanan arkadaşlarlarımız farklı kaynaklardan da destek alsınlar ilerleme boyunca.

Uçbirimimizi açalım ve bir çalışma dizini, hemen ardından ise paket yapılandırma dosyamızı oluşturalım.

mkdir webpack-blog-ders
npm init -y
npm install --save-dev webpack

Ben Arch Linux kullandığım için bazı dizinlerde kullanıcı yetki hatası ile karşılaşıyorum. Eğer siz de yetki hatası alırsanız bunu çözmek için doğru kullanım şu şekilde olmalıdır:

sudo npm install --save-dev --unsafe-perm webpack

Bu adımları başarılı bir şekilde ilerledi iseniz dizininiz şu şekilde olmalıdır:  node_modules package.json package-lock.json

Merhaba!

├── node_modules
├── index.html
├── package.json
├── package-lock.json
└── src
├── css
│   └── style.css
└── js
├── app.js
└── domquery.js

Şimdi basit bir çalışma örneği gerçekleştireceğiz. Yukarıdaki dizin ağacını takip edebilirsiniz. Yine, projemizin ana dizininde src dizini oluşturalım ve js dizini içerisinde basit bir işlemi birden fazla dosya ile yapmaya çalışalım.

Bir domquer.js dosyası oluşturuyorum, HTML nesnemin seçilimi için.

export const domquery = document.querySelector('.w-learn');

Bir de app.js dosyası oluşturuyorum, HTML DOM textContent özelliğim ile ekrana veri bastırmak için.

import { domquery } from "./domquery";
domquery.textContent="Merhaba!";

Ve son olarak css dizinini oluşturuyorum ve style.css dosyamda ilgili nesneme basit bir özellik tanımlıyorum.

.w-learn{
color:red;
}

Ana dizinimde bulunan index dosyamı oluşturup güncelleyeceğim. Burada dikkat etmemiz gereken nokta buradaki JavaScript dosyalarını dist/bundje.js yolu ile çağırmamız. Yani, elimizde bulunan iki adet modülü paketleyeceğiz.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Webpack: Modül Paketleyici</title>
<link rel="stylesheet" href="src/css/style.css">
</head>
<body>
<h1 class="w-learn"></h1>
<script src="dist/bundle.js" charset="utf-8"></script>
</body>
</html>

Şimdi ise Webpack konfigüre adımına geldik. Burası önemli olan kısım. Yine ana dizinimizde bulunan package.json dosyamızı güncelleyeceğiz.

"scripts": {
"build": "webpack --entry ./src/js/app.js --output-filename ./dist/bundle.js"
},

Bir bakalım, ne yazdık biz? Uçbirimde npm run build komutu ile çalıştıracağımız bir komut uyarladık. Önce paketimin ismini yazdım. Hemen ardından giriş dosyam anlamına gelen entry parametresini tanımladım ve yolunu gösterdim. Bir de çıkış dosyamın dizinini ve hangi dosya ismi ile adlandırılacağını belirttim. Bir dist yolu olmasa da kendi oluşturacak ve güncelleyecektir. Burada kullanılan komut ve parametrelerin tamamına dökümandan ulaşabilirsiniz. Temel olarak package.json’da çalıştırılmak istenildiğinde kullanılan iki temel parametre bunlardır.

Uçbirimde npm run build diyerek proje dizinimde komutumu çalıştırıyorum.

> webpack-blog-ders@1.0.0 build /opt/lampp/htdocs/webpack-blog-ders
> webpack --entry ./src/js/app.js --output-filename ./dist/bundle.js
Hash: c560be31af2d1d1ebcd6
Version: webpack 3.8.1
Time: 69ms
Asset  Size  Chunks             Chunk Names
./dist/bundle.js  3 kB       0  [emitted]  null
[0] ./src/js/app.js 73 bytes {0} [built]
[1] ./src/js/domquery.js 60 bytes {0} [built]

Yukarıdakine benzer bir çıktı almanız gerek. Burada oluşturduğu dizide her eleman bizim bir modülümüze denk gelmektedir. Bu dizi bundle.js dosyasından incelenebilir.

Şimdi ise sanal sunucumda çalıştırıyorum.

Başarılı bir şekilde çalıştırdık. Şu an elimizde sadece iki adet modül var fakat React JS ya da diğer çatılarla çalıştığınızda ne kadar hayati olduğunu bir kez daha kavrayabileceksiniz. Buradaki CSS dosyamızı neden paketlemedik peki? Çünkü Webpack sadece JavaScript dosyaları üzerinde çalışır. Bunun dışında tüm farklı modüller için Webpack eklentilerini kullanacağız.

Peki, bundle.js dosyamı canlı bir çalışmada kullandığım zaman sıkıştırılmasını isterim ben. Bunu nasıl yapacağım? Muhtemelen pretty’den gelen -p parametresi ile.

"scripts": {
"build": "webpack --entry ./src/js/app.js --output-filename ./dist/bundle.js -p"
},

Tekrar çalıştırıyorum.

> webpack-blog-ders@1.0.0 build /opt/lampp/htdocs/webpack-blog-ders
> webpack --entry ./src/js/app.js --output-filename ./dist/bundle.js -p
Hash: 2e07e765e0eae342c668
Version: webpack 3.8.1
Time: 103ms
Asset       Size  Chunks             Chunk Names
./dist/bundle.js  651 bytes       0  [emitted]  null
[0] ./src/js/app.js 75 bytes {0} [built]
[1] ./src/js/domquery.js 60 bytes {0} [built]

Ve, mutlu son. Bundle JS dosyamın boyutunun küçüldüğünü görebiliyorum.

Webpack Dev Server

Evet, bundan daha önce söz etmiştim. Webpack Dev Server, geliştirme ortamında bizlere sanal sunucu ortamı sunmaktadır. Şimdi çalışmamıza dahil edelim.

npm install --save-dev webpack-dev-server

Yukarıdaki komut ile çalışma dizinimize ilgili paketi tanımlayalım. Bu gibi yerel dizinde çalışıldığında daha verimli olabilecek paketleri global olarak yüklememeye özen gösterelim. GitHub’ta ya da bir takım çalışmasında yereldeki package.json dosyanızda gözükmeyen paketler farklı makinalarda çalışmayacaktır.

Bakıyorum, paket bağımlılıklarım güncellenmiş.

"devDependencies": {
"webpack": "^3.8.1",
"webpack-dev-server": "^2.9.3"
}

Şimdi build komutumuzu güncelleyelim.

"scripts": {
"build": "webpack-dev-server --entry ./src/js/app.js --output-filename ./dist/bundle.js"
},

Ve çalıştıralım.

npm run build

Şu an 8080 portumda proje sorunsuz çalışmakta. Tabir-i caizse; koşmakta, ayakta.

Çekirdek Kavramları

Şimdiye kadar package.json’da modül girişini ve paket çıkışını belirttik sadece. Peki, diğer eklentileri kullanmak için ve farklı konfigüre işlemleri için ne yapacağız? Cevap basit!

Çalışmamızın ana dizininde webpack.config.js oluşturuyorum.

module.exports = {
entry: './src/js/app.js',
output: {
filename: 'bundle.js',
path: __dirname + '/dist'
}
}

Burada komutlar tanıdık gelmiştir umarım. Entry, yine modülümüzün giriş nokta. Bu kullandığınız yapı dökümanda single entry olarak geçmekte. Birden fazla modül girişini dizi olarak da tanımlayabilirsiniz. Yine bir çıkış noktamız var paketleyicimiz için. Yol ve dosya ismi ile onu da tamamlıyoruz.

Tekrar package.json dosyamızda build komutumuzu güncelleyelim.

"scripts": {
"build": "webpack -p"
},

Ve tekrar çalıştıralım.

npm run build

Yeniden paketledi ve ekrana çıktımızı verdi.

Bizim bir de CSS dosyamız vardı. Şimdi, CSS’imizi de paketleyelim. Hemen hatırlıyoruz, Webpack yalnızca JS üzerinde çalışır. Peki, bunun için ne yapıyorduk? Eklenti kullanıyorduk, evet.

CSS (Sitil) Kullanımı

Yüklememiz gereken iki adet temel paket bulunmakta. Bunlar css-loader ve style-loader dir.

npm install style-loader css-loader --save-dev

Şimdi ise Webpack dosyamı güncelliyorum.

{
// ...
module: {
loaders: [
{ test: /\.css$/, loader: "style-loader!css-loader" }
]
}
}

Burada seçici dosya uzantım CSS ve yükleyicilerim style-loader ve css-loader burada paketlerin yazım sırası da büyük önem arz etmektedir.

Ana dizinimizde bulunan index dosyamızda statik olarak içe aktardığımız CSS linkini yorum satırı ile geçersiz hale getiriyorum.

  <!--<link rel="stylesheet" href="src/css/style.css">-->

Src dizinimde bulunan App JS dosyasına CSS’i içe aktarıyorum.

import "../css/style.css"

Çalıştırıyorum…

npm run build

Ve yeniden ekrana çıktımızı bastı, hem de CSS dosyalarımızı da paketleyerek.

Sonuç

Yavaştan sonuca doğru gelelim diyorum. Webpack’in bir diğer kullanım alanları ise resimlerin paketlenmesi. File Loader paketini kullanarak basit bir şekilde bunu da çözebilirsiniz. Babel ve SCSS kullanımına dair örneklere de yine erişebilirsiniz. Ben temel olarak Webpack mimarisini ve işlevini anlatan basit bir anlatım gerçekleştirmek istedim. Yukarıda ilgili başlıkların altında yer verdiğim GitHub bağlantılarında doğru dalı seçmeyi unutmayınız.

Kaynak ve İleri Okuma

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir