JavaScript Gom Jabbar
(frantic.im)- 10 yıllık bir JavaScript geliştiricisinin
package.jsonokuma sahnesini acı sınavı olarak ele alıyor ve tek bir yapılandırma dosyasının ekosistemin birikmiş karmaşıklığının ne kadarını barındırdığını gösteriyor main,browser,type: modulegibi alanlar Isomorphic JavaScript, tarayıcı bundle’ları, CommonJS’ten ESM’ye geçişin eski migrasyon yaralarını akla getiriyorscripts,dependencies,devDependenciesiçinde lint varyasyonları,watchman, gulp,left-pad, moment.js,resolutionsgibi eski araçlar ve paket yönetimi sorunları birbirine dolanmış durumdaeslint,postcss,jestile build ve test araçları; katı kurallar, platforma özel kurulum hataları, ESM ve TypeScript yapılandırma zorlukları üzerinden geliştirme ortamını sürdürme maliyetini artırıyor- Node
enginesalanına bakarken bile Bun veya Deno’ya geçmeme nedeni, acının kaybolmayıp daha da büyüyeceğine duyulan kesin inanç; geliştirici dosyayı kapatıp şimdilik hayatta kalıyor
package.json okuma sınavı
- Hikâye, JavaScript’i 10 yıldır kullanan bir geliştiricinin bilgisayarının başında
package.jsondosyasını açıp sonuna kadar okumak zorunda kalmasıyla başlıyor - Bu dosya basit bir yapılandırma dosyası değil; JavaScript ekosisteminde yaşanan anı ve acıları bir anda geri çağıran bir nesne
versionhâlâ1.0’a ulaşmamış; SemVer ise uzun zaman önce görmezden gelmeyi öğrenilen tatsız bir anı olarak kalmışname, istenen adın kullanılamadığı bir durumu gösteriyor: 7 yıl önce birinin sahiplenip sonra güncellemediği bir paket yüzünden
Modüllerin ve bundle etmenin eski yaraları
mainvebrowseralanlarının birlikte var olması Isomorphic JavaScript izlerini ortaya çıkarıyor- Tarayıcı bundle’ında
fsmodülünürequireetmeye çalışıldığı anılar ve bunu çalıştırmak için kullanılan hack’ler tatsız deneyimler olarak kalmış type: module,require’danimport’a geçiş migrasyonuyla bağlantılı- CommonJS ve ESM modüllerini birbirinden import etmeye çalışma deneyimi büyük bir acı olarak kalmış
Script’ler ve bağımlılıkların karmaşası
scripts, sıcak ve acı verici bir karmaşanın merkezilint,lintall,lintfast,lintdiffgibi varyasyonlar var- Paralel çalıştırma, belirsiz argümanlar ve JSON biçimli argümanların çift escape edilmesi ortaya çıkıyor
- yarn ve pnpm’e geçildikten sonra bile bazı alt komutlar hâlâ npm’i çağırıyor
- Bazı script’ler hâlâ
watchmankullanıyor- Symlink desteklemediği için kullanılmaması gerektiğini hatırlamak gerekiyor
- İlgili issue 2015’ten beri açık
- gulp tabanlı script’ler de duruyor; daha modern bir şeye geçirmek isteniyor ama kimse değiştirmeye cesaret edemiyor
Paket listesinin tetiklediği travma
dependenciesiçinde çok sayıda paket var ve her paket kendi travma anısını yeniden canlandırıyorleft-padküçük bir paket olsa da “tüm interneti bozan” efsanevi paket olarak kalmış- Bağımlılık listesi her değiştirildiğinde bazı paketler konsola uzun bağış çağrıları veya breaking change uyarıları yazdırıyor
- Geliştirici, kötü amaçlı bir paketin sırları çalmamasını ya da bilgisayarı bozmamasını umar hâle geliyor
- moment.js iyi bir API’ye sahip bir kütüphane olarak hatırlanıyor; ancak internet onun fazla mutable ve büyük olduğuna, treeshaking desteklemediğine hükmetti ve şimdi date-fns’e migrate etmek gerekiyor
- Paket sürümleri güncel kıstasların çok gerisinde ve yükseltilmeleri gerekiyor; fakat geçmişteki upgrade deneyimleri nedeniyle büyük acı bekleniyor
resolutions, paket yükseltmelerinden kaçınmak için seçilmiş bir başka acı olarak kalıyor
Geliştirme araçlarının yarattığı bir başka karmaşıklık
devDependenciese bakınca yalnızca non-dev dependency’lerin gerektiği zamanları hatırlamak zoreslintyapılandırması o kadar katılaşmış ki küçük hatalarda bile kırmızı alt çizgi beliriyor; CI ise lint sorunlarını dünyanın sonu gibi ele alıyor- Ekibin junior mühendisine yanlış bir güven hissi veriyor
- Hangi kuralın açılacağı konusunda birçok kez tartışma yaşanmış
- Kod tabanının dört bir yanındaki
eslint-ignoresayısı kadar acı büyüyor
postcssdoğrudan kullanılmıyor; ancak bir bağımlılığın bağımlılığının gerektirdiği bir paket olarak var- Yeni bir platformda
npm installdenenince her seferinde belirsiz C++ derleme hatalarına yol açıyor
- Yeni bir platformda
jesthızlı bir test runner olarak başladı ama artık büyük ve ağırlaştı; bazı Babel paketlerine bağımlı- Uygulamanın geri kalanı esbuild ve swc kombinasyonuyla transpile ediliyor
- ESM ve TypeScript’e uygun biçimde doğru yapılandırmak “PhD bilim projesi” kadar zor
- Kod tabanında TypeScript, esbuild, swc, babel, eslint, prettier, jest, webpack, rollup, terser gibi birçok araç ve parser yer alıyor
enginesiçindenodebelirtilmiş; Bun veya Deno’ya geçilse bile acının durmayıp daha kötüleşeceği düşünülüyor- Son kapanış süslü parantezine kadar okuduktan sonra sekmeyi kapatıp nefesini topluyor; eli ve beyni sağlam kalarak şimdilik hayatta kalıyor
1 yorum
Hacker News yorumları
Oldukça komik. Yaklaşık 18 yıl JavaScript yazdım ve 3 yıl kadar önce bıraktım; bu listedeki dertlerin çoğu son 10 yılın ürünü
Özellikle 2013'te yazılmış olsaydı mutlaka yer alacak olan polyfill'lerin eksikliği göze çarpıyor. 2013'ün JavaScript kâbuslarından bugün neredeyse ortadan kalkmış başka neler vardı acaba? Tabii onların yerini bu komik liste aldı
En sevdiğim kısım, bir codebase'de çalışan araçları ve parser'ları sayarken TypeScript, esbuild, swc, babel, eslint, prettier, jest, webpack, rollup, terser akla geliyor da, daha fazlasını kaçırıp kaçırmadığını bile öğrenmek istemeyecek kadar acı verici olmasıydı
undefined,with, private field taklidi için closure'lar, değiştirilmiş prototype'lar, varsayılan global değişkenler, çağrıldığı yere göre değişenthis, karşılaştırmada otomatik type coercion…Evet, JavaScript 10+ yıl boyunca tam da böyle geçti
SomeFunction.prototype'ı değiştirerek yapılan sahte sınıflardıBunu hemen çalışan anonim fonksiyonlara sarıp nesne olarak döndürerek,
SomeFunctionbir sınıfmış gibinew SomeFunction()ya daSomeFunction.actualFunction()çağrılmasını sağlıyorduk. Arrow function olmadığı için event'leri scope'a bağlamak adınaFunction.prototype'ın kendisini değiştirip.apply()kullanmak ya da her event callback'inde bitmeyen.bind(this)cehennemine düşmek de ayrı bir derttiBugün bile Promise veya declaration file olmadan saf JavaScript kullanan bir şirketin test ödevini yazma talihsizliğini yaşadım; 2012'de Node ile ilk tanıştığım günlere dönmüş gibi hissettirdi. JavaScript kullanma şartını JSDoc ile aşmaya çalıştım ama hatırladığımdan çok daha kötüymüş
Yeni bir JavaScript, daha doğrusu TypeScript projesi başlatırken her seferinde aynı süreci yaşıyorum
Genelde frontend olduğu için React seçiyorum; Svelte'i de denemek istiyorum doğrusu. Bundler olarak eskiden create-react-app ya da Webpack wrapper'ları vardı ama şimdi az ayar gerektiren ve ana framework'lerin hepsini destekleyen Vite en iyi seçenek gibi
TypeScript compiler'ı kurup ayarlıyorum; çoğu zaman bir template'ten kopyala-yapıştır yapıyorum. Hedefi güncel kararlı JavaScript ve ESM modülleri olarak belirliyorum, eslint ile prettier'ı uyumlu hale getiriyorum ve TypeScript ile React gibi plugin'leri de ekliyorum. Commit öncesi Prettier ve eslint çalıştıran hook'lar da koyuyorum
IDE eklentilerini de kuruyor,
.devcontainerya da önerilen extension listesini hazırlıyorum. Stilin kendisiyle çok ilgilenmiyorum; önemli olan kod tutarlılığı ve hata yakalama, bu yüzden eslint için genelde hazır ayarlar kullanıyorumSonra jest ya da vitest gibi unit test kurulumunu yapıyorum, peşinden TypeScript ayarları ve eslint kuralları da geliyor. CSS framework olarak tailwind'i seviyorum; bu yüzden styled-components ve twin.macro'yu da kurup React ile iyi çalışacak hale getiriyorum, ayrıca Google Fonts plugin'i ya da font kütüphanesi de ekliyorum
Ancak bir gün kadar geçtikten sonra programlamaya başlayabiliyorum. Neden bu kadar çok iş var? Vite + TypeScript + React/Vue/Svelte + eslint/prettier + tailwind/bootstrap + jest/vitest kombinasyonunu kullanan bu kadar çok kişi varken, kullanım senaryolarının %90'ına doğrudan uyan bir sıfır ayar kütüphanesi neden yok?
Toolchain'i bir şekilde ayağa kaldırsam bile kontrolün bende olduğu hissi hiç olmuyordu; en ufak sarsıntıda çökecek ve benim de düzeltemeyeceğim bir şey gibi geliyordu
Son zamanlarda bu JavaScript stack'inin büyük bölümünü yapmak istediğim işin önündeki engel olarak görmeye başladım ve eskisi gibi Flask ile Jinja2 tabanlı server-side rendering uygulamaları yaptım. Modern ve gösterişli değil, CSS'si de yok; o yüzden şu an epey çirkin, ama tamamen modern saf CSS kullanmam önerildi. Yine de o stack'te ne kadar hızlı özellik geliştirebildiğime şaşırdım
package.jsoniçindeki adı değiştiriyorum. Tabii ben daha çok backend yapıyorum ama frontend tarafında da böyle kişisel şablonlar oluşturulamaz mı?npm createyapmıyor mu?npm create vuedersen, ayarların çoğu önceden yapılmış, gayet düzgün ve çalışan bir Vue kurulumu çıkıyor. Boilerplate ve türlü ıvır zıvırın fazla olduğuna katılıyorum ama bugün web'de yaptığımız uygulamalar da eskisine göre çok daha büyük. İstersen sadece ESModules ile, hiç araç kullanmadan JavaScript yazabilirsin; ama insanlar bunu pek yapmıyor çünkü bu araçlar gerçekten bir şeyler sağlıyor. En temiz yöntem olmayabilir ama sonuçta çalışıyorYeni proje başlatırken onu clone'layıp birkaç yerde adı değiştirmen yeterli olur
Bu, insanların JavaScript dediği ama aslında “Node ekosistemindeki ıvır zıvır”ı kastettiği başka bir örnek
Daha başında
package.jsondosyasını açıp okuman gerektiğini söylüyor ve sonrası da hep o çizgide ilerliyor. Bahsedilen şeylerin neredeyse hiçbiri JavaScript’in kendisiyle ilgili değilJavaScript ile NodeJS’in aynı şey olmadığı doğru, ama çoğu kişi yazarın ne demek istediğini anlamıştır. Daha doğru yazılsa iyi olurdu ama tamamen yanlış demek de zor
package.jsonkullanan bir bundler olmadan gerçekten JavaScript yazmayı dene. ECMA resmî spesifikasyona bir paket yöneticisi ya da bundler ekleyene kadarpackage.jsonfiilen JavaScript’in bir parçasıŞakacı tonu hoşuma gitti. Cildin ve sinir uçların birkaç kat yandıktan sonra, bu tür acı noktalarını yeniden hatırlamak faydalı oluyor
Tersinden bakarsak, hevesli bir junior geliştiriciye yeni bir MacBook verip derin suya atsan bile bir gün içinde üretken olabilir. Container’ları, .NET’i, nginx’i, sık kullanılan 100 komut satırı aracını bilmesine gerek yok; bir sorun olursa da aratır geçer
Elinle dokunabilsen birkaç günde bütün gemiyi yapabileceğini bildiğin hâlde, sana verilen özensiz araçlarla şişedeki gemiyi tamir eder gibi gereksiz karmaşıklık katmanlarıyla boğuşuyorsun. Yalnızca JavaScript, HTML ve CSS kullandığın kişisel projelerde hızlı ilerlerken modern frontend işine sokulunca his tam olarak böyle
Onu yapmanın aylar süreceğini ve sorunun bir kısmının zaten framework fazlalığı olduğunu, ayrıca ertesi gün eskiyeceğini safça bilmiyorlar
“Anlatıldığı gibi yaptım ve grunt’ın kurulu olmadığını söyledi. Ben artık yaşlı bir adamım, o yüzden grunt’ın ne olduğunu pek bilmiyordum, bir de benim grunt dosyamda bir şeyler tutmuyordu. Biraz aradım ve grunt’ın ne olduğunu öğrendim. Grunt... aslında hâlâ tam olarak ne olduğunu bilmiyorum.”
--Joe Armstrong, https://www.youtube.com/watch?v=lKXe3HUG2l4
Birkaç gün önce
gem install wayback_machine_downloaderçalıştırdım. Ruby adlı dili, kendi ekosistemine girecek kadar hiç sevmedim ama dışarıdan bakınca o ekosistem şaşırtıcı derecede istikrarlı korunmuş gibi görünüyor. gem hâlâ kullanılan bir araç, Rails de hâlâ ortadaKarmaşık bir frontend gerektiren ve JavaScript’in 0–30 satırını aşacak yeni bir proje bekliyorum. O zamanlar, günün en popüler dev framework’ü yerine HTMX ile daha mutlu olabilirim gibi geliyor
Bu yazı JavaScript hakkında değil, npm hakkında
Bu tür ıvır zıvırlar yüzünden npm’den nefret ediyorum ve mümkün olduğunca kaçınıyorum. Kişisel olarak Deno kullanıyorum; işte ise npm gerektirmeyen, monorepo tabanlı, bazel benzeri bir şey kullanıyoruz
Ama JavaScript/TypeScript’in programlama yapmak için hoş diller olduğunu düşünüyorum ve ne inşa edecek olursam olayım ilk seçtiğim dil bunlar oluyor. İnsanların “JavaScript berbat” deyip aslında React uygulamasını npm ile build etmenin berbat olduğunu kastetmesi üzücü. Modern JavaScript/TypeScript ile kod yazmak gerçekten keyifli
Sanki JavaScript ve ekosistemi hepimize PTSD bıraktığı için bu yazıdaki komedinin tadını çıkaramıyoruz
Komik bir yazının altında fazla sayıda “ciddi” tartışma var. İsteyen istediği kadar didik didik etsin ama asıl niyetin mizah olduğunu akılda tutmak iyi olur
Dürüst olmak gerekirse, ilk başladığım ekosistem Node’du ve sonradan öğrendiğim şeylerin de her birinin yeterince çılgın sorunları vardı
Haskell’i farklı makinelerde kullanmak çok zordu; 2019’da MacOS’e kurmak da işkenceydi ve ekosistemi yönetmek de zordu. Makrolar ve eklentiler ciddi biçimde kafa karıştırıcı, dilin geriye dönük uyumluluğu da pek iyi değil. Buna karşılık 2010’daki JavaScript’in çoğunlukla 2023’te de çalışmasını beklersin
Docker imajı ya da codespace/gitpod benzeri bir ortamı düzgün kurmak bile zor; GitHub’ın verdiği varsayılan imaj da pek iyi değil ve sorunlu
C çoğu platformda genel olarak fena değil ama dilin kendisi dürüst olmak gerekirse karmaşık ve tüm sistem hakkında geniş bilgi gerektiriyor. Sonuç olarak, genel programlamanın çoğu kullanımına uymayan ve taşınabilirliği düşük kod üretmek kolaylaşıyor
Daha da sayabilirim ama birkaç dil kullanmış herkes, her ekosistemin çeşitli kusurları olduğunu ve hepimizin acı çekmeye devam ettiğini bilir. PHP’de proje kurulumunu birkaç gün içinde bitirebildiğim pek olmadı; Elm daha az acı veriyor ama onun da iyi niyetli diktatörlük durumu ve geliştirme hızı gibi kendi sorunları var
Çeşitli programlama paradigmaları ve dilleriyle, hem frontend hem backend tarafında rahat olduğunu düşünen bir çok dilli geliştirici
package.jsondosyasının 20 satırı geçtiğini her gördüğümde neredeyse tam olarak böyle tepki veriyorumpackage.jsondosyası 200 satırı aşıyorSanki şeytanı uzak tutmaya çalışıyormuş gibi yüksek sesle söylüyor. “Korkmamalıyım. Korku zihin katilidir. Korku, bütünüyle yok oluşu getiren küçük ölümdür. Korkumla yüzleşeceğim. Onun içimden geçip gitmesine izin vereceğim. Geçip gittikten sonra, onun izlediği yolu zihnimin gözüyle göreceğim. Korkunun geçtiği yerde hiçbir şey kalmayacak. Yalnızca ben kalacağım.”
Ağlıyor
hackernewsers'ı hiç kullanmadım, bu yüzden normal davranış mı bilmiyorumEski usul JavaScript geliştiricisi yazıyı okurken PTSD ve flashback'lerle acı çekiyor
Korkmamalıyım. Korku zihin katilidir. Korku, bütünüyle yok oluşu getiren küçük ölümdür
Korkumla yüzleşeceğim. Onun içimden geçip gitmesine izin vereceğim. Geçip gittikten sonra, onun izlediği yolu zihnimin gözüyle göreceğim
Korkunun geçtiği yerde hiçbir şey kalmayacak. Yalnızca ben kalacağım
Yazının tamamını okuyup hayatta kaldığını fark ediyor, ama çoktan sırılsıklam ter içinde kalmış