Türkçe
  • parcel
  • vite
  • js
  • esbuild
  • bundler
  • monorepo

Parcel'dan Vite'a: 100K LOC geçişinin kısa hikayesi

Üç ön yüz projemizi Parcel'dan Vite'a geçirdik ve süreç... sorunsuz geçti.

Gao
Gao
Founder

Arka plan hikayesi

Logto'da üç ana ön yüz projemiz var: giriş deneyimi, Konsol ve canlı önizleme. Bu projelerin hepsi TypeScript, React ve SASS modüllerini kullanmakta; toplamda yaklaşık 100K satırlık koddan oluşuyorlar.

Parcel'ı basitliği ve sıfır yapılandırma ile kullanıma hazır olması nedeniyle çok sevdik. Parcel ile yeni bir proje kurmanın ne kadar kolay olduğuna şaşırdığım günü hala hatırlayabiliyorum. Sadece parcel index.html komutunu çalıştırıyorsunuz ve bum, gerekli tüm bağımlılıklar yükleniyor ve proje çalışıyor. Eğer "deneyimli" bir geliştiriciyseniz, bu durumu Gulp ve Webpack ile kurulum yapmanın eski günleriyle karşılaştırdığınızda aynı şekilde hissedebilirsiniz. Parcel sihirli bir değnek gibi.

Parcel'ın sadeliği, onu bu kadar uzun süre kullanmamızın ana nedeniydi, ancak bazen huysuz olabiliyordu. Örneğin:

  • Parcel, aslında orada olan bazı parça dosyalarını bulamadığı için projeyi derlemekte başarısız olabiliyordu.
  • Monorepo kurulumumuzla çalışması için bazı hileli yapılandırmalar gerekiyordu.
  • MDX 3'ü yerel olarak desteklemiyor, bu yüzden onun için özel bir dönüştürücü oluşturmamız gerekiyordu.
  • Manuel parçaları desteklemiyor (bu yazının yazıldığı dönemde manuel parça özelliği hala deneysel aşamada), bu çoğu durumda sorun değil, ancak bazen buna ihtiyaç duyulabiliyor.

Peki neden başka bir şeye geçmeye karar verdik?

  1. Haziran 2023'te yayımlanan Parcel 2.9.3 sürümüne takılıp kaldık. O zamandan sonra her yeni sürüm çıktığında denedik fakat her zaman derleme hataları ile karşılaştık.
  2. Parcel'ın en son sürümü Şubat 2024'te yayımlanan 2.12.0'ydı. Neredeyse her gün yeni commitler olsa da, o zamandan bugüne kadar yeni bir sürüm yayımlanmadı.

Birisi, Parcel öldü mü diye bir tartışma bile başlattı. Resmi cevap hayır, Parcel hala hayatta, ama üzerinde büyük bir yeniden yapılanma çalışıyoruz ve küçük sürümler için zamanımız yok halinde. Bizim için bu durum "ördek ölümü" gibiydi: Kullanabileceğimiz en son sürüm bir yıldan daha eskiydi ve bir sonraki sürümün ne zaman çıkacağı hakkında hiçbir bilgimiz yoktu. Ölmüş gibi görünüyor, ölmüş gibi davranıyor, bu nedenle bizim için ölmüş durumda.

Parcel yükseltme istekleri

Bana güvenin, denedik.

Neden Vite?

Vite'i Vitest sayesinde tanıdık. Birkaç ay önce, Jest'in ESM desteğinden (testlerde) bıktık ve yeni bir şey denemek istedik. Vitest, yerel ESM desteği ve Jest uyumluluğu ile kalplerimizi kazandı. Harika bir geliştirici deneyimi sunuyor ve Vite tarafından destekleniyor.

Mevcut durum

Projenizde farklı ayarlar olabilir, ama genellikle Vite ekosistemi geliştiği için eklenti ikameleri bulursunuz. İşte geçiş sırasında kullandığımız ayarlar:

  • Monorepo: Monorepo'muzu yönetmek için PNPM (v9) çalışma alanlarını kullanıyoruz.
  • Modül: Tüm projelerimiz için ESM modüllerini kullanıyoruz.
  • TypeScript: Tüm projelerimizde yol takma adları ile TypeScript (v5.5.3) kullanıyoruz.
  • React: Tüm ön yüz projelerimizde React (v18.3.1) kullanıyoruz.
  • Stil: Tarzlama için SASS modüllerini kullanıyoruz.
  • SVG: SVG'leri React bileşenleri olarak kullanıyoruz.
  • MDX: GitHub Tarzı Markdown ve Mermaid desteği ile MDX kullanıyoruz.
  • Tembel yükleme: Bazı sayfalarımızı ve bileşenlerimizi tembel yüklememiz gerekiyor.
  • Sıkıştırma: Üretim derlemeleri için sıkıştırılmış varlıklar (gzip ve brotli) üretiyoruz.

Geçiş

Geçişe yeni bir Vite projesi oluşturarak ve nasıl çalıştığını görmek için etkileşimde bulunarak başladık. Süreç sorunsuz geçti ve gerçek geçiş sadece birkaç gün sürdü.

Hazır destek

Vite, monorepo, ESM, TypeScript, React ve SASS için yerleşik desteğe sahip. Sadece gerekli eklentileri ve yapılandırmaları kurmak yeterliydi.

Yol takma adları

Vite, yol takma adları için yerleşik desteğe sahiptir, örneğin tsconfig.json dosyamızda:

Sadece vite.config.ts dosyamızda aynı çözümlemeyi eklememiz yeterli oldu:

Dikkat edilmesi gereken nokta: Değiştirilen yolun proje köküne göre göreli olmasının yanında, mutlak yol olması gerekir. Alternatif olarak, vite-tsconfig-paths eklentisini kullanarak yol takma adlarını tsconfig.json dosyasından okuyabilirsiniz.

React Fast Refresh ve HMR

Vite, HMR için yerleşik desteğe sahip olsa da, React Fast Refresh'i etkinleştirmek için bir eklenti kurulması gereklidir. Vite ekibi tarafından sağlanan ve Fast Refresh gibi React özellikleri için mükemmel destek sunan @vitejs/plugin-react eklentisini kullandık:

SVG'yi React bileşeni olarak kullanma

SVG'leri React bileşenlerine dönüştürmek için vite-plugin-svgr eklentisini kullandık. Vite yapılandırmasına eklentiyi eklemek kadar basit:

Ancak, SVG'lerin hangi koşulda React bileşenlerine dönüştürüleceğini belirtmedik, bu nedenle tüm ithalatlar dönüştürüldü. Eklenti, yalnızca .svg?react uzantısıyla ithal edilen SVG'leri dönüştürmeyi öneren daha iyi bir varsayılan yapılandırma sunuyor. İthalatlarımızı buna göre güncelledik.

SASS modülleri

Vite, SASS modülleri için yerleşik desteğe sahip olsa da, üzerinde durmamız gereken bir konu var: sınıf adlarının nasıl biçimlendirildiği. Sınıf adları tutarlı bir şekilde biçimlendirilmediğinde kullanıcılar ve entegrasyon testleri için sorun yaratabilir. vite.config.ts dosyasındaki tek satırlık yapılandırma bu sorunu çözebilir:

Bu arada, Parcel ve Vite'in SASS dosyalarını ithalatlarındaki bazı farkları vardır:

* as sözdizimi Vite'de çalışır, ancak styles nesnesine dinamik anahtarlar kullanarak erişirken modüler sınıf adlarının kaybına neden olur. Örneğin:

MDX desteği

Vite, kaputun altında Rollup kullandığından, MDX ve eklentilerini desteklemek için resmi @mdx-js/rollup eklentisini kullanabiliriz. Yapılandırma şu şekildedir:

remarkGfm eklentisi, GitHub Tarzı Markdown'u desteklemek için kullanılır ve rehypeMdxCodeProps eklentisi, MDX dosyalarında kod bloklarına prop'ları vermek için kullanılır; bu özellik Docusaurus'un yaptığı gibi çalışır.

MDX içerisinde Mermaid desteği

MDX dosyalarımızda diğer programlama dilleri gibi Mermaid diyagramlarını kullanmak istiyoruz. Kullanımı diğer kod blokları kadar basit olmalıdır:

Şu şekilde render edilmelidir:

Uygulamamız açık ve koyu temaları desteklediğinden, Mermaid diyagramlarının koyu temayla çalışması için biraz kodlama yaptık. Bir React bileşeni oluşturduk:

useTheme mevcut temayı bağlamdan almak için kullanılan özel bir hook'tur. mermaid kütüphanesi, ilk sayfa yükleme boyutunu azaltmak için asenkron olarak yüklenir.

MDX dosyasındaki kod bloğu için, işi yapmak için birleşik bir bileşene sahibiz:

Sonunda MDX sağlayıcısını şu şekilde tanımlıyoruz:

Tembel yükleme

Bu Vite'e özgü bir şey değil, ancak geçiş sırasında sayfalarımızı tembel yüklemeye güncellediğimiz için ve hiçbir şey bozulmadığı için bahsetmeye değer.

React, bileşenleri tembel yüklemek için yerleşik bir React.lazy işlevine sahiptir. Ancak, hızlı iterasyon yaparken bazı sorunlara neden olabilir. Bu sorunları çözmek için react-safe-lazy adında küçük bir kütüphane geliştirdik. Bu, React.lazy için bir bırakma değiştiricidir ve bu blog gönderisinde ayrıntılı bir açıklama bulabilirsiniz.

Sıkıştırma

Üretim varlıklarını sıkıştırmak için vite-plugin-compression adlı güzel bir eklenti bulunuyor. Hem gzip hem de brotli sıkıştırmasını destekliyor. Yapılandırma basit:

Manuel parçalar

Vite'in (veya alttaki Rollup'ın) harika özelliklerinden biri manuel parçalardır. React.lazy bileşenleri tembel yüklemek için kullanılırken, hangi bileşenlerin veya modüllerin birlikte paketlenmesi gerektiğine karar vermek için manuel parçaları belirleyerek parçalar üzerinde daha fazla kontrol sağlayabiliriz.

Örneğin, önce vite-bundle-visualizer kullanarak paket boyutunu ve bağımlılıkları analiz edebiliriz. Ardından parçaları bölmek için uygun bir işlev yazabiliriz:

Geliştirme sunucusu

Üretim derlemesinin aksine, Vite geliştirici modunda kaynak kodunuzu DERLEMEZ (aynı monorepo'daki bağlı bağımlılıklar dahil) ve her modülü bir dosya olarak ele alır. Bizim için tarayıcı, ilk kez yüzlerce modül yükleyecektir, bu çılgınca görünebilir ama aslında çoğu durumda bir sorun değildir. Tartışmaya buradan göz atabilirsiniz.

Bu sizin için bir sorun ise, mükemmel olmayan alternatif bir çözüm vite.config.ts dosyasındaki optimizeDeps seçeneğinde bağlı bağımlılıkları listelemektir:

Bu, bağlı bağımlılıkları "ön-derleyecek" ve geliştirme sunucusunu daha hızlı hale getirecektir. Dezavantajı ise bağlı bağımlılıklar için HMR'ın beklendiği gibi çalışmama olasılığıdır.

Ayrıca, üretimde statik dosyaları sunan ve geliştirme sırasında istekleri Vitest sunucusuna yönlendiren bir proxy kullanıyoruz. Çakışmalardan kaçınmak için belirli portları yapılandırdık ve vite.config.ts dosyasını ayarlamak da oldukça kolay:

Ortam değişkenleri

Parcel'dan farklı olarak, Vite, import.meta.env kullanarak ortam değişkenlerini modern bir yaklaşımla ele alır. .env dosyalarını otomatik olarak yükler ve koddaki değişkenleri değiştirir. Ancak, tüm ortam değişkenlerinin VITE_ (yapılandırılabilir) önekiyle başlaması gerekir.

Parcel'ı kullanırken, sadece önek kontrolü yapmadan process.env değişkenlerini değiştiriyordu. Bu nedenle, geçişi kolaylaştırmak için define alanını kullanarak bir çözüm bulduk:

Bu, ortam değişkenlerine yavaş yavaş önek eklememize ve define alanını kaldırmamıza olanak tanır.

Sonuç

Hepsi bu kadar! Üç ön yüz projemizi Parcel'dan Vite'a başarılı bir şekilde geçirdik ve umarız bu kısa hikaye, sizin geçişinize de yardımcı olur. İşte son yapılandırmanın nasıl göründüğü: