Webpack 4'den 5'e Geçiş
2020'nin Kasım aylarında Webpack ekibinin duyurusuyla Webpack 5 sürümü yayımlanmış oldu. Aşağıda bahsedeceğim bir çok değişikliğin yanında özellikle micro front-end yapısını hedefleyen uygulamalar için büyük kolaylık sağlayan Module Federation özelliğinin sunulması Webpack 5'e olan ilgiyi artırmış gözüküyor. Konfigürasyonların sadeleşmesi ve hissedilir performans artışı benim bu güncellemedeki en sevdiğim noktalar oldu. Şu anda bir parçası olduğum OPLOG’un front-end ekibi(Team Picasso) olarak projelerimizi güncel tutmak ve scalibility adına alt yapımızı micro front-end’e hazırlamak için bu güncellemeyi hayata geçirdik.
Bu makalede Webpack 5'in sunduğu değişiklikler ve yeniliklerden bahsettikden sonra, Webpack 4'den Webpack 5'e geçerken izlediğim yolları, webpack ve webpack-dev-server konfigürasyonları üzerinde yaptığım değişiklikleri paylaşacağım.
Webpack için 5. major güncelleme 2 yılın ardından bir çok değişiklikler ile geldi. Hadi bu yeniliklerden konuşalım.
Webpack 5'deki yenilikler
Bu değişikleri belli genel başlıklar altında toplayabiliriz.
Kalıcı çerezleme(Persistent Caching) ile daha hızlı yapılandırma
Bir çok önyüz geliştiricinin popüler problemlerinden biri de uzun yapılandırma süreleridir. Webpack 5, module paketleyicinin önerdiği dahili dosya sistemi çerezleri ile geliştirme ortamındaki yapılandırma sürelerimizi azaltarak üretkenliğimizi artırıyor.
Daha küçük paket boyutları
Ölü kod eleme sisteminde iyileştirmeler yapıldı. Önceki webpack sürümlerinde de çalışan ölü kod eleme algoritması (tree shaking), webpack 5 ile daha da ileri gitti. Modüllerin içerisindeki ölü kod bloklarını da eleyerek daha da küçük paket boyutlarına ulaşmamızı sağlıyor.
Daha iyi uzun-vadeli çerezler
Daha küçük paketleri elde ettikden sonra uygulamamızın yüklenme süresini hızlandırabileceğimiz en etkili yol çerezlerdir. Doğru bir çerezleme ile geri dönen ziyaretçileriniz neredeyse hiç yüklenme süresi beklemeyeceklerdir. Webpack 5 ile birlikte ufaltılmış(minimized) kodunuza etki etmeyen kod değişiklikleri(yorumlar, değişken isimleri vs.) çerezlerinizi geçersiz kılmayacaklar. Bu da kullanıcılarımızın daha uzun süre hızlı bir uygulama deneyimi yaşayacaklarını sağlayacaktır.
Daha büyük iyileştirmeleri mümkün kılacak köklü değişiklikler
Şu an için gözle görülür bir iyileştirme sağlamasalar da yarattıkları altyapılar ile ilerleyen vakitlerde büyük iyileştirmelere zemin hazırlayan bazı değişikler de webpack 5 kapsamında yayımlandı.
Webpack artık minimum Node.JS versiyonu olarak 10.13.0
ı destekliyor.
experiments
konfigürasyonu ile birlikte WebAssembly, Asenkron Web Assembly, Üst Seviye Bekleme (Top Level Await) ve paketlerinizi modül olarak dışarı çıkarmak mümkün hale geldi.
Modül Birliği (Module Federation)
Bu yeni özellikle birlikte birden çok derlemenin birlikte çalışması mümkün hale geliyor. Bu özellik uygulamanızın diğer uygulamalardan (diğer webpack derlemesinden) dinamik olarak kod yükleyebilmesini sağlıyor. Module federationın en yaygın uygulama alanı mikro önyüz yapısıdır. Module federation hakkında daha detaylı bilgi sahibi olmak istiyorsanız, şu resmi makaleyi okuyabilirsiniz.
Köklü değişiklikler
Deprecated Araçlar Silindi
Webpack 4'de deprecated uyarısı veren tüm araçlar silinmiş durumda. Versiyonu 5'e çekmeden bu uyarıları adreslediğinizden emin olun.
Gömülü(built-in) eklentilerdeki değişiklikler
Bazı eklentiler öncekine göre farklı argümanlar kabul ediyorlar, aşağıda bahsedeceğim üzere ya da migrasyon yönelgesini takip ederek bunları gerçekleştirmeniz gerekiyor.
Node.JS polyfilleri silindi
Önceki versiyonlarda crypto
gibi doğal NodeJS kütüphaneleri dahil haldeydi. Bunlar Webpack 5 ile birlikte silindi. Bunlar yerine önyüz odaklı kütüphaneler kullanmalı veya bu polyfilleri kendiniz yüklemelisiniz.
Adım Adım Göç Senaryosu
Webpack
Bildiğiniz üzere webpack konfigürasyonları farklı istekler doğrultusunda bir çok eklentiyle desteklenerek karmaşık bir yapıya bürünebiliyor. Webpack 4'den 5'e göç ederken bu yan etkileri dikkatlice ele almak gerekiyor.
Öncelikle Webpack versiyonumuzu güncelleyerek işe başlayalım.
npm install webpack@latest
ya da
yarn add webpack@latest
Daha sonra konfigürasyonlarda kullandığımız yan paketleri güncellemeden önce webpack.config.js dosyamızı güncelleyelim. Webpack 5'in getirdiği sadeleştirmeler ve farklı varlık yönetimi(asset management) tarzı ile versiyon 4'de kullanmakta olduğumuz eklentilerden bazıları gereksiz hale gelecek. Bunları kaldırıp, geri kalan eklentileri de Webpack 5'e uyumluluk kapsamında son versiyonlarına güncellememiz gerekecek (bu tüm paketler için zorunlu bir hamle değil fakat uygulamamızın güncel kalabilmesi için güzel bir fırsat).
Kendi projemiz için kullandığımız webpack konfigürasyonunun versiyon 4 ve 5 için oluşan halini paylaşıp, daha sonra bu göç hareketi için takip ettiğim kural dizininden adım adım bahsedeceğim.
Burada Webpack konfigürasyonu yapılan uygulama TypeScript ile ReactJS kullanılarak geliştirilen bir yapıya sahip.
webpack.config.js
versiyon 4.* örneği:
webpack.config.js
versiyon 5.* örneği:
Webpack 4'den 5'e geçişte izlenmesi gereken noktalar:
- NodeJS versiyonunuzun en az
10.13.0
olduğundan emin olun. mode
tercihinizinproduction
veyadevelopment
a eşitlendiğinden emin olun.optimization.moduleIds
veoptimization.chunkIds
seçeneklerini kaldırmayı tercih edin. Varsayılan ayarlar daha iyi sonuç almanızı sağlayacaktır (production modunda uzun-vadeli çerezleri aktif ederken, geliştirme ortamında debug modunu destekliyorlar).[hash]
yertutucularınızı[contenthash]
ile değiştirin. Aynı değiller ama daha etkili olduğu kanıtlandı.- Eğer Yarn’ın PnP eklentisini kullanıyorsanız (
pnp-webpack-plugin
) artık varsayılan olarak bu destekleniyor. Bu eklentiyi konfigürasyondan kaldırabilirsiniz. - Eğer
IgnorePlugin
i regular expression ile kullanıyorsanız bunu artık seçenek objesi olarak vermeniz gerekiyor:new IgnorePlugin({ resourceRegExp: /regExp/ })
. - Eğer
node.fs: 'empty'
gibi bir yapı kullanıyorsanız bunu şununla değiştirin:resolve.fallback.fs: false
. - Eğer
raw-loader
,url-loader
vefile-loader
kullanarak asset yüklemesi içinrules
tanımlamaları yapıldıysa bunları Asset Modülünü kullanarak sağlamak daha doğru olacaktır. Bu loaderlar ilerleyen zamanlarda atıl hale gelecekler. - Eğer
target
seçeneğiniz bir fonksiyona eşitse bunufalse
a eşitleyip fonksiyonunuzuplugins
seçeneğinin altına taşıyın. - Webpack ekibi tarafından
splitChunks
seçeneği için ya varsayılan seçeneğin kullanılması ya daoptimization.splitChunks: { chunks: 'all' }
şeklinde kullanılması öneriliyor.
Aşağıdaki tercihlerinizi yenileriyle güncellemelisiniz:
optimization.hashedModuleIds: true
→optimization.moduleIds: 'deterministic'
optimization.namedChunks: true
→optimization.chunkIds: 'named'
optimization.namedModules: true
→optimization.moduleIds: 'named'
NamedModulesPlugin
→optimization.moduleIds: 'named'
NamedChunksPlugin
→optimization.chunkIds: 'named'
HashedModuleIdsPlugin
→optimization.moduleIds: 'deterministic'
optimization.noEmitOnErrors: false
→optimization.emitOnErrors: true
optimization.occurrenceOrder: true
→optimization: { chunkIds: 'total-size', moduleIds: 'size' }
optimization.splitChunks.cacheGroups.vendors
→optimization.splitChunks.cacheGroups.defaultVendors
Compilation.entries
→Compilation.entryDependencies
serve
seçeneği silindi yerineDevServer
seçeneği geldi
Bu değişiklikleri uyguladığınızda bazı yükleyicilerinizin (loaders) ve eklentilerinizin boşa çıktığını farketedeceksiniz. Onları bağımlılıklardan kaldırıp, diğer kullanılan eklenti ve yükleyicileri mümkün olan en güncel seviyeye çekmeye çalışın.
Bazı kütüphaneler için webpack 5'e uyumluluk açısından beta versiyonlarını yüklemeniz gerekebilir.
Bizim projemizde package.json’da gerçekleşen durumu paylaşmam gerekirse:
Kaldırılan Eklentiler: workbox-webpack-plugin, @babel/plugin-transform-react-jsx, eslint-loader, file-loader, fork-ts-checker-webpack-plugin-alt, pnp-webpack-plugin, url-loader
Son Versiyona Çekilen Eklentiler: @svgr/webpack, babel-preset-react-app, case-sensitive-paths-webpack-plugin, fork-ts-checker-webpack-plugin, eslint-webpack-plugin, html-webpack-plugin, mini-css-extract-plugin, react-dev-utils, terser-webpack-plugin, ts-loader, webpack, webpack-bundle-analyzer, webpack-dev-server, webpack-manifest-plugin
Webpack Dev Server
Webpack 5 ile uyumluluk açısından webpack-dev-server
kütüphanesinin de versiyon 4'e yükseltilmesi gerekiyor. Aksi takdirde zaman zaman beliren Failed to compile.
hatası ve hot-reload özelliğini kaybediyorsunuz.
Öncelikle webpack-dev-server versiyonunu 3.11.2
den 4.0.0-beta.2
ye yükseltelim.
npm install webpack-dev-server@4.0.0-beta.2 --save-dev
ya da
yarn add -D webpack-dev-server@4.0.0-beta.2
Sadece paket versiyonu yükseltme ile işimiz bitmiyor. Webpack dev server webpack 5 ile uyumlu olmakla kalmamış, konfigürasyonlarında sadeliğe gitmiş ve bir çok iyileştirme yapmış. Aşağıda detaylıca açıklayacağım bu değişikliklerin konfigürasyon dosyasında yaptığı değişiklikleri görebilirsiniz.
webpack-dev-server versiyon 3.* konfigürasyon dosyası örneği:
webpack-dev-server versiyon 4.* konfigürasyon dosyası örneği:
webpack-dev-server 4 ile gelen değişiklikler:
- Minimum desteklenen Node versiyonu 10'a yükseldi.
hot
seçeneği varsayılan olarak açık işaretlendi.hotOnly
seçeneği kaldırıldı. Bu mod içinhot: 'only'
tercihini kullanabilirsiniz.- Varsayılan
transportMode
sockjs
denws
e çevrildi. before
,after
vesetup
seçenekleri kaldırıldı. Bunlar yerineonBeforeSetupMiddleware
(öncekibefore
) veonAfterSetupMiddleware
(öncekiafter
) geldi.clientOptions
seçeneğiclient
olarak değiştirildi.key
,cert
,pfx
,pfx-passphrase
,cacert
verequestCert
seçeneklerihttps
seçeneğinin altına taşındı.sockHost
,sockPath
vesockPort
seçeneklericlient
dan kaldırıldı.inline
seçeneği kaldırıldı.lazy
vefilename
seçenekleri kaldırıldı.features
seçeneği kaldırıldı.log
,logLevel
,logTime
,noInfo
,quiet
,reporter
vewarn
seçenekleri kaldırıldı. Bu seçeneklerin sağladığı özellikler webpack’in gömülü loglama sistemiyle elde edilebilir. Şu yazıyı okuyup loglamayı kurup etkinleştirebilirsiniz.fs
,index
,mimeTypes
,publicPath
,serverSideRender
vewriteToDisk
seçenekleridev
seçeneğinin altına taşındı.stats
seçeneği kaldırıldı. webpack konfigürasyonundakistat
seçeneğiyle gerekli ayarlamalar yapılabilir.socket
seçeneği kaldırıldı.contentBase
,contentBasePublicPath
,serveIndex
,staticOptions
,watchContentBase
,watchOptions
seçenekleri yenistatic
seçeneği altına alındı.disableHostCheck
veallowedHosts
seçenekleri yenifirewall
seçeneği altına taşındı.server.listen()
eğer bir port ayarlanmamış veya arguman olarak verilmemişse, müsait bir portu kendisi bulacaktır.progress
seçeneğiclient
seçeneğinin altına taşındı.profile
seçeneği kaldırıldı. Profil verisini yazdırmak içinclient: { progress: 'profile' }
ayarlamasını yapabilirsiniz.
Tüm bunları düzenledikten sonra bir ufak düzenleme daha yapmanız gerekebilir. Bilinen bir bug olan;
TypeError: message.split is not a function
hatasıyla karşılaşabilirsiniz. Bu hata webpack 5 güncellemesine henüz adapte olamamış react-dev-utils
kütüphanesi ile alakalı. Daha sonra düzeleceği kesin olsa da bu geçiş döneminde bir workaround çözüm oluşturduk.
Öncelikle npm scriptlerinizi oluşturduğunuz klasörün içerisinde postinstall.js
dosyası oluşturun ve içerisine şunu ekleyin;
Daha sonra bunu npm install
sonrası çalışması üzere package.json scriptlerine ekleyin.
"scripts": {
... "postinstall": "node scripts/postinstall.js",...
},
Her npm bağımlılıklarını yüklediğinizde bu script gerekli düzeltmeyi yapıp probleminizi çözmüş olacaktır.
Peki bu değişiklik ne gibi bir fayda sağladı ?
Aşağıda kendi projemiz olan Maestro üzerinde Webpack versiyon 4'den 5'e yükseltmenin(TypeScript versiyonu da 3'den 4'e alındı fakat performans olarak bir etkisi olduğunu pek düşünmüyorum) performans indikatörleri üzerinde yaptığı değişiklikleri paylaşıyorum. İndikatörlerin yanı sıra hissedilebilir bir son kullanıcı ve geliştirici deneyimi iyileşmesi olduğu aşikar.
Webpack 5 ilk duyduğumda bende yarattığı heyecanın karşılığını vermiş gözüküyor. Ayrıca sağladığı yeni altyapı ile daha keskin gelişmelere olanak sağlayacak gibi.
Bu versiyon yükseltmesi görüldüğü kadar sancılı olmayabilir. Hatta eski versiyonlarda kalmış kütüphanelerinizin güncellenmesi adına iyi bir fırsat olduğunu düşünüyorum.
Kaynaklar
https://webpack.js.org/blog/2020-10-10-webpack-5-release/
https://webpack.js.org/migrate/5/
https://frontend-digest.com/whats-new-in-webpack-5-ef619bb74fae