Yeni Başlayanlar İçin Webpack : Part 1

Yağmur Mutluer
6 min readJan 24, 2022
Brett Jordan adlı kişinin Pexels’daki fotoğrafı

Bu yazı karşınıza çıktıysa webpack’i araştıranlardan biri olduğunuzu varsayıyorum. Önceden araştırıp anladığımı düşünsem de, tam olarak derinlemesine öğrenememiştim. Webpack for Beginners (Mohamed Bouzid) adlı kitap ise bu konuda en iyi kaynaklardan birisi. Bu kitaptan öğrendiklerimi iki parçada paylaşacağım.

İlk yazı

  • webpack nedir? neden ortaya çıkmış?
  • webpack’in kurulumu
  • ve loaders & pluginler hakkında olacak.

Webpack nedir?

Projenizdeki javascript dosyalarını ( css, resimler vb) paket haline getirip sunar.

Diyelim ki bir sayfa tasarlıyorsunuz, farklı javascript kütüphanelerine ihtiyaç duydunuz. Tek tek eklediniz, bazıları birbirine bağımlı olduğu için sırasına özel dikkat gösterdiniz. Ardından diğer sayfaları da eklediniz, bazı scriptler diğerlerini de içermeye başladı. Günün sonunda kontrolden çıkmış, bağımlılıklar birbirine girmiş bir proje ile karşı karşıyasınız. Ne yapacaksınız?

O halde webpack ile tanışalım. 🔫

Başlamadan önce bilgisayarınızda Node JS yüklü olmalı.

mkdir webpack-101 cd webpack-101npm init -y

webpack-101 adında bir proje oluşturup, package.json’ı da eklemiş olduk böylece.

Şimdi webpack’i yükleyelim.

npm install webpack webpack-cli --save-dev

( projenin çalışması için gerekli olanları save ile kaydederken, test ya da optimizasyon için kullandığımız, uygulamanın çalışmasında gerekli olmayanları save-dev ile ekliyoruz.)

src > 
> App.js
> index.html
> index.css
> index.js

olacak şekilde dosyaları oluşturalım.

// index.js
import React from "react"
import ReactDOM from "react-dom"
import App from "./App"

ReactDOM.render(<App />, document.getElementById("app"))
------// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<p> webpack learning...</p>
</body>
<body>

</body>
</html>

şimdilik index.js ve index.html’in içlerine bunları yazalım.

Şimdi webpack’e geçebiliriz.

4.0 versiyonu ile konfigürasyon gerektirmeden çalışabilen webpack’te kendimiz bir konfigürasyon oluşturmak istersek bu adımları takip edebiliriz.

Resmi sitesinde ve çoğunluk tarafından webpack.config.js isimlendirmesiyle kullanılmakta, biz de böyle kullanacağız.

module.exports = {
entry: "/src/index.js",
}

Entry

Webpack için bir başlangıç noktası gerekli. Buna entry demekteyiz. Entry dosyasından başlayıp, diğer dosyalar içine inerek bir dependency ağacı oluşturuyor. Böylece doğru bir sırada her şeyi yüklemiş oluyor. 🌳

Bunu anlamak için başlangıç noktamız olan index.js’e bakalım.

Webpack

ReactDOM.render(<App />, document.getElementById("app"))

ile işlemeye başlar. Uygulamayı çalıştırmak için kullanılan fonksiyon react-dom modülü bir dependency. App component’i ayrı bir yerden import edilmekte, bunu da dependency olarak işaretliyoruz. Son olarak App’i anlamak için ihtiyaç duyduğumuz react’ı da dependency olarak işaretliyoruz.

Bu üç dependency içinde diğerlerini de bulup, dallanmış bir ağaç elde ediyoruz. Tüm hepsini analiz etmesinin ardından resolve adımına geçiyoruz.

Not: Bazı kavramları İngilizce kullandığımın farkındayım fakat anlamını koruyacak şekilde Türkçeye nasıl çeviririm bilemedim. :)

Resolve

Webpack bu aşamada her dosyanın absolute path’ini çıkarmakta. Bunun için kendimiz de konfigürasyon ekleyebiliriz. Şimdilik extensions’ları ekliyoruz. Bu sayede otomatik bir şekilde dosyaların uzantısını webpack eklemiş olacak.

Resolve kısmını ikinci partta daha ayrıntılı inceleyeceğiz.

// webpack.config.js
module.exports = {
...
resolve: {
extensions: [".js", ".jsx"],
},
}

Typescript kullanıyorsanız “.ts/.tsx” de ekleyebilirsiniz. Fakat sadece bu ikisini ekleyip .js’i pas geçerseniz, webpack hata verir. Node modüllerinin çalışması için .js’in de olması gerek.

Output

Webpack’e sonucu nereye kaydetmesi gerektiğini söylemek için output’u kullanıyoruz. Burada node’un path modülünü kullanabiliriz.

Bulunduğumuz klasör ile dist adlı dosyayı birleştirip, bundle.js adı altında sonucu kaydediyoruz.

// webpack.config.js
const path = require("path");
module.exports = {
...
output: {
path: path.join(__dirname, "dist"),
filename: "bundle.js",
publicPath: "./",
},
}

Hemen hemen webpack’in temel halini böylece tamamlamış olduk. Şimdi bunu nasıl çalıştıracağız kısmına geldik.

Şimdilik tek html üzerinden gitme nedenimiz, react kısmını loaders içinde tamamlayıp çalıştıracağız.

Script

Package.json dosyasında, scripts altında bu iki scripti ekleyebiliriz.

Burada karşımıza iki yeni kavram çıkıyor. Biri watch diğeri de mode.

Değişiklikleri izlemek için watch ekleyebiliriz, geliştirirken böylece her defasında scripti çalıştırmamıza gerek kalmaz.

Mode seçeneğiyle development ya da production olduğunu webpack’e söyleriz. Production iken kodlar minified halde iken, development modda değildir.

"build": "webpack --mode production",
"build:watch": "webpack --mode development --watch",

Debug

Mode’a göre farklı devtool’lar kullanabiliriz. Development modunda hızlı build&rebuild seçeneklerini daha avantajlı.

https://webpack.js.org/configuration/devtool/

Bunları bu şekilde de ekleyebiliriz.

module.exports = {
mode: "development",
devtool: "cheap-module-eval-source-map",
watch: true,
}

Scripte geri dönersek webpack cli’ni kullanmamız için eklememiz gerekli.

npm install webpack-cli --save-dev

Artık script’i çalıştırdığımızda,

npm run build

webpack <Webpack version> compiled successfully in <execution time in ms>

mesajıyla birlikte dist dosyasının altında bundle.js’i görebilir ve mutlu olabiliriz. 😄

Loaders & Plugins

Webpack’in sihirli yanına gelmiş bulunmaktayız. Dosyaları başka bir formata geçirmek ya da oluşan sonucu optimize hale getirmek gibi konulara değineceğiz.

Loaders kaynak kodun nasıl yorumlanacağını, hangi forma çevirilmesi gerektiğini webpack’e açıklar.

Pluginler ise loader’ların yapamadığı her şeyi yapabilirler. Konfigürasyonu fonksiyonel bir hale getirip, optimize işlemlerini gerçekleştirirler.

Şimdi örneklere geçelim.

Babel Loader

Babel sıkça kullanılan ve bilinen loader’lardan biri. Amacı ES6 olan javascript’i ES5 haline çevirmek. Javascript’in yıllar içinde farklı versiyonları yayınlandı fakat bu versiyonlar aynı hızda tarayıcı tarafına geçmedi. ES6 tamamıyla desteklenmediğinden, bir önceki versiyona, ES5 haline geçmek gerek. Babel bunu bizim için yapmakta.

Öncelikle babel-loader’ı projeye ekleyelim.

npm install --save-dev babel-loader @babel/core @babel/preset-env

Google’da ‘webpack + loader/plugin ismi’ diye arattığınızda siz de istediklerinizi indirebilirsiniz.

Loader’ları eklemek için modül objesinin içerisindeki rules arrayını kullanıyoruz. Babel için bir rule eklemiş bulunmaktayız.

test: “/\.m?js$/” regular expressionı ile webpack’e eğer js ya da mjs varsa babel-loader’ı uygula der.

use kısmında loader’ın ismini ve eğer varsa opsiyonları varsa onları ekleriz.

module.exports = {
// ...
output: {
// ...
},
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
}

CSS Loaders

Webpack javascript yanında diğer dosya türlerinde de kullanılmakta. CSS için nasıl olduğuna bakalım. Bunun için stil dosyasının içinde background’ı değiştirelim.

Ardından index.js içerisinde import edelim.

import "./index.css";

Webpack css dosyaları için bir loader yüklenmediğini hata olarak gösterdi.

npm install css-loader — save-dev

Css loader’ı ekleyip ardından rule olarak ekleyebiliriz. Böylece webpack’e css dosyası gördüğünde onu tanıyabilmesini sağlamış olduk.

module: {
rules: [
{
test: /\.css$/i,
use: ['css-loader']
}
],
},

Sayfayı yenilediğimizde hatanın gittiğini fakat stilin uygulanmadığını fark edeceğiz. Yüklememiz gereken bir loader daha var.

npm install style-loader --save-dev

Style loader import edilmiş css dosyasını alıp style tagları içerisinde bunu yerleştirir.

{
test: /\.css$/i,
use: ['style-loader', 'css-loader']
}

Bu şekilde style loader’ı da ekledik. Burada sıra önemli. Sağdan sola gidecek şekilde kurallar uygulanıyor. Buna dikkat edelim.

Artık stili görebilmekteyiz. 🚀

Peki css dosyalarını ayrı olarak görmek istersek? Şu anda html içerisinde style tagları arasına yerleştirmekte webpack. Ayrıca asenkron css kullanmak istiyorsak da bunu düşünebiliriz. Ve “mini-css-extract-plugin” adlı plugin ile bunu gerçekleştirebiliriz.

Bu plugin css import etmiş olan her js dosyası adına bir css dosyası oluşturur.

npm install --save-dev mini-css-extract-plugin

Plugini indirdikten sonra webpack config dosyasının içerisinde şu şekilde kullanacağız.

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

CSS’in build olacağı dosyanın ismini argüman olarak veriyoruz. Vermezseniz de css dosyasının isminde build edecektir. Yine farklı argümanlar almakta, webpack dokümantasyonlarından bakabilirsiniz her biri için.

module.exports = {
...
plugins: [
new MiniCssExtractPlugin({
filename: 'application.css'
})
]
...

Kullandığımız loader’ı da güncelleyeceğiz.

{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}

Uygulamayı yeniden çalıştırdığımızda dist altında application.css’i görmüş olacağız böylece.

Photo by Alex Motoc on Unsplash

Umarım bu yazı faydalı olmuştur, ikinci partın ardından daha farklı loader&pluginlere de değineceğim. ✋

--

--