22 Ekim 2025 Çarşamba

WebAuthn ve Passkey ile Parolasız Kimlik Doğrulama: Next.js + Node.js ile Uçtan Uca Kurulum

Giriş

Parolalar bitmek bilmeyen bir güvenlik ve kullanıcı deneyimi sorunu. WebAuthn ve Passkey (FIDO2) standartları, hem güvenliği artıran hem de kullanıcıyı zahmetten kurtaran parolasız kimlik doğrulama sunuyor. Bu yazıda, Next.js ve Node.js kullanarak uçtan uca bir WebAuthn akışını nasıl kuracağınızı adım adım anlatıyorum. Hem modern tarayıcı desteğini, hem de üretim ortamında dikkat edilmesi gerekenleri ele alacağız.

WebAuthn ve Passkey Nedir?

WebAuthn, W3C ve FIDO Alliance tarafından geliştirilen, tarayıcı üzerinden güvenli anahtar tabanlı kimlik doğrulama standardıdır. Passkey ise kullanıcıların cihazlarında saklanan ve bulut üzerinden senkronize olabilen (Apple iCloud, Google Password Manager vb.) WebAuthn kimlik bilgileridir. Kısaca: kullanıcı, parolaya gerek duymadan cihaz biyometrisi (Face ID, Touch ID, Windows Hello) veya güvenlik anahtarı (YubiKey) ile giriş yapar.

Kavramsal olarak iki akış var: Kayıt (Registration) ve Giriş (Authentication). Sunucu, benzersiz bir challenge üretir; tarayıcıda navigator.credentials.create() veya navigator.credentials.get() çağrıları yapılır; elde edilen yanıt sunucu tarafından doğrulanır. Doğrulama sonrası, kullanıcı artık parolasız giriş yapabilir.

Mimari Özeti

- Relying Party (RP): Uygulamanızın alan adıyla tanımlanır (ör. rpId: "ornek.com"). Bu değer kök alan adınız olmalıdır.

- Attestation ve Assertion: Kayıtta attestation, girişte assertion doğrulanır. Üretimde çoğunlukla attestation: "none" kullanılır.

- Depolama: Kamu anahtarı, credential ID ve counter gibi veriler sunucuda saklanır. Challenge için kısa süreli bir önbellek (Redis) önerilir.

Ön Koşullar

- Next.js 14+ (App Router önerilir), Node.js 18+.

- HTTPS zorunlu (geliştirmede localhost hariç). Üretimde gerçek bir alan adıyla test edin.

- Kütüphaneler: @simplewebauthn/server ve @simplewebauthn/browser. Bu ikili, challenge üretimi ve doğrulama işini hataya yer bırakmadan kolaylaştırır.

Adım 1: Projeyi Hazırlayın

Next.js projesini oluşturun ve bağımlılıkları kurun: npm i @simplewebauthn/server @simplewebauthn/browser. App Router ile app/api altında dört endpoint planlayın: /webauthn/register/options, /webauthn/register/verify, /webauthn/login/options, /webauthn/login/verify.

Sunucu tarafında yapılandırma için değişkenleri belirleyin: rpName, rpID (alan adınız), origin (ör. https://app.ornek.com). Bu üçü birbirine tam uyumlu olmalıdır; aksi halde tarayıcı doğrulamayı reddeder.

Adım 2: Kayıt (Registration) Akışı

1) Options üretimi: Sunucu, oturumu açık kullanıcının (ör. user.id, user.name) bilgileriyle generateRegistrationOptions çağırır. attestation: "none", authenticatorSelection için residentKey: "preferred" ve userVerification: "preferred" yeterlidir.

2) Challenge saklama: Dönen options.challenge değerini kullanıcının oturumuna veya Redis’e yazın. Bu değer tek kullanımlık ve kısa ömürlü olmalıdır.

3) İstemci işlem: Tarayıcıda startRegistration(options) veya yerel API ile navigator.credentials.create({ publicKey: options }) çağırın. Kullanıcı, cihaz biyometrisiyle onaylar ve bir attestation yanıtı oluşur.

4) Doğrulama: Yanıt sunucuya gönderilir ve verifyRegistrationResponse ile doğrulanır. Başarılıysa credentialID, publicKey, counter, transports gibi alanları veritabanına kaydedin.

Not: Binary verilerin JSON’a taşınmasında base64url dönüşümleri gerekir. @simplewebauthn bu dönüşümleri kolaylaştırır; farklı bir yaklaşım kullanıyorsanız, ArrayBuffer ↔ base64url dönüşümleri için tutarlı yardımcı fonksiyonlar geliştirin.

Adım 3: Giriş (Authentication) Akışı

1) Options üretimi: Sunucu generateAuthenticationOptions ile yeni bir challenge üretir. Dilerseniz sadece kullanıcıya ait allowCredentials listesi dönebilir veya passkey’lerin “discovered” kullanımına izin vermek için boş da bırakabilirsiniz.

2) İstemci işlem: Tarayıcıda startAuthentication(options) ya da navigator.credentials.get({ publicKey: options }) çağrılır. Kullanıcı biyometrik onayı verir.

3) Doğrulama: Sunucu, verifyAuthenticationResponse ile yanıtı doğrular; counter değerini günceller ve başarılıysa oturum veya token üretir (HTTP only, SameSite=Strict bir çerez önerilir).

Güvenlik ve Üretim İpuçları

- Origin ve rpID eşleşmesi: origin tam URL, rpID kök alan adı olmalı. https://login.ornek.com ile rpID: "ornek.com" uyumludur.

- HTTPS zorunlu: Geliştirme dışında güvenli olmayan kökenlerde WebAuthn çalışmaz.

- Attestation politikası: Kurumsal cihaz kökenini doğrulamak gerekmiyorsa none en pratik seçenek.

- Kullanıcı doğrulaması: userVerification: "required" güvenliği artırır; deneyim açısından “preferred” daha esnek olabilir.

- Passkey senkronizasyonu: Çok cihazlı deneyim için kullanıcıya aynı ekosistemde (iCloud / Google) senkronizasyonu etkinleştirmesini anlatın.

- Conditional UI: Chrome’da parolasız “otomatik” akış için navigator.credentials.get({ mediation: "conditional" }) ve ilgili bayrakları düşünün.

- Geri dönüş: İlk aşamada SMS/e-posta yedek yöntem bulundurun ancak uzun vadede phishing’e dayanıklı seçeneklere yönelin.

Sık Karşılaşılan Hatalar

- NotAllowedError: Kullanıcı akışı iptal etti veya tarayıcı UI zaman aşımına uğradı. Zaman aşımını düşürün ve açık geri bildirim gösterin.

- InvalidStateError: Aynı cihazda aynı kullanıcı için tekrar kayıt yapılmak isteniyor olabilir. Kayıt öncesi kullanıcıya mevcut passkey’leri gösterip yönetin.

- RP ID uyuşmazlığı: Alt alan adı/Origin ve rpID yanlış ayarlandığında doğrulama başarısız olur. Üretim alan adınızla birebir test edin.

Dağıtım ve Sonuç

Uygulamayı dağıtırken, ters proxy (Nginx) üzerinden HTTP → HTTPS zorlaması yapın. Load balancer arkasında gerçek istemci IP’sini günlüğe almak için X-Forwarded-For başlığını doğru iletin. CDN veya WAF kullanıyorsanız WebAuthn isteklerinin gövde boyutu ve header’larını kısıtlamadığından emin olun.

Sonuç olarak, WebAuthn ve Passkey ile Next.js + Node.js üzerinde parolasız kimlik doğrulama kurmak düşündüğünüzden daha erişilebilir. Doğru rpID/origin eşleşmesi, sağlam challenge saklama, güvenli çerez ayarları ve iyi bir kullanıcı akışı ile hem güvenlik seviyenizi yükseltir hem de dönüşüm oranlarını artırırsınız. Bugün basit bir kayıt/giriş prototipi hazırlayıp ekibinizle birlikte deneyin; parolaları geride bırakma vakti geldi.

3.

21 Ekim 2025 Salı

Yerel LLM Kurulumu: Ollama ve Open WebUI ile Hızlı ve Güvenli Yapılandırma Rehberi

Giriş: Neden Yerel LLM?

Gizlilik, düşük gecikme ve maliyet kontrolü, büyük dil modellerini (LLM) yerelde çalıştırmanın en önemli avantajları. Bu rehberde, açık kaynak ekosistemde hızla popülerleşen Ollama ile modelleri nasıl indireceğinizi ve Open WebUI üzerinden nasıl yöneteceğinizi adım adım göstereceğim. Amaç, teknik bariyeri düşük tutarak pratik bir kurulum sağlamak ve GPU hızlandırma, belge tabanlı arama (RAG) gibi ileri kullanım senaryolarına hızlıca geçebilmek.

Ön Koşullar ve Mimari

Ollama; macOS’ta Metal, Linux’ta CUDA/ROCm, Windows’ta DirectML/CUDA (uyum durumuna göre) ile çalışır. Open WebUI, Ollama’nın sunduğu yerel API’ye (varsayılan http://localhost:11434) bağlanarak tarayıcı tabanlı bir arayüz sunar. İkisini tek makinede koşturabilir, Docker ile izole edebilir veya sunucuya taşıyabilirsiniz.

Kurulum: Ollama

macOS: Homebrew ile brew install ollama komutunu çalıştırın. Ardından ollama serve ile servisi başlatın. Apple Silicon’da GPU hızlandırma otomatik devreye girer.

Linux: Terminalde curl -fsSL https://ollama.com/install.sh | sh komutunu çalıştırın. NVIDIA GPU için sürücü ve CUDA kurulumu yaptığınızdan emin olun. Servisi systemctl enable --now ollama ile kalıcılaştırabilirsiniz.

Windows: Resmi .msi yükleyicisiyle kurulum yapın. Ollama Tray ile servis başlatılabilir. GPU hızlandırma için güncel sürücüler ve desteklenen backend gereklidir.

İlk Modeli İndirme ve Çalıştırma

Popüler ve hızlı bir başlangıç için ollama pull llama3:8b veya ollama pull mistral:7b komutlarını kullanın. Ardından ollama run llama3:8b diyerek etkileşime geçin. Soruları terminalden yazabilir veya REST API ile programatik çağrılar yapabilirsiniz.

API örneği: curl http://localhost:11434/api/generate -d '{"model":"llama3:8b","prompt":"Merhaba, bugünün tarihi?"}'. Yanıtlarda gecikme görürseniz daha düşük quantizasyon (ör. q4_K_M) indirmeyi değerlendirin.

Open WebUI ile Grafik Arayüz

Open WebUI, sohbet geçmişi, çoklu model, belge ekleme ve RAG gibi özellikleri tek ekranda sunar. Docker ile hızlı kurulum için iki konteyner yeterlidir.

Ollama (Docker): docker run -d --name ollama -p 11434:11434 --gpus all -v ollama:/root/.ollama ollama/ollama

Open WebUI: Linux’ta Ollama’ya erişim için host gateway ekleyin: docker run -d --name open-webui -p 3000:8080 --add-host=host.docker.internal:host-gateway -e OLLAMA_API_BASE_URL=http://host.docker.internal:11434 -v open-webui:/app/backend/data open-webui/open-webui:latest

Windows/macOS’ta genellikle host.docker.internal otomatik çalışır. Tarayıcıdan http://localhost:3000 adresine giderek arayüze ulaşabilirsiniz.

RAG: Belgelerle Akıllı Yanıtlar

Open WebUI içinde “Knowledge” veya “Documents” bölümünden PDF, Markdown, TXT gibi belgeleri ekleyebilir ve indeksleyebilirsiniz. Ardından sohbet penceresinde ilgili bilgi tabanını seçtiğinizde model, cevaplarını bu içeriklere dayandırır. Küçük veri kümelerinde arama oldukça hızlıdır; büyük koleksiyonlarda bellek yükünü azaltmak için daha düşük boyutlu modeller ve hafif embedding’ler tercih edin.

Performans ve İnce Ayar

- Quantization: q4 varyantları RAM ve VRAM kullanımını düşürür; kalite/akıcılık dengesi için q5 veya q6 deneyin.
- İş Parçacığı: OLLAMA_NUM_PARALLEL ile eşzamanlı istek sayısını, --num-ctx ile bağlam penceresini ayarlayın.
- GPU Paylaşımı: Birden fazla model kullanıyorsanız aynı anda çalıştırmak yerine sıraya almayı tercih edin. GPU belleği dolarsa CPU’ya düşerek performans keskin biçimde azalabilir.
- Model Seçimi: Kod tamamlama için “Coder” varyantları; uzun bağlam gerektiren işlerde “Instruct” ve geniş context pencereli sürümler daha verimlidir.

Güvenlik ve Ağ Erişimi

Ollama’nın API’sini dış dünyaya açacaksanız bir ters vekil (ör. Caddy, Nginx) arkasında temel kimlik doğrulama uygulayın. Ev ağı senaryosunda sadece localhost’a bağlayın ve 11434 portunu yönlendirmeyin. Open WebUI kullanıcı hesapları oluşturmanıza izin verir; rol tabanlı erişimle modellerin kimler tarafından kullanılabileceğini sınırlayın.

Sorun Giderme

- Yavaş yanıt: Daha küçük modeli veya düşük quantizasyonu deneyin; CPU moduna düşmediğinizden emin olun.
- GPU tanınmıyor: Sürücü/CUDA güncellemelerini kontrol edin. Docker’da --gpus all bayrağı ve NVIDIA Container Toolkit gereklidir.
- Bağlantı hatası: Open WebUI’de OLLAMA_API_BASE_URL değerini ve ağ köprüsünü doğrulayın; Linux’ta --add-host parametresini eklemeyi unutmayın.
- Disk doluyor: Kullanmadığınız modelleri ollama rm model-adı ile kaldırın; hacim boyutlarını düzenli izleyin.

Sonuç

Ollama + Open WebUI ikilisiyle yerel LLM deneyimi, hem bireysel üretkenlik hem de kurumsal prototipleme için güçlü bir zemin sunuyor. Kurulum basit, yönetim pratik ve maliyet öngörülebilir. Başlangıçta hafif bir modelle ilerleyip ihtiyaçlara göre ölçeklendirmek, GPU kaynaklarını dikkatle planlamak ve güvenlik katmanlarını erken eklemek uzun vadede en sağlıklı yaklaşım olacaktır.

20 Ekim 2025 Pazartesi

Traefik v3 ile Docker Compose Üzerinde Çoklu Alan Adı ve Otomatik SSL: Adım Adım Rehber

Bir sunucuda birden fazla web uygulamasını farklı alan adlarıyla güvenli (HTTPS) şekilde yayınlamak istiyorsanız, modern bir ters proxy çözümü olan Traefik v3 harika bir seçenek. Bu rehberde, Docker Compose kullanarak Traefik v3 ile otomatik Let’s Encrypt sertifika yönetimini, HTTP’den HTTPS’e yönlendirmeyi ve birden fazla alan adını tek yapılandırmada yönetmeyi adım adım göstereceğim.

Traefik v3 nedir ve neden tercih edilmeli?

Traefik v3, konteyner tabanlı mimariler için optimize edilmiş, otomatik keşif ve sade etiketleme (label) mantığıyla çalışan bir ters proxy ve yük dengeleyicidir. Docker, Kubernetes ve diğer sağlayıcılarla derin entegrasyon sunar. v3 sürümü, performans ve yapılandırma deneyiminde iyileştirmeler getirirken, Let’s Encrypt ile otomatik TLS/SSL sertifikalandırmayı pratik hale getirir.

Ön koşullar ve DNS

- Bir Linux sunucu (Ubuntu/Debian/CentOS vb.)

- Docker ve Docker Compose kurulu

- Alan adınızda, sunucunuzun IP adresine işaret eden A/AAAA kayıtları (örnek: app.example.com ve traefik.example.com)

İpucu: Cloudflare kullanıyorsanız ve HTTP-01 doğrulaması yapacaksanız, ilgili DNS kaydını “DNS only” (turuncu bulut kapalı) olarak ayarlayın; aksi halde Let’s Encrypt doğrulaması başarısız olabilir.

Adım 1: Docker ağı ve klasörler

Aşağıdaki ağ, farklı Compose dosyaları arasında servisleri paylaşmanızı sağlar. Oluşturun:

docker network create web
mkdir -p traefik/letsencrypt
touch traefik/letsencrypt/acme.json
chmod 600 traefik/letsencrypt/acme.json

Adım 2: Traefik v3 için docker-compose.yml

Aşağıdaki dosya, Traefik’i 80/443 portlarına bağlar, Let’s Encrypt’i HTTP-01 ile etkinleştirir, HTTP’yi otomatik olarak HTTPS’e yönlendirir ve güvenli bir kontrol paneli kurar. E-postayı ve alan adlarını kendinize göre düzenlemeyi unutmayın.

version: "3.8"

services:
  traefik:
    image: traefik:v3.0
    container_name: traefik
    command:
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --entrypoints.web.http.redirections.entrypoint.to=websecure
      - --entrypoints.web.http.redirections.entrypoint.scheme=https
      - [email protected]
      - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
      - --certificatesresolvers.letsencrypt.acme.httpchallenge=true
      - --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
      - --api.dashboard=true
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik/letsencrypt:/letsencrypt
    networks:
      - web
    labels:
      - "traefik.enable=true"
      # Dashboard için güvenli router
      - "traefik.http.routers.api.rule=Host(`traefik.example.com`)"
      - "traefik.http.routers.api.service=api@internal"
      - "traefik.http.routers.api.entrypoints=websecure"
      - "traefik.http.routers.api.tls.certresolver=letsencrypt"
      # Basit BasicAuth middleware (parolayı hashleyip $$ ile kaçırın)
      - "traefik.http.middlewares.basicauth.basicauth.users=admin:$$2y$$12$$REPLACE_WITH_YOUR_BCRYPT_HASH"
      - "traefik.http.routers.api.middlewares=basicauth@docker"

  # Örnek uygulama
  whoami:
    image: traefik/whoami
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`app.example.com`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls.certresolver=letsencrypt"
    networks:
      - web

networks:
  web:
    external: true

Bu dosyada iki önemli nokta var: “exposedbydefault=false” etiketsiz konteynerların dış dünyaya açılmasını engeller; “http redirections” ise tüm HTTP trafiğini otomatik olarak HTTPS’e taşır. Dashboard’ı traefik.example.com üzerinden basit bir BasicAuth ile koruyoruz. Parola hash’ini üretmek için şu komutlardan birini kullanabilirsiniz:

# OpenSSL ile bcrypt:
htpasswd -nbB admin SIFRENIZ

# Ya da Python:
python3 -c "import bcrypt; print(b'admin:' + bcrypt.hashpw(b'SIFRENIZ', bcrypt.gensalt()))"

Elde ettiğiniz hash’i compose dosyasına yapıştırırken $ karakterlerini $$ ile kaçırın; aksi halde Compose bunu çevresel değişken sanacaktır.

Adım 3: Servis ekleme ve çoklu alan adı

Yeni bir servis eklemek için ilgili konteynere “traefik.enable=true” etiketi ve “rule=Host(`sub.example.com`)" kuralı tanımlayın. Her servis için ayrı router, entrypoint ve TLS resolver atayabilirsiniz. Örneğin bir Node.js uygulaması için:

myapp:
  image: node:20-alpine
  working_dir: /app
  command: ["node", "server.js"]
  volumes:
    - ./myapp:/app
  labels:
    - "traefik.enable=true"
    - "traefik.http.routers.myapp.rule=Host(`api.example.com`)"
    - "traefik.http.routers.myapp.entrypoints=websecure"
    - "traefik.http.routers.myapp.tls.certresolver=letsencrypt"
  networks:
    - web

Statik dosya sunucuları, PHP-FPM arkasındaki Nginx veya Go/Rust uygulamaları da benzer şekilde etiketlenir. Tüm servisler aynı “web” ağına bağlı oldukça Traefik onları otomatik keşfeder.

Güvenlik ve en iyi uygulamalar

- Dashboard’ı mutlaka alt alan adı ve BasicAuth (veya IP kısıtlaması) ile koruyun.

- “acme.json” dosyasını 600 izinleriyle saklayın; sertifika anahtarları bu dosyada tutulur.

- Gereksiz portları açmayın; yalnızca 80 ve 443 çoğu kurulum için yeterlidir.

- Üretimde otomatik yeniden başlatma politikası (“restart: unless-stopped”) kullanabilirsiniz.

Sık karşılaşılan hatalar ve çözümler

- Sertifika alınamadı: DNS kayıtlarınız doğru mu? Cloudflare “proxied” açık mı? HTTP-01 için kapalı olmalı. Alternatif olarak DNS-01 challenge kullanarak wildcard (*.example.com) alabilirsiniz.

- 80/443 dinlenemiyor: Sunucuda bu portları kullanan farklı bir servis (ör. Nginx) çalışıyor olabilir. Kapatın veya taşıyın.

- Rate limit: Let’s Encrypt test sırasında üretim yerine staging sunucularını deneyin. Traefik için “acme.caserver” parametresiyle staging’e geçebilirsiniz.

- “acme.json permission denied”: Dosya izinlerini 600 yapın ve doğru mount yolunu kontrol edin.

Sonuç

Traefik v3 ve Docker Compose ile çok sayıda servisi tek bir sunucu üzerinde, otomatik SSL ve modern yönlendirme yetenekleriyle dakikalar içinde yayına alabilirsiniz. Etiket tabanlı mimari, CI/CD süreçlerine rahatça entegre olurken, yeniden başlatma ihtiyacı olmadan konfigürasyon değişikliklerini devreye almanızı sağlar. Üstelik ölçeklenebilir ve gözlemlenebilir bir altyapının temelini atmış olursunuz.

19 Ekim 2025 Pazar

Tarayıcıda Python Çalıştırma Rehberi: WebAssembly ve Pyodide ile Adım Adım

WebAssembly (WASM) ve Pyodide sayesinde Python kodunu doğrudan tarayıcıda, sunucuya ihtiyaç duymadan çalıştırmak artık mümkün. Bu yazıda, Pyodide nedir, nasıl entegre edilir, paket yönetimi ve performans ipuçları nelerdir gibi sorulara adım adım yanıt veriyorum. Hedefimiz, hem modern web uygulamalarına Python gömmenin pratik yolunu göstermek hem de gerçek hayatta işinize yarayacak optimizasyon önerilerini sunmak.

Pyodide Nedir?

Pyodide, CPython yorumlayıcısını ve birçok bilimsel Python paketini WebAssembly’ye derleyerek tarayıcıda çalıştırmanıza olanak tanır. NumPy, Pandas, Matplotlib gibi kütüphanelerin “pure-Python” olanlarını veya WASM’a derlenmiş varyantlarını tarayıcıya getirir. Ağ bağlantısı olmasa bile, gerekli dosyalar indirildikten sonra kodunuzu yerel olarak işletir. Bu da interaktif eğitim içerikleri, gömülü veri görselleştirme, offline notebook deneyimleri ve güvenli istemci tarafı prototipleme için güçlü bir zemin sunar.

Hızlı Başlangıç: Basit Entegrasyon

Aşağıdaki minimal örnekle tarayıcıda Python çalıştırabilirsiniz. Kodu bir HTML dosyasına koyup açmanız yeterli.

<!-- Pyodide yükleyici -->
<script src="https://cdn.jsdelivr.net/pyodide/v0.26.0/full/pyodide.js"></script>
<script>
(async () => {
const pyodide = await loadPyodide({ indexURL: "https://cdn.jsdelivr.net/pyodide/v0.26.0/full/" });
await pyodide.runPythonAsync(`import sys; print(sys.version)`);
const result = await pyodide.runPythonAsync("sum(range(10))");
console.log("Python sonucu:", result);
})();
</script>

Burada loadPyodide ile WASM tabanlı Python ortamı yükleniyor, ardından runPythonAsync ile kod yürütülüyor. Konsolda Python sürümü ve örnek bir hesaplamanın sonucu görünecektir.

Paket Yönetimi: micropip ve Yerleşik Paketler

Pyodide, birçok popüler kütüphaneyi hazır olarak getirir. Ek bir pakete ihtiyaç duyduğunuzda micropip ile pure-Python paketleri (C uzantısı gerektirmeyenler) kolayca kurulabilir.

await pyodide.runPythonAsync(`import micropip; await micropip.install("requests")`);

NumPy veya Pandas gibi ağır paketler için Pyodide’ın yerleşik kaynaklarını kullanmak daha verimlidir. Bunlar çoğunlukla pyodide.loadPackage ile önceden yüklenebilir:

await pyodide.loadPackage(["numpy", "pandas"]);

Paket yüklemelerini sayfa ilk açılışında toplu yapmak, kullanıcı etkileşimi sırasında gecikmeleri azaltır. İlk kez yüklemede CDN’den indirme yapılırken, sonraki sayfa yenilemelerinde tarayıcı önbelleğinden faydalanılır.

Tarayıcı Dosya Sistemi ve Veri Paylaşımı

Pyodide, Emscripten’in sanal dosya sistemini (MEMFS) kullanır. JavaScript tarafındaki veriyi Python tarafına aktarmak için dosya sistemine yazmak pratik bir yöntemdir:

const csv = "a,b\\n1,2\\n3,4";
pyodide.FS.writeFile("/tmp/data.csv", csv);
await pyodide.runPythonAsync(`import pandas as pd; df = pd.read_csv("/tmp/data.csv"); print(df.sum().to_dict())`);

Alternatif olarak, doğrudan JS-Python köprüsünden yararlanabilir ve pyodide.toPy / pyodide.toJs ile veri alışverişi yapabilirsiniz. Büyük verilerde kopyalamayı en aza indirmek için bu köprüleri tercih edin.

Performans İpuçları

- Lazy yükleme yapın: İlk ekranda gerekmeyen büyük paketleri, kullanıcı etkileşimiyle tetiklenen aşamada yükleyin.
- runPython yerine runPythonAsync kullanın: Uzun süren işlemler UI’ı kilitlemesin.
- Ön ısıtma (warm-up): Sayfa yüklenir yüklenmez küçük bir Python ifadesi çalıştırmak, JIT yoksa bile modül başlatmalarını önceden yaparak ilk gerçek görevde gecikmeyi azaltır.
- Önbellekleme: CDN varlıklarını (pyodide.js, .wasm, paket indeksleri) Service Worker ile cache-first stratejisiyle saklayın. Böylece offline veya zayıf ağda bile hızlı açılış sağlanır.
- Veri boyutunu sınırlayın: Tarayıcı belleği kısıtlıdır. Tek seferde işlenen veri setlerini makul boyutta tutun ve gereksiz kopyalardan kaçının.

Güvenlik ve Sandbox

Pyodide, tarayıcının güvenli çalışma alanında koşar. Varsayılan olarak yerel dosya sistemine erişemez ve ağ istekleri tarayıcı CORS kurallarına tabidir. Üçüncü taraf paketleri yüklerken yalnızca güvendiğiniz kaynakları kullanın. Kullanıcıdan gelen Python kodunu çalıştıracaksanız, suistimali azaltmak için zaman sınırı, bellek sınırı ve izinli API listesi (allowlist) gibi korumalar düşünün.

Ne Zaman Pyodide? Ne Zaman Sunucu?

- Pyodide’ı tercih edin: Hızlı prototip, eğitim içerikleri, etkileşimli dokümantasyon, gizlilik gerektiren istemci tarafı analizler, offline kullanım senaryoları.
- Sunucuyu tercih edin: Büyük veri işlemleri, yoğun CPU bellek kullanımı, kurumsal paket bağımlılıkları, kalıcı depolama ve erişim kontrolünün kritik olduğu projeler.

Örnek Kullanım: Mini Veri Görselleştirme

Aşağıdaki örnek, küçük bir veri kümesiyle Matplotlib’i kullanır. İlk etapta paketi yükleyin, ardından grafiği base64 olarak üretip bir <img> etiketine atayabilirsiniz. (Bu yazıda görsel eklemiyoruz, ancak yaklaşım bu şekildedir.)

await pyodide.loadPackage(["matplotlib", "numpy"]);
const png = await pyodide.runPythonAsync(`import matplotlib.pyplot as plt, io, base64, numpy as np
x = np.linspace(0, 2*np.pi, 200)
y = np.sin(x)
plt.figure(figsize=(3,2), dpi=150)
plt.plot(x, y)
buf = io.BytesIO()
plt.savefig(buf, format="png", bbox_inches="tight")
base64.b64encode(buf.getvalue()).decode()`);
// document.getElementById("plot").src = "data:image/png;base64," + png;

Sonuç

Pyodide ve WebAssembly, Python’u tarayıcıya taşıyarak ön uç geliştirmeye yeni kapılar açıyor. Doğru paket yönetimi, akıllı önbellekleme ve verimli veri paylaşımıyla hem akıcı bir kullanıcı deneyimi hem de sürdürülebilir performans elde edebilirsiniz. Küçük başlayın, ihtiyaç duydukça paketleri ve optimizasyonları ekleyin. Böylece ister eğitim amaçlı mini bir laboratuvar, ister ürününüze gömülü etkileşimli bir analiz modülü geliştirin; modern webin olanaklarından en iyi şekilde yararlanırsınız.

18 Ekim 2025 Cumartesi

Rust ve WebAssembly ile Tarayıcıda Yüksek Performanslı Görüntü Filtresi Geliştirme (Adım Adım)

Giriş

Tarayıcıda yüksek performanslı görüntü işleme yapmak çoğu zaman JavaScript ile zorlayıcı olabilir. Rust ve WebAssembly (WASM) ikilisi sayesinde, CPU yoğun işlemleri güvenli ve hızlı biçimde web tarafına taşıyabilirsiniz. Bu rehberde, Rust ile basit bir gri tonlama filtresi yazacak, wasm-bindgen ve wasm-pack kullanarak WebAssembly’ye derleyecek ve sonucu bir web projesinde çağıracağız. Amaç sade, pratik ve SEO uyumlu bir anlatımla sizi hızlıca üretken hale getirmek.

Neden Rust + WebAssembly?

WebAssembly, tarayıcıda neredeyse yerel hızda çalışabilen bir bayt kod formatıdır. Rust ise bellek güvenliği, sıfır maliyetli soyutlamalar ve modern dil özellikleriyle WebAssembly hedefi için biçilmiş kaftandır. Bu kombinasyon sayesinde, görüntü işleme, ses işleme, veri sıkıştırma gibi CPU yoğun iş yüklerini JavaScript’in tek iş parçacıklı darboğazından çıkarır ve kullanıcıya akıcı bir deneyim sunarsınız.

Önkoşullar ve Kurulum

Başlamadan önce sisteminizde Rust (stable), wasm-pack ve bir paket yöneticisi (npm veya pnpm) kurulu olmalı. Kurulum komutları: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ve cargo install wasm-pack. Web tarafı için basit bir Vite veya React projesi işinizi görecektir.

Rust Kütüphanesini Oluşturma

Yeni bir Rust kütüphanesi oluşturun: cargo new --lib image_filter_wasm. Ardından Cargo.toml dosyanızı aşağıdaki gibi düzenleyin:

[package]
name = "image_filter_wasm"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2"

Gri Tonlama Filtresi Yazımı

Temel yaklaşımımız, bir Uint8Array içindeki RGBA piksel verisini alıp, gri tonlama uygulayarak yine Uint8Array olarak geri döndürmek. src/lib.rs içeriği örneği:

use wasm_bindgen::prelude::*;
use js_sys::Uint8Array;

#[wasm_bindgen]
pub fn grayscale(input: Uint8Array) -> Uint8Array {
  let mut data = input.to_vec();
  let len = data.len();
  let mut i = 0;
  while i + 3 < len {
    let r = data[i] as u32;
    let g = data[i + 1] as u32;
    let b = data[i + 2] as u32;
    // Luma (BT.709) yaklaşımı
    let y = (0.2126 * r as f32 + 0.7152 * g as f32 + 0.0722 * b as f32) as u8;
    data[i] = y;
    data[i + 1] = y;
    data[i + 2] = y;
    i += 4;
  }
  Uint8Array::from(&data[..])
}

Yukarıdaki örnekte wasm-bindgen ile Uint8Array türünü kullanarak kopyalama maliyetini yönetilebilir düzeyde tutuyoruz. Daha ileri optimizasyonlar için tek seferlik bellek ayırma ve işaretçi tabanlı API’ler de tercih edilebilir.

WebAssembly’ye Derleme

Klasör kökünde wasm-pack build --target web çalıştırın. Bu komut pkg klasöründe tarayıcı uyumlu JS wrapper ve .wasm dosyasını üretir. Alternatif olarak --target bundler ile bundler tabanlı projelere uygun çıktı alabilirsiniz.

Web Projesine Entegrasyon (React Örneği)

Bir React projesinde, canvas üzerinden ImageData elde edip pikselleri WASM fonksiyonuna aktaracağız. Basit bir akış şu şekilde olabilir:

import init, { grayscale } from "./pkg/image_filter_wasm.js";

async function runFilter(ctx, width, height) {
  await init();
  const imageData = ctx.getImageData(0, 0, width, height);
  const input = new Uint8Array(imageData.data.buffer.slice(0));
  const output = grayscale(input);
  imageData.data.set(output);
  ctx.putImageData(imageData, 0, 0);
}

Bu kod, canvas içindeki görseli alır, pikselleri grayscale fonksiyonundan geçirir ve yeniden kanvasa yazar. Geri dönüşte yeni bir Uint8Array aldığımız için doğrudan set ile kopyalamak yeterlidir.

Performans İpuçları

- Kopyalamaları azaltın: Sürekli yeni Uint8Array oluşturmak yerine, tek bir tamponu tekrar kullanacak bir API tasarlayın (ör. işaretçi ve uzunluk üzerinden, ileri düzey wasm-bindgen teknikleriyle).
- SIMD etkinleştirin: Rust’ta wasm32-unknown-unknown hedefi için SIMD desteği stabildir. Yapılandırmada RUSTFLAGS="-C target-feature=+simd128" kullanabilir, wasm-opt -O3 ile Binaryen optimizasyonlarına başvurabilirsiniz.
- İş yükünü ayırın: Büyük resimlerde ana iş parçacığını kilitlememek için Web Worker üzerinden çağrı yapın. Çok iş parçacığı (WASM threads) kullanacaksanız SharedArrayBuffer gerekeceğinden COOP/COEP ile Cross-Origin Isolation aktif olmalı.

Karşılaşılabilecek Sorunlar

- Paketleme: Bazı bundler’lar .wasm dosyalarının kopyalanması ve yüklenmesi için özel yapılandırma ister. --target web çıktısı, modern bundler’larla genelde sorunsuzdur.
- Tür uyumsuzluğu: ImageData.data Uint8ClampedArray döndürür. Bu nedenle Uint8Array dönüşümü yaptığımızdan emin olmalıyız.
- Boyut: WASM paketinin boyutunu düşük tutmak için gereksiz bağımlılıklardan kaçının ve wasm-opt kullanın.

Test ve Ölçüm

Basit bir FPS sayacı veya zaman damgası ile performance.now() ölçümleri alarak JavaScript ve WASM sürümlerini kıyaslayın. Büyük çözünürlükteki görsellerde, Rust + WebAssembly yaklaşımının belirgin şekilde daha düşük gecikme ve daha yüksek kare/saniye ürettiğini göreceksiniz.

Sonuç

Rust ve WebAssembly, tarayıcıda yüksek performanslı görüntü işleme için güçlü ve sürdürülebilir bir çözüm sunar. Bu rehberde, sıfırdan bir gri tonlama filtresi yazarak derleme, entegrasyon ve optimizasyon adımlarını gördük. Aynı yöntemi keskinleştirme, bulanıklaştırma, kenar algılama gibi farklı filtrelerle genişletebilir, hatta gerçek zamanlı kamera akışlarına uygulayabilirsiniz. Modern web uygulamalarında performansı öne çıkarmak istiyorsanız, Rust + WASM öğrenme eğrisine kesinlikle değer.

17 Ekim 2025 Cuma

Tarayıcıda WebGPU ile Yapay Zeka Modellerini Hızlandırma: ONNX Runtime Web ile Adım Adım Rehber

WebGPU ile Tarayıcıda Yapay Zeka Neden Önemli?

WebGPU, tarayıcıda GPU’ya neredeyse yerel erişim sağlayan modern bir web standardıdır. WebGL’in grafik odaklı doğasını aşarak hesaplama iş yüklerini de hızlandırır ve makine öğrenmesi modellerini doğrudan Chrome, Edge veya Safari gibi tarayıcılarda çalıştırırken belirgin performans kazancı sunar. Bu yazıda, ONNX Runtime Web kullanarak WebGPU üzerinden nasıl hızlandırma yapabileceğinizi, gerçek dünya ipuçları ve sorun giderme önerileriyle adım adım anlatıyorum.

Ön Koşullar ve Uyumluluk

WebGPU, Chrome 113+, Edge 113+ sürümlerinde yaygın olarak desteklenir. macOS’te Metal, Windows’ta Direct3D 12, Linux’ta ise Vulkan üzerinden çalışır. Güncel bir tarayıcı kullandığınızdan emin olun. Kurumsal cihazlarda GPU sürücüleri eskiyse veya politika kısıtları varsa WebGPU adaptörü bulunamayabilir; bu durumda ONNX Runtime Web otomatik olarak WASM (WebAssembly) yedek yoluna düşebilir. Eğer eski bir tarayıcı kullanıyorsanız, chrome://flags alanında WebGPU ile ilgili ayarları gözden geçirmeniz gerekebilir; ancak çoğu güncel sürümde ekstra bir işlem yapmadan çalışır.

Ne Kuracağız? Kısa Yol Haritası

Bu rehberde bir web sayfasına ONNX Runtime Web’i entegre edip, bir görüntü sınıflandırma modelini WebGPU üzerinde çalıştıracağız. Adımlar özetle şöyle: ONNX Runtime Web’i projeye eklemek, uygun bir ONNX modeli seçmek, girdi verisini hazırlamak, executionProviders: ["webgpu"] ile oturum açmak ve sonuçları yorumlamak.

Adım 1: Projeye ONNX Runtime Web Eklemek

İki yaygın yöntem var. NPM ile kurulum için modern bir paketleyici (Vite, Webpack, Parcel) kullanabilirsiniz. Komut satırında npm i onnxruntime-web diyerek kurduktan sonra uygulamanızda import * as ort from "onnxruntime-web" ifadesini kullanın. Hızlı denemeler için CDN ile de ilerleyebilirsiniz: HTML dosyanıza ONNX Runtime Web’in CDN bağlantısını eklemek yeterli olur. Her iki yöntemde de tarayıcınızda WebGPU destekliyse arka planda otomatik olarak GPU hızlandırma devreye alınabilir.

Adım 2: Model Seçimi ve Hazırlık

Başlangıç için ONNX Model Zoo’da bulunan hafif bir model tercih edin. Örneğin MobileNet veya SqueezeNet düşük bellek tüketimiyle iyi bir başlangıç sunar. İndirdiğiniz model dosyasını (örnek: model.onnx) sunucunuzdan statik olarak servis edin. Model boyutunu mümkün olduğunca düşük tutmak hem ilk yükleme süresini hem de bellek kullanımını azaltır. FP16 dönüştürülmüş modeller, GPU bellek ayak izini düşürerek performansa katkı sağlar.

Adım 3: WebGPU ile Oturum Oluşturma

ONNX Runtime Web ile bir oturum oluştururken executionProviders: ["webgpu"] parametresini geçerek GPU hızlandırmayı istersiniz. WebGPU uygun değilse kütüphane WASM’a otomatik geçebilir. Bu aşamada önemli nokta, oturumu yalnızca bir kez oluşturmanızdır; inference işlemleri sırasında aynı oturumu tekrar tekrar kullanmak, modelin yeniden yüklenmesini ve derlenmesini önleyerek ciddi zaman kazandırır.

Adım 4: Girdi Hazırlama ve İnference

Görüntü tabanlı bir model için girdiyi modele uygun boyuta ölçekleyip normalleştirmeniz gerekir. Bu işlem genellikle şu adımlardan oluşur: görseli kanallara ayırma (RGB), piksel değerlerini 0-1 aralığına ölçekleme, ortalama/standart sapma ile normalizasyon ve tensörü NCHW biçiminde düzenleme. ONNX Runtime Web için tensör oluştururken new ort.Tensor("float32", data, [1, 3, H, W]) biçimini kullanabilirsiniz. Çıktı yüzlerce sınıf ve olasılık içeriyorsa en yüksek olasılıklı birkaç etiketi seçip kullanıcıya sunmak idealdir.

Adım 5: Performans İyileştirme İpuçları

Performansı artırmak için birkaç pratik öneri: Oturum nesnesini yeniden kullanın ve model dosyasını önbelleğe alarak ilk yükleme süresini kısaltın. Girdi verisini oluştururken gereksiz kopyalardan kaçının; aynı Float32Array tamponunu yeniden kullanmak GC yükünü azaltır. Mümkünse daha küçük çözünürlükte girişler deneyin; bazı modeller 224x224 ile tatmin edici sonuç verir. Ağır iş yüklerini Web Worker içine taşıyarak ana iş parçacığını bloklamayın; UI donmalarını önlemek için hesaplama dilimlerini requestIdleCallback veya küçük partisyonlarla planlayın. Ölçüm için performance.now() ile yükleme, ön işleme, inference ve son işlem sürelerini ayrı ayrı izleyin; darboğazı nokta atışı bularak iyileştirin.

Güvenlik, Gizlilik ve Dağıtım

Tarayıcı içinde yerel inference çalıştırmak, verilerin sunucuya gitmeden işlenmesini sağlar; bu da gizlilik ve gecikme (latency) açısından avantajdır. WASM yedek yolunda iş parçacıkları ve SIMD kullanmayı planlıyorsanız COOP/COEP başlıklarıyla cross-origin isolated bir yapılandırma gerekir. İç ağda veya kurumsal ortamlarda dağıtım yaparken GPU sürücü sürümlerini ve tarayıcı versiyonlarını standardize etmek, destek çağrılarını ciddi ölçüde azaltır.

Yaygın Hatalar ve Çözümler

“Adapter is null” veya “No WebGPU device found” hataları alıyorsanız tarayıcınızı ve ekran kartı sürücünüzü güncelleyin; sanal makinelerde WebGPU kısıtlı olabilir. “Out of memory” uyarılarında giriş boyutunu küçültün, modelin FP16 sürümüne geçin veya daha hafif bir mimari deneyin. “Invalid model input shape” hatası, tensör boyutlarıyla modelin beklediği şeklin uyuşmadığını gösterir; modelin giriş ismini ve beklenen boyutları kontrol edin. WASM’a düşüşte performans çok geriliyorsa, WebGPU’nun gerçekten etkinleştiğini doğrulamak için oturum seçeneklerini ve tarayıcı destek sayfalarını inceleyin.

Gerçek Dünya Senaryoları

Perakende uygulamalarında raf denetimi veya barkod dışı ürün tanıma gibi görevler, mağaza içi tabletlerle çevrimdışı çalıştırılabilir. Eğitim teknolojilerinde çizim veya laboratuvar deneylerinde görüntü analizi, öğrenci cihazlarında gecikme olmadan yapılabilir. Yayıncılıkta canlı metin filtreleme veya basit duygu analizi, kullanıcı tarayıcısında gerçekleşerek sunucu maliyetlerini düşürür.

Sonuç ve Öneriler

WebGPU, tarayıcıda yapay zeka deneyimini yeni bir seviyeye taşıyor. ONNX Runtime Web ile birlikte kullanıldığında, çeşitli cihaz ve tarayıcı kombinasyonlarında tatmin edici performans ve düşük gecikme elde etmek mümkün. Küçük ve optimize edilmiş bir model, doğru ön işleme adımları ve tek seferde başlatılan bir oturum mimarisi, projelerinize stabilite ve hız kazandırır. İlk prototipinizi basit bir görüntü sınıflandırma modeliyle kurup, ardından model boyutu, giriş çözünürlüğü ve iş parçacığı stratejileri üzerinde iterasyon yaparak prodüksiyon seviyesine güvenle geçebilirsiniz.

16 Ekim 2025 Perşembe

Rust ve WebAssembly ile Tarayıcıda Görüntü İşleme: Adım Adım Rehber

Giriş

WebAssembly (WASM), tarayıcıda neredeyse yerlisi kadar hızlı çalışan kodlar yazmayı mümkün kılıyor. Eğer piksel piksel görüntü işleme, gerçek zamanlı filtreler veya CPU yoğun işlemlerle uğraşıyorsanız, JavaScript tek başına her zaman yeterli olmayabilir. Bu rehberde, Rust + WebAssembly ikilisini kullanarak tarayıcıda basit bir görüntü işleme modülü oluşturmayı ve performansı artırmanın pratik yollarını adım adım anlatıyorum.

Neden Rust + WebAssembly?

Performans: Rust derlenmiş kodu WebAssembly’ye taşıdığınızda, piksel manipülasyonu gibi yoğun işlemlerde belirgin bir hız kazanırsınız. Özellikle büyük görsellerde JavaScript döngülerinin sınırlamalarını aştığınızı hissedeceksiniz.

Bellek güvenliği: Rust’ın sahiplik modeli ve derleyici kontrolleri, tipik bellek hatalarını en başında engeller. Tarayıcı gibi hassas bir ortamda bu oldukça kritiktir.

Taşınabilirlik: WASM çıktısı, modern tüm tarayıcılarda çalışır. Rust tarafında yazdığınız çekirdek algoritmaları, Node.js veya Wasmtime gibi ortamlarda da kullanabilirsiniz.

Gereken Araçlar ve Kurulum

Rust kurulumu için resmi yönlendiriciyi tercih edin: rustup. Ardından WASM hedefini ekleyin: rustup target add wasm32-unknown-unknown. Paketleme ve bağlayıcılar için wasm-pack aracını kurun: cargo install wasm-pack. Tarayıcı tarafında modülü kullanmak için npm veya yarn da işinizi kolaylaştırır.

Yeni bir kütüphane projesi oluşturun: cargo new goruntu-wasm --lib. Proje klasörüne geçin ve Cargo.toml dosyasına wasm-bindgen bağımlılığını ekleyin.

Proje İskeleti ve Yapılandırma

Cargo.toml içine aşağıdakine benzer satırlar ekleyin: [dependencies] wasm-bindgen = "0.2". Derleme hedefi için [lib] bölümüne crate-type = ["cdylib", "rlib"] yazmayı unutmayın. Bu, Rust kütüphanesinin WASM olarak bağlanabilmesini sağlar.

Kaynak dosyası src/lib.rs içinde, JavaScript ile köprü kurmak için wasm_bindgen makrolarını kullanacağız. Temel bir dışa aktarma şöyle görünür: use wasm_bindgen::prelude::*; #[wasm_bindgen] pub fn versiyon() -> String { "0.1.0".into() }. Bu, tarayıcıda modül yüklendiğinde çağrılabilir bir fonksiyon üretir.

Tarayıcı Entegrasyonu

Derlemek için wasm-pack build --target web komutunu çalıştırın. Bu, pkg klasöründe ES modül uyumlu bir çıktı üretir. Ön yüzde bir modül dosyasında şu şekilde içe aktarabilirsiniz: import init, { versiyon } from "./pkg/goruntu_wasm.js"; await init(); console.log(versiyon());. Basit bir HTML sayfasında <script type="module"> kullanarak bu modülü kolayca yükleyebilirsiniz.

Paket yöneticisi ile entegre çalışmak isterseniz wasm-pack çıktısını bir NPM paketi gibi tüketebilirsiniz. Bu sayede Vite, Webpack veya Parcel ile ağaç sarsma ve önbellekleme gibi optimizasyonlardan faydalanırsınız.

Basit Bir Gri Tonlama (Grayscale) Örneği

Tarayıcıdan aldığınız ImageData nesnesi, RGBA kanal sıralı bir Uint8ClampedArray içerir. Bu diziyi WASM tarafına aktarıp geri almak için iki pratik yol var: kopyalamak veya paylaşılan bir tampon üzerinden erişmek. Başlangıç için, güvenli ve net olduğu için kopyalama yaklaşımı işinizi görecektir.

Rust tarafında bir fonksiyon düşünün: #[wasm_bindgen] pub fn grayscale(input: Vec<u8>) -> Vec<u8> { ... }. Algoritma basit: Her piksel için r, g, b değerlerinin ağırlıklı ortalamasını alın ve geri yazın. Yaygın bir yaklaşım: gray = 0.299*r + 0.587*g + 0.114*b. Rust’ta tamsayı işlemlerinde küçük bir yuvarlama eklemek renk doğruluğunu iyileştirir.

Ön yüzde, CanvasRenderingContext2D ile bir görüntüyü çizip getImageData ile pikselleri alın. Daha sonra const out = grayscale(new Uint8Array(imageData.data)); gibi bir çağrıyla sonuç dizisini alın ve putImageData ile tekrar tuvale yazın. Bu döngüde veriyi fazla kopyalamamak için işlemi toplu yapın; birden fazla filtre uygulayacaksanız tek bir WASM çağrısında zincirlemek daha etkilidir.

Performans İpuçları

SIMD desteği: Modern tarayıcılar WASM SIMD’i destekliyor. Rust’ta std::arch veya uygun crate’lerle vektörleştirme yaparak yaklaşık 2-4 kat hız artışı görebilirsiniz. Varsa RUSTFLAGS="-C target-feature=+simd128" deneyin.

Veri kopyalarını azaltın: Çok büyük görüntülerde her karede kopyalama pahalıdır. Orta vadede wasm-bindgen ile Uint8Array tamponunu paylaşmak veya WebAssembly.Memory üzerinden doğrudan yazmak daha iyi sonuç verir.

Web Workers: Ana iş parçacığını kilitlememek için görüntü işlemeyi bir Worker içine taşıyın. OffscreenCanvas kullanabiliyorsanız, çizim ve filtrelemeyi tamamen worker içine izole ederek UI akıcılığını korursunuz.

Ön ısıtma: Modülü sayfa yüklenir yüklenmez başlatıp küçük bir “ısındırma” çağrısı yapmak, JIT/optimizasyon basamaklarını kullanıcı etkileşimi öncesinde tamamlamaya yardımcı olur.

Hata Ayıklama ve Ölçüm

WASM kodunu debug modunda derlediğinizde boyut artar ve performans düşer; bu normaldir. Geliştirmede console.time/console.timeEnd ile uçtan uca süreleri ölçün, Performance.now() ile kare bazlı gecikmeyi takip edin. Rust tarafında log ve console_error_panic_hook kullanarak panik ve logları tarayıcı konsoluna yönlendirebilirsiniz.

Boyut optimizasyonu için üretim derlemesinde wasm-opt -O3 (Binaryen) deneyin. Ayrıca wasm-pack build --release kullanarak sembol isimlerini küçültür ve gereksiz debug bilgilerini atarsınız.

Sonuç

Rust ve WebAssembly, tarayıcıda görüntü işleme gibi CPU ağırlıklı görevlerde güvenli, hızlı ve öngörülebilir bir çalışma zemini sunuyor. Basit bir gri tonlama filtresiyle başladık; aynı yaklaşımı kenar algılama, bulanıklaştırma, renk düzeltme veya gerçek zamanlı kamera filtrelerine kolayca genişletebilirsiniz. Doğru veri aktarım stratejisi, SIMD ve Web Workers ile birleştiğinde, modern web uygulamalarında yerel uygulama hissi veren bir performans elde etmek mümkün. Bir kez kurduktan sonra, bu altyapıyı pek çok projede tekrar tekrar kullanabileceğinizi göreceksiniz.