Web için Non-Hype Rehberi: ES Modules ile Geleceğe Dönüş

Barış Güler
8 min readDec 17, 2020

--

Hatırlatma: Bu makale size neyi nasıl yapacağınızı değil, web’in kabul gören best practice’leri nasıl değiştirebileceğinizi anlatıyor. Yazının orjinaline buradan ya da buradan ulaşabilirsiniz. Bu yazı bir süredir Kjaer ile üzerinde kafa patlattığımız build ya da bundle olmaksızın geliştirme yapma fikri üzerine bir detay paylaşımı olarak değerlendirilebilir.

Hatırlatma 2: Geleceğe Dönüş temasını neden seçmemin sebebi, geçmişte web geliştirmenin daha çok HTML’in içerisinde yapılan geliştirmeden oluşuyordu. Gün geçtikçe ortaya çıkan araçlarla zaman içerisinde değişen paradigmanın yavaş yavaş terkedilip, web’in orjinal yaklaşımına daha çok yaklaşıyoruz.

Gerçekten İstediğimiz Bundler-bağımlı Geliştirme mi?

Web uygulama code bundler’ları (Webpack vb.) bugün neredeyse geliştirdiğimiz bütün web uygulamalarında kullanılıyor. Bunu da bugüne kadar ECMAScript’teki gelişmelere tarayıcı engine’lerinin yetişememelerine borçluyuz. Her araç gibi bu ekstra step’in geliştirme yaşam döngüsüne dahil olması beraberinde başka dertleri de beraberinde getirdi. Özetle bu ek adım, bir uygulama geliştirmek istediğinizde, projenizi canlıya almadan önceki geliştirme sürecinize ek bir adim eklemeniz anlamına geliyor: build/bundle aşaması. Deneyimleri farklı olsa da kullandığımız her bir code bundler’ın geliştirme suresince aldığı kod export’u, yazdığınız kodun boyutu büyüdükçe genişliyor, şişiyor. Kaldı ki sorun sadece geliştirme aşamasında değil. Canlıya çıkıldığında eğer doğru bir caching stratejisinden bahsedemiyorsak canlıda bundle’i remote noktadan fetch etmek için harcanan bir de ek süre söz konusu. Bu da insanı şunu düşünmeye itiyor: nerede kaldı geliştirme/geliştirici deneyimi ya da tatmini?

https://httparchive.org/reports/page-weight#bytesTotal
https://httparchive.org/reports/page-weight#reqTotal

Bugün, web teknolojilerindeki son gelişmeler ışığında, tarayıcılar geliştirici ve|veya geliştirme deneyimini arttırmak için farklı bir yol izlemek zorunda olduğunu bir süre önce anladı. Bu deneyimi kolaylaştırmak ve geliştiricilerin sadece inşa etttikleri ürüne odaklanmalarını sağlamak icin yeni ürünler çıkartıyorlar. Örneğin Vercel, Netlify, Amplify, vb. gibi araçlar bu işi daha kolay hale getirmek, geliştirme döngüsünü (code ⇒ CI/CD ⇒ Live) daha da hızlandırırken bugün geliştiriciler birçok nedenden ötürü bu sürenin giderek uzamasından muzdarip alabiliyor. Bunun birçok sebebi var: kullanılan araçlara (tool) özel konfigürasyon yapmak zorunda kalmak, ek compilation/build/bundle zamanları, ve export edilen kod çıktısına eklenen onca ilave kod nedeniyle runtime’da yaşanan performans sorunları.

Credits: https://v8.dev/blog/cost-of-javascript-2019

Burada değinmek istediğim konu daha çok code bundle’ları. Web uygulamalarını statik olarak çıktı almanın performans parametrelerine katkısı olduğu gibi, web geliştirmeyi daha rahat ve ağrısız, sızısız yapmanın bir başka yolu bir süredir zaten var; o da bütün uygulamanın bir kod çıktısı olarak bir ya da birden fazla dosyalar halinde build-time sırasında load etmek ya da işlemek yerine, runtime’da başka bir yaklaşıma yaslanmak. Ben buna “buildless” diyorum ama “bundleless”, “bundle-exportless” gibi ifadelerle tanımlamak da mümkün, hatta daha uygun gelebilir. (Ne de olsa bugünlerde bir yaklaşımı -less ekiyle tanımladığınızda daha çok ilgi görüyor: bkz. codeless, serverless, vb.)

Neden bundle almayalım ki?

Çoktandır bir EcmaScript standardı olan modül sistemi hem sunucu hem de istemci tarafında desteklenir hale geldi diyebiliriz. Böylece daha az baş ağrısı ile tutarlı bir geliştirme deneyimi yasayabilirsiniz.

Bircok uygulamaya sıfırdan başlandığı ilk anda başvurduğu hazır boilerplate üreteçlerinin ürettiği bundle boyutları düşünüldüğünde konunun ciddiyeti tabii ki daha da artıyor. node_modules dizininin ünü evrensel bir hale geldigi günümüzde, bu konudaki her gelişmenin bize hem geliştirme zamanı olarak, hem de canlıya çıkma zamanında olarak artısı zaten kaçınılmazdı.

Credits: https://medium.com/better-programming/npkill-the-easy-solution-to-deleting-node-modules-with-style-1c591126f7a5

Nitekim aşağıdaki tablo her deploy sonrasında sunucularınızdan tekrar tekrar yüklediğimiz bundle dosyaların yanısıra build sırasında export edilen dosyaların boyutlarına dair bir fikir veriyor.

Bütün bunlara ek olarak, daha önceleri BrowserSync ile aşina olduğumuz Save & Refresh yerini React.js ile geliştirme yapılırken ilk kez tanıştığımız HMR’ye (Hot-Module Reloading) bıraktı. Bu süre genellikle geliştirmenin yarattığı hararetle es geçilen bir detay. Ancak geliştirme esnasında her bir CTRL+S / Bundle Export işleminin aldığı süre göz önüne alındığında geliştiricinin yaşadığı bu muhtemel zaman kaybının geri dönüşü de ayrıca bir memnuniyetsizlik konusu olabiliyor. V8'te halihazırda bulunan Dynamic import ile bu dert kısmen aşılabiliyor olsa da, her şekilde bir code bundler tool kullanıldığından yine de önümüzde ciddi bir bundle export time gibi bir can sıkıcı parametre duruyor. Her save sonrası bekleme, sonucu görme, kodu update etme ve yeniden aynı döngü. Tabii kodun boyutu büyüdükçe bu zamanın artması da söz konusu.

Bütün bunları düşünürken tabii bir de kullanıcıya bir an önce bir ürün ile ulaşayım derken urunun bağlamından kopup (zaten basta planlama olmak üzere başka bir ton parametreyle uğraşırken bir de) bu tür sadece geliştirme döngüsünde varolan detaylarda boğulmanız ve (varsa) deadline’ınıza yavaş yavaş el sallamaya 👋🏿 başlamanız çok olası. Elbette bu detaylar her uygulama geliştirme surecinin neredeyse bir parçası ama hype anlayışın ya da tool’ların aksine başka bir imkan daha mümkün: ES Modules. Bunu bundle almadan geliştirme olarak özetleyebiliriz.

Ve bu tarz bir modül kullanımı, yani Node.js’in bir suredir stabil sürümünde de yer verdigi ES Modules özelliği tarayıcıların önemli bir kısmında bugün aktif ve kullanılabilir durumda.

Aynı zamanda halihazırda npm’deki herhangi bir package’ı direk olarak skypack üzerinden JS ya da HTML dosyanıza import ederek kullanabilirsiniz:

Veya direk HTML içerisinden import ettiğiniz package’a ulaşmanız mümkün.

type attribute’ü “module” olan her script tag’i ve import edilen dosyanın icinden export edilmiş entry’niz ile kodunuzu direk HTML dosyanızda run etmeniz mümkün demek, evet, web’de tarihin tekerleğini geriye doğru çevrilmesi gibi gelebilir ama yöntemlerin basitleşmesiyle daha kullanışlı hale gelmeleri hoş bir detay. Hatta terminalinizde npm install’ı run etmenize gerek duymadan!

preact’ın skypack package skoru: https://www.skypack.dev/view/preact

Gelin bir de bunu bi gerçel bir use-case uzerinden inceleyelim. Bir çoğumuz cookie set/get islemleri için belli kütüphaneler kullanmıştır. Benim bir süredir tercih ettiğim js-cookie kütüphanesinin readme dosyasından yakaladığım bir detayı surada paylaşayım:

https://github.com/js-cookie/js-cookie#direct-download

An itibariyle “ama biz vanilla javascript sentaksını sadece tooling için kullanıyoruz” denildiğini duyar gibiyim. Malumunuz bir aralar (aslında hala devam eden oranda) jQuery icin söylenilenleri bugün yavaş yavaş diğer birçok favori tool icin söylüyoruz. Nitekim kullanım oranları giderek artan Vue, React, Angular, vb. araçların ES Modules desteklemeye başlamalarının çok uzun zaman almayacağını da belirteyim. Tek ihtiyacımız olan şey ES Modules uyumlu bir entry file’ının çıktı olarak alınmasıydı. (Bu konuda Vue.js’i tebrik etmek lazım! 👏🏿) Hala desteklemeyenler için sykpack gibi package CDN’lerini kullanmanızı tavsiye ederim.

Özetle işin ucu şuraya dayanıyor: paket bağımlılıklarınızı ek olarak iş mantığınızı işleyen koda ekleyip bundle’lar çıkartarak çalışmak yerine, runtime’da geliştirmenizi yapıp, hiç geliştirme ortamınızı terk etmeden aynı ortam ile canlıya çıkmanız da mümkün diyebiliriz. Her gün bir build-time zamanını zaten yeterince bundler tanrılarına kurban ediyoruz; bu sefer de geliştirici deneyimine katkıda bulunan bir özellik ile geliştirme yapmak eminim geliştirme sürecini daha zevkli hale getirecektir. Sadece tarayıcılarda değil, farklı ortam ve platformlarda da çalışan uygulamaları yazdığımız her gün “tek bir yerde (dosyada) yaz, hemen çalıştır” demek (aşağıdaki örnekteki gibi) çok da zor olmamalı, degil mi?

Mesela preact kullanarak ES Modules özelliğinden faydalanarak bir uygulama yazmaya başladınız. Ben burada snowpack kullanıyorum, siz aralarından seçtiğiniz şu, şu veya şu tool’u tercih ederek geliştirme yapabilirsiniz.

npx create-snowpack-app app --template @snowpack/app-template-preact --use-npm && cd ./app && npm start
Terminaliniz şu çıktıyı verdiğinde hazırsınız demektir. 👌
App.js dosyası 👍
Tarayıcıdakı sonuç 🎉

public dizinindeki index.html’in içeriğine baktığınızda göreceğiniz şu satır ile kodunuz tarayıcıda koşmaya hazır:

<script type="module" src="/_dist_/index.js"></script>

_dist_dizini içindeki dosyayi bundle edilmiş kod olarak kabul edebilirsiniz. snowpack'in burada yaptığı şey, geliştirdiğiniz kodu ilgili package'lar ile size browser ortaminda direk run edebileceginiz hale getirmesi. Farkı, bunu ekstra eklenti olmadan yapıyor olması ve ES Modules-native bir dosya çıkartması. Örneğin, index.jsdosyasını herhangi bir HTML dosyasında ya da bir JS istediginiz tool'u kullanabilir, hatta hicbir tool'a bagimli olmadan gelistirmenizi yapabilirsiniz.

Eğer kodu production’da run edecekseniz skypack’in her package için sunduğu pinned url’leri kullanmamız tavsiye ediliyor. Yukarıdaki kodun direk olarak browser’dan çalışan halini merak ediyorsanız, buyrun burada:

meşhur index.html

Ben deployment step’ini Vercel uzerinden konfigüre ettim. Yapmanız gereken SettingsBuild & Development Settings kısmına giderek Build npm run snowpack:build ile değiştirmeniz. Ardından her bir master’a merge işleminizde deploy ettiginiz kodunuz public dizininden canlıya alınacaktır. Eğer custom bir distribution dizininin var ise, onu da Output Directory’de belirtebilirsiniz, aksi durumda sorunsuz çalışacaktır.

Geçişi nasıl yapsak?

ES Modules çoktan birçok tarayıcı tarafından desteklendiğinden bundler kullanarak geliştirme yapmaktan uzaklaşıp kodunuzda daha modern bir yaklaşım benimsemek için, kod tabanınızın ihtiyaçlarına uygun olarak bir strateji izleyebilirsiniz. Bu konuda (örn.) Rollup ile başlayıp, kodu küçük islem parçalarına bölüp kucuk migration’lar yapmak her bir feature’ınızı module dönüştürmenizi sağlayabilir. Veya direk olarak kodunuzu ES modules export’u alabileceğiniz herhangi bir tool uzerinden uygulamalarınıza entegre edebilirsiniz.

Geliştirme deneyiminizi böyle arttırırken aynı zamanda domain-specific ürünlerinizi başka uygulamalarınıza kod tabanındaki küçük konfigürasyon değişiklikleriyle ekleyeceğiniz ES Modules desteğiyle entegre edebilirsiniz. Bu konuda şu örneği verebilirim. Özellikle son zamanlarda framework ve tool’lar arası çakışmaların sadece özel kod çatılarıyla çözülebildiği günümüzde temiz bir entegrasyon sunan ES Modules’ün microfrontend yaklaşımında nasıl yardımcı bir araç haline gelebildiğini göreceksiniz. Eminim production.like.bla.bla.bla.config.js dosyalarından kurtulduğunuza sevinirken, artan geliştirme tatmini ile iş odaklanmanızı saglayabilirsiniz.

Takımca yaptığınız grooming oturumlarında, guild toplantılarında, kahve sohbetlerinizde bu konudan bahsedip arkadaşlarınızın konudan heyecan duymasını saglayabilir, birlikte çeşitli inisiyatifler yaratarak mevcut kod tabanınızı ES Modules üzerinden kolaylıklar yeniden tasarlayabilirsiniz. Böylece belki de lead-by-example için bir konu bulmuşsunuzdur.

Patronu / yöneticinizi burada detaylarıyla anlatılan EStimator’dan alacağınız raporu kullanarak bu modern web paradigmasını kullanmak için ikna etmeye başlayabilirsiniz.

Bütün bunlara ek olarak, bir sure once Kjaer ile birlikte yayına aldığımız buildless.site’a (awesome-buildless üzerinden) göndereceğiniz repo/ornek/makale vb. kaynaklarla destek verebilir, modern web teknolojilerini etrafınıza ve geliştirme dünyasının geri kalanına yaymaya yardımcı olabilirsiniz. Aynı firmada calıştığımız dönemde konu ile ilgili hazırladığımız sunuma da buradan ulaşabilirsiniz.

Umarım yazılım geliştirme süreçlerinizde size yardımcı olacak bir yaklaşım ile tanıştırmışımdır. Destek ve tartışmayı yaymak icin paylaşabilir, bana twitter ya da linkedin üzerinden ulaşabilirsiniz. Diğer yazılarıma da hwclass.dev’den okumanız mümkün.

Zaman ayırıp okuduğunuz için teşekkürler. Geri bildirimlerinizi sabırsızlıkla bekliyorum. 👋

--

--