Buat monorepositori dengan ruang kerja lerna & benang

belajar-dan-benang

Selama beberapa tahun terakhir, konsep mono-repositori telah berhasil memantapkan dirinya, karena secara signifikan dapat menyederhanakan proses pengembangan proyek perangkat lunak modular, seperti infrastruktur berbasis microservice. Keuntungan utama dari pendekatan arsitektur ini jelas dalam praktiknya, oleh karena itu, saya mengusulkan untuk membuat repositori mono uji Anda sendiri dari awal, sekaligus memahami nuansa bekerja dengan ruang kerja benang dan lerna . Baiklah, mari kita mulai!

Pertimbangkan struktur proyek kami, yang akan menjadi tiga perpustakaan yang terletak di paket / folder, serta package.json di direktori root.

├── package.json └── packages ├── app │  ├── index.js │  └── package.json ├── first │  ├── index.js │  └── package.json └── second ├── index.js └── package.json 

Dapat dipahami bahwa kami memiliki dua pustaka independen pertama dan kedua , serta pustaka aplikasi yang akan mengimpor fungsi dari dua pustaka pertama. Untuk kenyamanan, ketiga paket ditempatkan di direktori paket . Anda dapat meninggalkan mereka di folder root atau meletakkannya di direktori dengan nama lain, tetapi untuk mengikuti konvensi yang diterima secara umum, kami akan menempatkannya dengan cara ini.

Pustaka pertama dan kedua untuk kesederhanaan percobaan hanya akan berisi satu fungsi di index.js , masing-masing akan mengembalikan string halo atas nama modul. Untuk contoh pertama , akan terlihat seperti ini:

 // packages/first/index.js const first = () => 'Hi from the first module'; module.exports = first; 

Dalam modul aplikasi , kami akan menampilkan pesan Hai dari aplikasi di konsol, serta salam dari dua paket lain:

 // packages/app/index.js const first = require('@monorepo/first'); const second = require('@monorepo/second'); const app = () => 'Hi from the app'; const main = () => { console.log(app()); console.log(first()); console.log(second()); }; main(); module.exports = { app, main }; 

Agar yang pertama dan kedua tersedia di aplikasi , kami menyatakannya sebagai dependensi dalam dependensi .

Selain itu, untuk setiap perpustakaan kami menambahkan awalan @ monorepo / di nama nilai di depan nama utama paket ke package.json lokal.

 // packages/app/package.json { "name": "@monorepo/app", "version": "1.0.0", "main": "index.js", "license": "MIT", "dependencies": { "@monorepo/first": "^1.0.0", "@monorepo/second": "^1.0.0" } } 

Mengapa saya perlu awalan dengan ikon anjing di depan nama paket npm (@ monorepo /)?
Menambahkan awalan adalah opsional, tetapi ini persis seperti konvensi penamaan paket yang dipatuhi oleh banyak monorepositori:
material ui , sudut dan lain-lain. Faktanya adalah bahwa setiap pengguna atau organisasi memiliki ruang lingkupnya sendiri di situs web npm , jadi ada jaminan bahwa semua modul dengan @ somescope / postfix dibuat oleh tim somescope , dan bukan oleh penyerang. Selain itu, dimungkinkan untuk memanggil nama modul yang sudah diambil. Misalnya, Anda tidak bisa hanya mengambil dan membuat modul utilitas Anda sendiri, karena perpustakaan seperti itu sudah ada . Namun, menambahkan postfix @ myscopename / kita bisa mendapatkan utils ( @ myscopename / utils ) kita dengan blackjack dan wanita muda.

Sebuah analog dari kehidupan nyata untuk proyek pengujian kami dapat berupa berbagai pustaka untuk bekerja dengan data, alat validasi, analitik, atau hanya satu set komponen UI. Jika kami berasumsi bahwa kami akan mengembangkan aplikasi web dan seluler (misalnya, masing-masing menggunakan React dan React Native ), dan kami memiliki bagian dari logika yang digunakan kembali, mungkin ada baiknya memasukkannya ke komponen yang terpisah, untuk digunakan nanti di proyek lain. Tambahkan ke server ini pada Node.js dan Anda mendapatkan kasus nyata dari kehidupan.

Ruang kerja benang


Sentuhan terakhir sebelum membuat repositori mono lengkap adalah desain package.json di root repositori kami. Perhatikan properti ruang kerja - kami menentukan nilai paket / * , yang berarti "semua subkunci dalam folder paket ". Dalam kasus kami, ini adalah aplikasi , pertama , kedua .

 // package.json { "name": "monorepo", "version": "1.0.0", "main": "packages/app/index.js", "license": "MIT", "private": true, "workspaces": [ "packages/*" ] } 

Selain itu, "pribadi": true harus ditentukan dalam package.json , karena ruang kerja hanya tersedia di proyek pribadi.

Agar semuanya lepas landas, jalankan perintah benang (analog dengan pemasangan benang atau instalasi npm ) dari direktori root. Karena dependensi yang ada dalam modul aplikasi didefinisikan sebagai ruang kerja di paket root.json , pada kenyataannya, kami tidak akan mengunduh apa pun dari npm-registry , tetapi hanya mengikat ("tautan") paket kami.

 yarn 

gambar

Sekarang kita dapat menjalankan perintah node. dari direktori root yang akan menjalankan skrip dari file paket / app / index.js .

 node . 

gambar

Mari kita lihat cara kerjanya. Dengan memanggil benang , kami membuat tautan simbolik di node_modules ke direktori kami di folder paket .

gambar

Karena hubungan ini dalam ketergantungan, kami mendapat satu keuntungan besar - sekarang, ketika mengubah modul pertama dan kedua , aplikasi kami akan menerima versi saat ini dari paket-paket ini tanpa membangun kembali. Dalam prakteknya, itu sangat nyaman, karena kita dapat melakukan pengembangan paket lokal, masih mendefinisikannya sebagai dependensi pihak ketiga (yang akhirnya menjadi).

Keuntungan penting berikutnya yang bisa Anda dapatkan dari bekerja dengan ruang kerja benang adalah organisasi menyimpan dependensi pihak ketiga.

Pelajari lebih lanjut tentang menyimpan dependensi di tingkat atas.
Misalkan kita ingin menggunakan perpustakaan lodash di urutan pertama dan kedua . Dengan menjalankan perintah yarn add lodash dari direktori yang sesuai, kami akan menerima pembaruan untuk package.json lokal - versi paket saat ini akan muncul dalam dependensi .
 "dependencies": { "lodash": "^4.17.11" } 

Adapun paket lodash itu sendiri - secara fisik perpustakaan akan diinstal dalam node_modules di tingkat root sekali.
Jika versi yang diperlukan dari paket eksternal (dalam kasus kami lodash ) berbeda untuk pertama dan kedua (misalnya, pertama Anda perlu lodash v3.0.0 , dan dalam v4.0.0 kedua ), maka paket dengan versi yang lebih rendah ( 3.0.0 ) akan sampai ke root node_modules , dan versi lodash untuk modul kedua akan disimpan dalam paket lokal / detik / node_modules .
Selain kelebihannya, pendekatan ini mungkin memiliki sedikit kelemahan, yang memungkinkan benang untuk memotong dengan bantuan bendera tambahan. Anda dapat membaca lebih lanjut tentang nuansa tersebut di dokumentasi resmi .

Tambahkan Lerna


Langkah pertama bekerja dengan lerna adalah menginstal paket. Biasanya mereka melakukan instalasi global ( benang global add lerna atau npm i -g lerna ), tetapi jika Anda tidak yakin apakah Anda ingin menggunakan perpustakaan ini, Anda dapat menggunakan panggilan menggunakan npx .

Kami akan menginisialisasi lerna dari direktori root:

 lerna init 

gambar

Bahkan, kami melakukan beberapa tindakan sekaligus dengan bantuan satu perintah: membuat repositori git (jika belum diinisialisasi sebelumnya), membuat file lerna.json dan memperbarui paket root kami.json .

Sekarang di file lerna.json yang baru dibuat , tambahkan dua baris - "npmClient": "yarn" dan "useWorkspaces": true . Baris terakhir mengatakan bahwa kita sudah menggunakan ruang kerja benang dan tidak perlu membuat folder app / node_modules dengan tautan simbolis ke pertama dan kedua .

 // lerna.json { "npmClient": "yarn", "packages": [ "packages/*" ], "version": "1.0.0", "useWorkspaces": true } 

Tes dengan Lerna


Untuk menunjukkan kenyamanan bekerja dengan lerna, tambahkan tes untuk perpustakaan kami.
Dari direktori root, kami menginstal paket untuk pengujian - bercanda . Jalankan perintah:

 yarn add -DW jest 

Mengapa saya perlu flag -DW?
Flag -D (- dev) diperlukan agar paket jest diinstal sebagai dependensi dev, dan flag -W (- Abaikan-workspace-root-check) memungkinkan instalasi pada level root (yang kita butuhkan).

Langkah selanjutnya adalah menambahkan satu file uji ke paket kami. Untuk kenyamanan contoh kami, kami akan membuat semua tes serupa. Untuk contoh pertama , file tes akan terlihat seperti ini:

 // packages/first/test.js const first = require('.'); describe('first', () => { it('should return correct message', () => { const result = first(); expect(result).toBe('Hi from the first module'); }); }); 

Kita juga perlu menambahkan skrip untuk menjalankan tes di package.json dari masing-masing perpustakaan kami:

 // packages/*/package.json ... "scripts": { "test": "../../node_modules/.bin/jest --colors" }, ... 

Sentuhan terakhir akan memperbarui root package.json . Tambahkan skrip pengujian yang akan memanggil lerna run test --stream . Parameter berikut lerna run mendefinisikan perintah yang akan dipanggil di setiap paket kami dari paket / folder, dan flag --stream akan memungkinkan kita untuk melihat output dari hasil di terminal.

Hasilnya, package.json dari direktori root akan terlihat seperti ini:

 // package.json { "name": "monorepo", "version": "1.0.0", "main": "packages/app/index.js", "license": "MIT", "private": true, "workspaces": [ "packages/*" ], "scripts": { "test": "lerna run test --stream" }, "devDependencies": { "jest": "^24.7.1", "lerna": "^3.13.2" } } 

Sekarang, untuk menjalankan tes, kita hanya perlu menjalankan perintah dari root proyek kita:

 yarn test 

gambar

Peningkatan Versi dengan Lerna


Tugas populer berikutnya, dengan mana lerna dapat mengatasi kualitas, adalah memperbarui versi paket. Bayangkan setelah mengimplementasikan tes, kami memutuskan untuk memutakhirkan perpustakaan kami dari 1.0.0 ke 2.0.0. Untuk melakukan ini, cukup tambahkan baris "perbarui: versi": "versi lerna - no-push" ke bidang skrip paket root.json , dan kemudian jalankan pembaruan benang: versi dari direktori root. Bendera --no-push ditambahkan sehingga setelah memperbarui versi perubahan tidak dikirim ke repositori jarak jauh, yang lerna lakukan secara default (tanpa bendera ini).

Akibatnya, paket root kami. Json akan terlihat seperti ini:

 // package.json { "name": "monorepo", "version": "1.0.0", "main": "packages/app/index.js", "license": "MIT", "private": true, "workspaces": [ "packages/*" ], "scripts": { "test": "lerna run test --stream", "update:version": "lerna version --no-push" }, "devDependencies": { "jest": "^24.7.1", "lerna": "^3.13.2" } } 

Jalankan skrip pembaruan versi:

 yarn update:version 

Selanjutnya, kita akan diminta untuk memilih versi yang ingin kita alihkan:

gambar

Dengan mengklik Enter, kami mendapatkan daftar paket di mana versi diperbarui.

gambar

Kami mengkonfirmasi pembaruan dengan memasukkan y dan kami menerima pesan tentang pembaruan yang berhasil.

gambar

Jika kita mencoba menjalankan perintah status git , kita tidak mendapatkan pesan apa pun untuk dikomit, pohon bekerja bersih , karena Versi lerna tidak hanya memperbarui versi paket, tetapi juga membuat git commit dan tag yang menunjukkan versi baru (v2.0.0 dalam kasus kami).

Fitur bekerja dengan tim versi lerna
Jika kita menambahkan baris "versi": "versi lerna - no-push" alih-alih "update: versi": "versi lerna - no-push" di bidang skrip paket root. Json , kemungkinan besar Anda akan menemukan perilaku yang tidak terduga dan konsol merah. Faktanya adalah bahwa npm-skrip secara default menjalankan perintah versi (skrip yang dipesan) segera setelah memperbarui versi paket, yang mengarah pada panggilan rekursif ke versi lerna . Untuk menghindari situasi ini, cukup memberi skrip nama yang berbeda, misalnya pembaruan: versi , seperti yang dilakukan dalam contoh kita.

Kesimpulan


Contoh-contoh ini menunjukkan seperseratus dari semua kemungkinan yang dimiliki lerna bersama dengan ruang kerja benang . Sayangnya, sejauh ini saya belum menemukan instruksi terperinci untuk bekerja dengan monorepositori di Rusia, jadi kita dapat mengasumsikan bahwa permulaan telah dibuat!

Tautan ke repositori proyek uji.

Source: https://habr.com/ru/post/id448766/


All Articles