Angular Kütüphanesinden (Library) Bir Bileşen Paketi Oluşturmak ve Yayınlamak — Tüm Detaylarıyla

Erman Enginler
HAVELSAN
Published in
8 min readMar 7, 2023

Merhaba,
Bu makalede bir Angular Kütüphanesi’nin (Angular Library) nasıl oluşturulacağını, kütüphane ile çalışırken nelere dikkat etmemiz gerektiğini, bu kütüphaneden nasıl npm paketi (npm package) oluşturacağımızı ve oluşturduğumuz bu paketi nasıl yayınlayacağımızı (publish) göreceğiz.

Çok Uzun Özet Geç!
Bir bileşeni npm paketi haline getirip npmjs paket havuzuna yükleyeceğiz.
İstediğimiz bir projede de bu paketi yükleyip (npm install) kullanabileceğiz.

Düşünün ki birden çok projeniz var ve bu projeler arasında kullanacağınız bileşenleriniz var. Bu bileşenleri elbette ki projeler arasında paylaşarak kullanabilirsiniz fakat proje sayısı çoğaldıkça ve proje kapsamları genişledikçe bu bileşenleri projeler arasında senkronize bir şekilde tutmanız zor olacaktır. Bileşeni geliştirdiğiniz bir proje olacak. Bir bileşende değişiklik yaptığınızda da bunu projeler arasında ya kopyala-yapıştır yaparak ya da değişiklik yaptığınız mikro noktaları diğer projelerde de uygulayarak yapmalısınız. Bu durumda bir sorun daha çıkıyor. Değişiklik yaptığınız her projeyi tekrar commit - push - pull/merge request(PR) - CI/CD döngüsüne sokmanız ve varsa unit-test / code-review süreçlerinden geçirmeniz gerekiyor. Burada birden çok projeden bahsettiğimizi tekrar hatırlatmak isterim.

Ayrıca bir problem daha var. Projeler zaman içerisinde farklı versiyon yükseltmeleri (update) yapabilir. Örneğin, bir proje Angular 10 ve buna uygun paketleri kullanırken diğer bir proje Angular 14 olabilir. Bu durumda da geliştirdiğimiz tek bir bileşeni her farklı proje için uyumlu hale getirmeye çalışacağız. Bu durumda farklı projelere farklı bileşen versiyonu verme ihtiyacı doğacak.

Bu durumları çözmek için bileşenimizi kütüphane olarak oluşturup, paketleyip bir versiyon numarası veriyoruz ve tüketeceğimiz projelere yükleyerek kullanabiliyoruz. Farklı projeler için de farklı versiyonda paket verebiliyoruz. Bileşende bir güncelleme yaptığımızda da kullanan projeler sadece package.json'da ilgili versiyona geçerek güncelleme işlemini sorunsuz bir şekilde yapıyorlar. Bu sayede sadece geliştirilen kütüphane paketi düzgün test edilip sorunsuz build olup yayınlandıysa diğer projeler içinde insan kaynaklı (kopyala-yapıştır) kod hataları olmayacak ve her proje kolayca bileşen güncellemesini gerçekleştirebilecektir.

Bu makalenin kapsamı aşağıdaki gibidir:

  • Angular CLI ile kütüphane oluşturmak.
  • Oluşturulan kütüphaneyi üretim (production) için paketlemek (build).
  • Kütüphaneyi npm havuzu’na (npm repository) yayınlamak (publish).

Kullandığım uygulama ve paket versiyonları
Node 14.20.1
@angular/cli 14.0.3

1. Angular CLI ile kütüphane oluşturalım

Bu bölümde içinde servis barındıran bir sayaç bileşenini (component) bir kütüphane olarak oluşturup kullanacağız. Kütüphane ismine ee-sayac diyelim. Angular CLI ile kütüphane oluşturmak için aşağıdaki komutu proje kök (root) dizininde çalıştırıyoruz.

ng generate library ee-sayac

Dikkat
ng generate library komutu ng g l <name> olarak kısaltılamaz.
En kısa ng g library <name> olarak kullanılabilir.
ng generate library <name> komutu Angular 6 ve üzeri versiyonlarda çalıştırılabilir.

Bu aşamadan sonra Angular CLI kök dizinde yoksa bir Projects klasörü oluşturup içine verdiğimiz isimle bir ee-sayac klasörü oluşturacak ve içine standart bir kütüphane dosya-dizin yapısı (scaffold) yerleştirecektir.

ng generate library ee -sayac

Öneri
ng generate library komutunun sonuna -d ya da --dry-run parametresi eklersek oluşacak değişiklikleri öngörebiliriz. Gerçek bir değişiklik olmaz.

2. Eklenen ve Değiştirilen Dosyaları İnceleyelim

projects/ee-sayac/src yolu (path) haricindeki dosyaları incelersek;

İlk olarak projects/ee-sayac yolundaki eklenen (CREATE) dosyaları inceleyelim.

  • package.json
projects/ee-sayac/package.json
  • Bileşen paketinin isminin (name), versiyon numarasının (version) ve bağımlı olunan (dependencies) paket isimlerinin yer aldığı json dosyasıdır. Bileşende güncelleme yaptığımızda versiyonu uygun bir semantik versiyon değeriyle değiştirmeyi unutmamamız gereklidir. (Bkz: Semantic Versioning)
  • ng-package.json
    Bileşen paketinin inşa edildiğinde (build) nereye çıkacağını (dest), hangi paketleme şemasını kullanacağını ($scheme) ve paketin dışarıya kendini hangi dosyayla teşhir (expose) edeceğini (lib/entryFile) içeren dosyadır.
  • karma.conf.js: Karma test için konfigürasyon dosyasıdır.
  • README.md: Paketinizle ilgili nedir, kurulum, detay, açıklama, başlangıç… gibi bilgileri yazacağınız dosyadır.
  • tsconfig.xxx.json: tsconfig konfigürasyonuyla ilgili dosyalardır. Ana dizindeki tsconfig.json’ı miras (extends) alırlar.

Güncellenen (UPDATE) dosyalar ana dizindeki angular.json, package.json ve tsconfig.json dosyalarıdır.

  • package.json [root]
    Bu dosyayı incelediğimizde ng-packagr npm paketinin eklendiğini görürüz. Bu ng-packagr sayesinde oluşturduğumuz kütüphaneyi biz de bir npm paketi olarak build edebileceğiz. Detaylı bilgi
  • angular.json [root]
    Bu dosyayı incelediğimizde projects kısmıda ana proje ismi dışında ee-sayac isminde bir proje daha eklendiğini göreceğiz. Proje konfigürasyonu olarak da kendi içinde test, geliştirme (development) ve build konfigürasyonlarını barındıracaktır.

Tespit
angular.json'a eklenen konfigürasyona baktığımızda eklediğimiz kütüphanenin aslında başlı başına kendi konfigürasyonları olan ayrı bir proje olabilecek kadar büyüyebileceğini görebiliyoruz.
Proje ihtiyaç veya mimarisine göre kütüphaneler başlı başına ayrı projeler/uygulamalar olabileceği gibi bizim örneğimizdeki gibi bileşenlerden veya bileşen kütüphanelerinden oluşabilir.

  • tsconfig.json [root]
    Bu dosyadaki değişiklikte compilerOptions altında yoksa bir paths nodu açılıp içine oluşturduğumuz kütüphane ismini içeren bir yol dizisi (array) eklemektir.

tsconfig.json'a eklenen path nodu oluşturduğumuz kütüphaneyi içeri aktarırken (import) kullanacağımız takma-isim-yolunu (alias-path) barındırmaktadır. Daha detaylı bilgi için Paths

3. Bileşen Üzerinde Çalışalım

Bileşenimiz bu makale için özel olarak hazırlanmış -herhangi bir projede kullanılacağını düşünmediğim- bir sayaç bileşenidir. Bir düğmeye (button) basınca sayısının arttığı ve bu sayının da bir servisle bağlantı kurarak bir olay fırlattığı (dispatch event) basit bir bileşendir. Bu bileşeni adım adım yazmayıp içindeki önemli alanları göstereceğim.

Projeyi bu github alanında da inceleyebilirsiniz.

  • public-api.ts Bu dosyada basitçe bileşenin dışarıya neleri vereceğinin listesi yer alır.

Bu dosya CLI ile ilk kez oluştuğunda .module,.component ve .service dosyaları otomatik olarak export ettiğini görürüz. Bu sayede bu dosyalarda export edilen class, interface, enum, service, component…vb tüketilen yerlerde kullanılabilir.

4. Bileşeni Build Etme

Bileşeni geliştirirken değişiklikleri görmek ve kullanabilmek için build etmemiz gereklidir. Bunun için CLI ile ng build <library_name> komutunu kullanmalıyız.

ng build ee-sayac

Bu komutu çalıştırdığımızda kütüphanemizi (library) dist klasörüne build alacaktır.

5. Bileşeni Geliştirme Projesinde Kullanma

Bileşeni geliştirme projesinde kullanacağımız zaman bileşende dışarı aktardığımız (export) modülü, kullanacağımız yerdeki modülde içeri aktararak (import) kullanabiliriz. Ben örneğimde app.module.ts içinde kullandım. Şimdi buradaki import’u inceleyelim.

Bileşen modülünü kullanacağımız yerde import ederken bağıl yolu’nu (relative-path) değil direk bileşen adını yazarak import ediyoruz. Bu bileşen bir paket olacağı için import ederken proje içindeki bir yoldan değil de bir paketten import edilmesi gereklidir.
Peki bu import ... from "ee-sayac" tam olarak nereden import ediyor?
Bunun cevabı için kök dizindeki tsconfig.json dosyasını inceliyoruz.

Bileşen geliştirme projemizde ee-sayac bileşenini kullanabilmek için tsconfig.json dosyasındaki compilerOptions/paths kısmına bileşen ismini ve kullanacağı yolu yazıyoruz.
Bizim örneğimizde ee-sayac bileşenini build ettiğimizde bileşeni dist\ee-sayac yoluna build ettiği için biz de projede kullanırken dist yolundaki paketi kullanıyoruz.

6. Bileşeni Güncelleme ve Geliştirme

Geliştirme yaparken her yaptığımız değişiklikten sonra build komutunu çalıştırmak biraz zahmetli olacaktır. Bunu daha kolay hale getirmek için ng build <library_name> --watch komutuyla kütüphanedeki dosyaları takip edip/gözleyip bir değişiklik olduğunda otomatik olarak build eden bir komut çalıştırabiliriz. ng build komutu çalıştığında eğer hali hazırda çalışan bir ng serve varsa bu süreci (process) iptal edecektir. İdeal bir geliştirme ortamı için önce ng build <library_name> --watch çalıştırılmalı. Kütüphane düzgün bir şekilde dist klasörüne çıktıktan sonra npm start çalıştırılmalıdır.

ng build ee-sayac --watch ng serve
Kütüphane Geliştrirme Döngüsü (Sürekli Build)

Dikkat
Herhangi bir terminalde
dist/ee_sayac yolu açıksa ng build komutu hata verecektir.
ng build <library_name> komutu çalıştığında dist klasöründeki ilgili kütüphaneyi siler ve tekrar oluşturur.

Bilgi
dist/<library_name> klasörüne çıkarılan paket Angular Package Format olarak çıkar.

6. Bileşeni npm Paketi Olarak Yayınlama (Publish)

Bileşeni yayınlamadan önce yaptığımız geliştirme ve değişikliklere göre uygun bir versiyon numarasıyla yeni bir versiyon vermemiz gerekir. Detaylı bilgi
projects/ee-sayac/package.json dosyasını açıyoruz ve buradaki versiyon numarasını uygun bir şekilde arttırıyoruz.
Bileşeni npm paketi olarak yayınlamak için normal build yerine prod build almamız gerekiyor.

ng build ee-sayac --configuration production

Bu komutu çalıştırdığımızda CLI yayınlanabilen bir paketi dist klasörüne build alır.

Dikkat
Angular 12 versiyonu öncesinde
--prod anahtarıyla build aldığımızda CLI bize production konfigürasyonuyla build alıyordu.
Ör:
ng build ee-sayac --prod.
Angular 12 ile bu anahtar kullanılmayan (deprecated) olarak işaretlenmiştir. Angular 14 itibari ile de tamamen kaldırılmıştır.

Özel bir npm paket havuzumuz (repo) yoksa npm publish komutu bu paketi npmjs.org'a göndermeye çalışır. Hiçbir kaydımız yoksa da npmjs.org bize hata verecektir.
Eğer kayıtlı değilsek öncelikle npmjs.org'a kayıt olmamız gereklidir. Detaylı Bilgi

  • Öncelikle npmjs.com/signup adresine tıklayarak kaydoluyoruz.
  • Daha sonra bir terminal açarak npm login komutunu çalıştırarak giriş yapıyoruz.
  • Bu aşamadan sonra terminalden dist/ee-sayac yoluna gidip npm publish komutunu çalıştırıyoruz.
npm publish

npm publish komutu çalıştıktan sonra her şey yolunda giderse yukarıdaki gibi bir tarball oluşturup ilgili registry'ye gönderecektir.

Önemli
npm publish komutunu mutlaka dist\<library_name> yolu içinden çalıştırmalıyız.

Bilgi
Eğer özel bir registry’miz varsa (şirket içi repo gibi)
npm publish komutu sonuna bu registry adresini ekleyebiliriz.
Ör:
npm publish --registry <registry_url>. Tabi burada ilgili registry için erişim ve yetkilerimizin olması gereklidir.
Komut satırı yerine registry ayarını
.npmrc dosyası kullanarak da yapabiliriz. Detaylı Bilgi

7. npm Paketini Başka Bir Projede Kullanma

Yayınladığımız npm paketini artık tüketecek olan proje package.json a paket ismini ve versiyon numarasını yazarak kullanabilir.

npm install ee-sayac

Bu komutla birlikte ee-sayac paketi npm havuzundan projeye yüklenecektir. Projede node_modules klasörüne baktığımızda ee-sayac paketinin eklenmiş olduğunu görürüz.

Bu aşamadan sonra paketi kullanmak istediğimizde importlarımızı yine aynı şekilde paket ismiyle yapıyoruz. Ör:

import {EeSayacModule} from "ee-sayac"

8. Sonuç ve Tavsiyeler

Geliştirdiğimiz paketleri sökülüp takılabilen küçük yapıtaşları gibi düşünmeliyiz. npm paketlerini tek bir projeye bağımlı değil birden çok sayıda projede kullanılabilmesi için sadece kendi işini yapan mümkün olduğu kadar az bağımlı paketler halinde tasarlayıp yayınlamalıyız. Daha önceden kullanan projeler varsa geliştirmelerimizde daha az refaktöre neden olacak ve geriye-dönüm uyumlu (backward compatible) geliştirmeler yapmalıyız.

9. Bitiriş

Bu yazımda bir Angular uyumlu bir npm paketini bir Angular kütüphanesi kullanarak nasıl geliştirildiğini anlattım.

  • Kütüphane Geliştirme Projesine buradan.
  • Geliştirdiğmiz dummy npm paketine buradan.
  • Başka bir projede kullanım örneğine buradan.
  • Npm paketi oluşturma ve yayınlamayla ilgili detaylı bilgilere buradan.
    ulaşabilirsiniz.

İyi çalışmalar keyifli okumalar
ermaneng

--

--