Bileşen Odaklı Frontend Uygulamalarının Arkasındaki Hikaye
Bu yazıda bileşen odaklı geliştirmeye (component-driven development) olanak sağlayan Angular, Vue, React gibi frontend framework’lerinin dayandıkları ortak temel noktalara ve bunu nasıl sağladıklarına değineceğim.
Web Bileşenleri
Web bileşenleri, ilk olarak 2011’de tanıtıldı, ancak bileşenler yıllardır yazılım geliştirme sürecinin bir parçasıydı. Web bileşenlerini uygulamak için gerekli standartlar W3C tarafından çalışılmakta ve web uygulamalarının geleceğini temsil etmekte.
Web Bileşenlerinin Yokluğunda Hayat
Frontend kodu geliştirdiğimizde, genellikle bazı JavaScript frameworklerini ve CSS tanımlarını kullanır, HTML’imize yediririz. Bunu yaparken de bazı CSS veya JavaScript dosyalarının gelmediğini ve yazdığınız tüm kodu değiştirmediğini umarız.
Geçenlerde bir web sitesinde çalışırken, bir sorunuma çözüm sağlıyor gibi görünen bir JavaScript kütüphanesi buldum. Kütüphaneyi ve CSS dosyalarını sayfama ekledim ve istediğim işlevselliği sağladım, ancak kötü bir yan etki ile: CSS, tüm <p> etiketlerimi text-align: center olarak değiştirdi.
Frontend geliştirme, birbirleriyle çakışmayan ve uygulamaya çalıştığımız işlevselliği sağlayan JavaScript ve CSS kütüphanelerinin dikkatlice birleştirilmesi konusu haline gelmekte.
Web Bileşenleri
Web bileşenleri, tarayıcının nasıl görüntüleneceğini bildiği, tam olarak kapsüllenmiş HTML öğeleridir. HTML ve CSS bileşen içinde kapsüllenmiş olduğundan, daha sonra yüklenen CSS stilleri HTML öğelerindeki sunum kurallarını değiştirse bile, bileşen her zaman tasarlandığı şekilde gösterilecektir.
Bir HTML sayfası oluşturduğunuzda, belge nesne modeli (DOM) oluşturursunuz. DOM, HTML kaynak kodunuzun nested bir ağaç yapısı olarak bir temsilidir. Tarayıcılar, HTML’i DOM’a ayrıştırmak (parse) için çeşitli layout motorları (WebKit veya Gecko gibi) kullanırlar. DOM inşa edildikten sonra, JavaScript ve CSS DOM’u işleyebilir (DOM Manipulation). JQuery veya CSS ile çalıştıysanız, belirli DOM öğeleri almak için, # (ID) veya . (class) gibi seçicileri kesinlikle görmüşsünüzdür.
Shadow DOM
Shadow DOM var olan herhangi bir DOM öğesinden oluşturulabilen kapsüllenmiş DOM nesnesidir. Shadow DOM’u oluşturan DOM öğesi ShadowHost, kapsüllenmiş yeni öğe ise ShadowRoot olarak adlandırılır. Aşağıdaki JavaScript parçası Shadow DOM öğesinin nasıl oluşturulduğunu göstermektedir.
Shadow Root içindeki biçimlendirmeler, Shadow DOM’un dışındaki script dosyaları için görünmezdirler. Shadow DOM’un amacı, güvenli ve kapsüllenmiş bir snippet sağlamaktır.
Aşağıdaki kod örneğini incelediğimizde, HTML öğesinin “Hello, world!” içerdiğini görüyoruz. Ancak, script dosyası bir ShadowRoot oluşturur (henüz yoksa) ve innerHTML özelliğini “Hello from the ShadowRoot” olarak set eder. Tarayıcı bu kodu çalıştırdığında, düğmenin içeriği ShadowRoot içeriğinde ne varsa onunla değiştirilir.
Ancak, düğmeyi tıkladığınızda, ShowTheSpan() fonksiyonu, tarayıcının ShadowRoot’tan görüntülendiği içeriği değil, Hello, world! içeriğini gösterir. Bu, Web bileşenleri oluşturmak için gerekli olan kapsülleme ve kapsamanın (encapsulation and scoping) bir örneğidir.
Not: Bazı tarayıcılar, özel pseudo-selector’ler aracılığı ile ShadowDOM’un kısımlarını CSS’e teşhir edebilmektedir. Ayrıca, bileşen geliştiricileri, istedikleri bazı içerikleri, özellikle theming ve styling ile ilgili içerikleri, expose etmeyi seçebilir.
Template Etiketi
Bileşen bulmacasının bir başka parçası HTML <template> etiketidir. Bu etiket, daha sonra kullanmak üzere HTML parçaları oluşturmamızı sağlar. Bir şablon etiketinin içindeki içerik görüntülenmez ve etkin değildir (imajlar indirilmez, komut dosyaları çalışmaz, vs.).
Şablonlar HTML, CSS stil sayfaları ve hatta JavaScript içerebilir. DOM içinde herhangi bir yere yerleştirilebilirler ve onlara ihtiyacınız olana kadar inaktif kalabilirler. Aşağıda bir <h3> öğesine kenarlık ve gölge çizen, biraz metin ekleyen basit bir şablon etiketi yer almaktadır.
<template> <style> h3 { color: darkblue; border:2px solid gray; box-shadow: 10px 10px 5px #0f0f0f; width:20%; margin-left:20px; padding-left:10px; } </style> <h3>[From the ShadowRoot...] </h3> </template>
Şimdi, innerHTML özelliğini manipüle etmek yerine Shadow Root oluşturarak, şablon kodunu içeri alacağız. Bu durumda şablonumuzun içindeki <h3> stili, Shadow Root içinde yer aldığından, sayfanın kullandığı diğer <h3> stillerini etkilemez.
Bu örnekte şablon öğesini alıyoruz (birden fazla şablonumuz varsa getElementById() kullanabilir) ve Shadow Root öğesine ekliyoruz. Ekranınız şimdi HostDiv öğesinde aşağıdakileri gösterecektir.
Host elementten içerik alınması
Çoğu zaman, şablonumuz kendine ait içeriği sabit kodlama (hard-code) yerine, host öğesinden almak isteyecektir. Örneğin, Shadow Host öğemiz aşağıdaki gibi görünüyorsa:
<div id="HostDiv"><span>[From the ShadowHost...]</span></div>
Şablonumuzun aşağıdaki HTML satırını:
<h3>[From the ShadowRoot...] </h3>
aşağıdaki şekilde değiştirebiliriz:
<h3>[From the ShadowRoot...] <content select="span"></content></h3>
Şablon eklendiğinde, Shadow Host’un <span> etiketinin içeriğini alır ve bunu kullanır.
Birlikte ele alındığında, Shadow DOM ve template sistemi, web sayfalarının Frontend geliştirmesinde bileşen tabanlı yapıya kapıyı açmaktadır. Ve bu, Angular, Vue, React gibi Frontend frameworklerinin sağladığı en büyük faydalardan biridir.
Özet
Modern Frontend framework’leri, bileşen odaklı geliştirmeyi (component-driven development) desteklemek ve yeniden kullanılabilir bileşenler (reusable components) oluşturmak için Web bileşenlerinden ve Shadow DOM’dan yararlanır.