Typescript: Mendukung proyek "berukuran sedang"

Dibuat pada 10 Jun 2015  ·  147Komentar  ·  Sumber: microsoft/TypeScript

Mendengarkan @nycdotnet membuat saya bersemangat untuk mengatasi yang satu ini. Terima kasih, Steve. (btw, Anda dapat melihat wawancara bagusnya di sini: http://www.dotnetrocks.com/default.aspx?showNum=1149)

Usulan di sini pertama kali dimulai pada zaman prasejarah (bahkan sebelum #11), ketika dinosaurus berjalan di bumi yang hangus. Meskipun tidak ada dalam proposal ini yang baru, saya yakin sudah saatnya kita menangani masalah ini. Usulan Steve sendiri adalah #3394.

Masalah

Saat ini, di TypeScript, agak mudah untuk memulai dan memulai, dan kami membuatnya lebih mudah setiap hari (dengan bantuan hal-hal seperti #2338 dan pekerjaan di System.js). Ini luar biasa. Tetapi ada sedikit rintangan seiring dengan bertambahnya ukuran proyek. Saat ini kami memiliki model mental yang berjalan seperti ini:

  • Proyek berukuran kecil: gunakan tsconfig.json, simpan sebagian besar sumber Anda di direktori saat ini
  • Proyek berukuran besar: gunakan build khusus, letakkan sumber di tempat yang Anda butuhkan

Untuk proyek berukuran kecil, tsconfig.json memberi Anda cara yang mudah disiapkan untuk memulai dengan editor mana pun secara lintas platform. Untuk proyek skala besar, kemungkinan besar Anda akan beralih ke sistem build karena beragam persyaratan proyek skala besar, dan hasil akhirnya akan menjadi sesuatu yang sesuai untuk skenario Anda tetapi sulit untuk digunakan karena terlalu sulit untuk digunakan. berbagai sistem dan opsi build.

Steve, dalam wawancaranya, menunjukkan bahwa ini bukanlah model dunia yang tepat, dan saya cenderung setuju dengannya. Sebaliknya, ada tiga ukuran proyek:

  • Proyek berukuran kecil: gunakan tsconfig.json, simpan sebagian besar sumber Anda di direktori saat ini
  • Proyek berukuran sedang: proyek dengan build standar dan komponen bersama
  • Proyek berukuran besar: gunakan build khusus, letakkan sumber di tempat yang Anda butuhkan

Saat Anda menskalakan ukuran proyek, Steve berpendapat, Anda harus mampu menskalakan melalui langkah menengah, atau dukungan alat akan jatuh terlalu cepat.

Usul

Untuk mengatasi ini, saya mengusulkan kami mendukung proyek "berukuran sedang". Proyek-proyek ini memiliki langkah-langkah pembuatan standar yang dapat dijelaskan di tsconfig.json hari ini, dengan pengecualian bahwa proyek tersebut dibangun dari beberapa komponen. Hipotesis di sini adalah bahwa ada cukup banyak proyek pada tingkat ini yang dapat dilayani dengan baik oleh dukungan ini.

Sasaran

Berikan pengalaman yang mudah digunakan bagi pengembang yang membuat proyek "berukuran sedang" untuk kompilasi baris perintah dan saat bekerja dengan proyek ini dalam IDE.

Non-gol

Proposal ini _tidak_ menyertakan kompilasi opsional, atau langkah apa pun di luar apa yang ditangani oleh kompiler saat ini. Proposal ini juga tidak mencakup bundling atau pengemasan, yang akan ditangani dalam proposal tersendiri. Singkatnya, seperti namanya, proposal ini hanya mencakup proyek-proyek 'menengah' dan bukan kebutuhan skala besar.

Desain

Untuk mendukung proyek berukuran sedang, kami fokus pada kasus penggunaan satu tsconfig.json yang mereferensikan yang lain.

Contoh tsconfig.json hari ini:

{
    "compilerOptions": {
        "module": "commonjs",
        "noImplicitAny": true,
        "sourceMap": true
    },
    "files": [
        "core.ts",
        "sys.ts"
    ]
}

Bagian 'dependensi' tsconfig.json yang diusulkan:

{
    "compilerOptions": {
        "module": "commonjs",
        "noImplicitAny": true,
        "sourceMap": true
    },
    "dependencies": [
        "../common", 
        "../util"
    ],
    "files": [
        "core.ts",
        "sys.ts"
    ]
}

Ketergantungan menunjuk ke salah satu dari:

  • Direktori, tempat tsconfig.json dapat ditemukan
  • Sebuah tsconfig.json secara langsung

Dependensi bersifat hierarkis. Untuk mengedit proyek lengkap, Anda perlu membuka direktori yang benar yang berisi root tsconfig.json. Ini menyiratkan bahwa dependensi tidak dapat bersifat siklik. Meskipun mungkin untuk menangani dependensi siklik dalam beberapa kasus, kasus lain, yaitu dengan tipe yang memiliki dependensi melingkar, mungkin tidak mungkin untuk melakukan resolusi penuh.

Bagaimana itu bekerja

Dependensi dibangun terlebih dahulu, dalam urutan mereka terdaftar di bagian 'dependensi'. Jika dependensi gagal dibangun, kompiler akan keluar dengan kesalahan dan tidak melanjutkan pembangunan proyek lainnya.

Saat setiap dependensi selesai, file '.d.ts' yang mewakili output akan tersedia untuk build saat ini. Setelah semua dependensi selesai, proyek saat ini dibangun.

Jika pengguna menetapkan subdirektori sebagai dependensi, dan juga menyiratkan kompilasinya dengan tidak menyediakan bagian 'file', dependensi dikompilasi selama kompilasi dependensi dan juga dihapus dari kompilasi proyek saat ini.

Layanan bahasa dapat melihat setiap ketergantungan. Karena setiap ketergantungan akan dihapus dari tsconfig.jsonnya sendiri, ini mungkin berarti bahwa beberapa contoh layanan bahasa perlu dibuat. Hasil akhirnya adalah layanan bahasa terkoordinasi yang mampu melakukan refactoring, navigasi kode, menemukan semua referensi, dll di seluruh dependensi.

Keterbatasan

Menambahkan direktori sebagai dependensi yang tidak memiliki tsconfig.json dianggap sebagai kesalahan.

Output dari dependensi diasumsikan mandiri dan terpisah dari proyek saat ini. Ini menyiratkan bahwa Anda tidak dapat menggabungkan output .js dari ketergantungan dengan proyek saat ini melalui tsconfig.json. Alat eksternal, tentu saja, dapat menyediakan fungsi ini.

Seperti disebutkan sebelumnya, dependensi melingkar dianggap sebagai kesalahan. Dalam kasus sederhana:

A - B
\ C

A adalah 'proyek saat ini' dan bergantung pada dua dependensi: B dan C. Jika B dan C sendiri tidak memiliki dependensi, kasus ini sepele. Jika C bergantung pada B, B tersedia untuk C. Ini tidak dianggap melingkar. Namun, jika B bergantung pada A, ini dianggap melingkar dan akan menjadi kesalahan.

Jika, dalam contoh, B bergantung pada C dan C mandiri, ini tidak akan dianggap sebagai siklus. Dalam hal ini, urutan kompilasinya adalah C, B, A, yang mengikuti logika yang kita miliki untuk ///ref.

Optimalisasi/peningkatan opsional

Jika dependensi tidak dibangun kembali, maka langkah pembangunannya akan dilewati dan representasi '.d.ts' dari pembangunan sebelumnya digunakan kembali. Ini dapat diperluas untuk ditangani jika kompilasi dependensi telah membangun dependensi yang akan muncul nanti dalam daftar 'dependensi' proyek saat ini (seperti yang terjadi pada contoh yang diberikan di bagian Batasan).

Daripada memperlakukan direktori yang diteruskan sebagai dependensi yang tidak memiliki tsconfig.json sebagai kasus kesalahan, kita dapat secara opsional menerapkan 'file' default dan pengaturan proyek saat ini ke dependensi itu.

Committed Monorepos & Cross-Project References Suggestion

Komentar yang paling membantu

Dokumen/posting blog sedang dalam proses di bawah (akan mengedit ini berdasarkan umpan balik)

Saya akan mendorong siapa pun yang mengikuti utas ini untuk mencobanya. Saya sedang mengerjakan skenario monorepo sekarang untuk memperbaiki bug/fitur terakhir di sana dan akan segera mendapatkan panduan tentangnya


Referensi Proyek

Referensi proyek adalah fitur baru di TypeScript 3.0 yang memungkinkan Anda untuk menyusun program TypeScript Anda menjadi bagian yang lebih kecil.

Dengan melakukan ini, Anda dapat sangat meningkatkan waktu pembuatan, menerapkan pemisahan logis antar komponen, dan mengatur kode Anda dengan cara baru dan lebih baik.

Kami juga memperkenalkan mode baru untuk tsc , flag --build , yang bekerja bersama dengan referensi proyek untuk memungkinkan pembuatan TypeScript yang lebih cepat.

Contoh Proyek

Mari kita lihat program yang cukup normal dan lihat bagaimana referensi proyek dapat membantu kita mengaturnya dengan lebih baik.
Bayangkan Anda memiliki proyek dengan dua modul, converter dan units , dan file pengujian yang sesuai untuk masing-masing:

/src/converter.ts
/src/units.ts
/test/converter-tests.ts
/test/units-tests.ts
/tsconfig.json

File pengujian mengimpor file implementasi dan melakukan beberapa pengujian:

// converter-tests.ts
import * as converter from "../converter";

assert.areEqual(converter.celsiusToFahrenheit(0), 32);

Sebelumnya, struktur ini agak canggung untuk digunakan jika Anda menggunakan satu file tsconfig:

  • File implementasi dapat mengimpor file pengujian
  • Tidak mungkin membangun test dan src bersamaan tanpa src muncul di nama folder keluaran, yang mungkin tidak Anda inginkan
  • Mengubah hanya internal dalam file implementasi memerlukan pemeriksaan ketik pengujian lagi, meskipun ini tidak akan pernah menyebabkan kesalahan baru
  • Mengubah hanya tes yang diperlukan, memeriksa implementasi lagi, bahkan jika tidak ada yang berubah

Anda dapat menggunakan beberapa file tsconfig untuk menyelesaikan beberapa masalah tersebut, tetapi yang baru akan muncul:

  • Tidak ada pemeriksaan terkini, jadi Anda akhirnya selalu menjalankan tsc dua kali
  • Memanggil tsc dua kali menimbulkan lebih banyak overhead waktu startup
  • tsc -w tidak dapat dijalankan pada beberapa file konfigurasi sekaligus

Referensi proyek dapat menyelesaikan semua masalah ini dan banyak lagi.

Apa itu Referensi Proyek?

File tsconfig.json memiliki properti tingkat atas baru, references . Ini adalah array objek yang menentukan proyek untuk referensi:

{
    "compilerOptions": {
        // The usual
    },
    "references": [
        { "path": "../src" }
    ]
}

Properti path dari setiap referensi dapat menunjuk ke direktori yang berisi file tsconfig.json , atau ke file konfigurasi itu sendiri (yang mungkin memiliki nama apa pun).

Saat Anda mereferensikan sebuah proyek, hal-hal baru terjadi:

  • Mengimpor modul dari proyek yang direferensikan akan memuat file deklarasi keluarannya ( .d.ts )
  • Jika proyek yang direferensikan menghasilkan outFile , deklarasi file .d.ts file output akan terlihat dalam proyek ini
  • Mode build (lihat di bawah) akan secara otomatis membangun proyek yang direferensikan jika diperlukan

Dengan memisahkan menjadi beberapa proyek, Anda dapat sangat meningkatkan kecepatan pengecekan dan kompilasi, mengurangi penggunaan memori saat menggunakan editor, dan meningkatkan penegakan pengelompokan logis program Anda.

composite

Proyek yang direferensikan harus mengaktifkan setelan composite .
Pengaturan ini diperlukan untuk memastikan TypeScript dapat dengan cepat menentukan di mana menemukan output dari proyek yang direferensikan.
Mengaktifkan flag composite mengubah beberapa hal:

  • Pengaturan rootDir , jika tidak disetel secara eksplisit, default ke direktori yang berisi file tsconfig
  • Semua file implementasi harus dicocokkan dengan pola include atau terdaftar dalam larik files . Jika batasan ini dilanggar, tsc akan memberi tahu Anda file mana yang tidak ditentukan
  • declaration harus diaktifkan

declarationMaps

Kami juga telah menambahkan dukungan untuk peta sumber deklarasi .
Jika Anda mengaktifkan --declarationMap , Anda akan dapat menggunakan fitur editor seperti "Buka Definisi" dan Ganti Nama untuk menavigasi dan mengedit kode secara transparan melintasi batas proyek di editor yang didukung.

prepend dengan outFile

Anda juga dapat mengaktifkan prepending output dari dependensi menggunakan opsi prepend dalam referensi:

   "references": [
       { "path": "../utils", "prepend": true }
   ]

Memulai proyek akan mencakup keluaran proyek di atas keluaran proyek saat ini.
Ini berfungsi untuk file .js dan file .d.ts , dan file peta sumber juga akan dipancarkan dengan benar.

tsc hanya akan pernah menggunakan file yang ada di disk untuk melakukan proses ini, jadi dimungkinkan untuk membuat proyek di mana file output yang benar tidak dapat dihasilkan karena beberapa output proyek akan ada lebih dari sekali dalam file yang dihasilkan .
Sebagai contoh:

  ^ ^ 
 /   \
B     C
 ^   ^
  \ /
   D

Dalam situasi ini, penting untuk tidak menambahkan di setiap referensi, karena Anda akan mendapatkan dua salinan A dalam output D - ini dapat menyebabkan hasil yang tidak diharapkan.

Peringatan untuk Referensi Proyek

Referensi proyek memiliki beberapa trade-off yang harus Anda ketahui.

Karena proyek dependen menggunakan file .d.ts yang dibuat dari dependensinya, Anda harus memeriksa keluaran build tertentu atau membangun proyek setelah mengkloningnya sebelum Anda dapat menavigasi proyek di editor tanpa melihat yang palsu kesalahan.
Kami sedang mengerjakan proses pembuatan .d.ts di balik layar yang seharusnya dapat mengurangi hal ini, tetapi untuk saat ini kami menyarankan untuk memberi tahu pengembang bahwa mereka harus membangun setelah kloning.

Selain itu, untuk menjaga kompatibilitas dengan alur kerja build yang ada, tsc tidak akan secara otomatis membangun dependensi kecuali dipanggil dengan sakelar --build .
Mari pelajari lebih lanjut tentang --build .

Membangun Mode untuk TypeScript

Fitur yang telah lama ditunggu-tunggu adalah build inkremental cerdas untuk proyek TypeScript.
Di 3.0 Anda dapat menggunakan flag --build dengan tsc .
Ini secara efektif merupakan titik masuk baru untuk tsc yang berperilaku lebih seperti orkestra build daripada kompiler sederhana.

Menjalankan tsc --build ( singkatnya tsc -b ) akan melakukan hal berikut:

  • Temukan semua proyek yang dirujuk
  • Deteksi jika mereka mutakhir
  • Bangun proyek kedaluwarsa dalam urutan yang benar

Anda dapat memberikan tsc -b dengan beberapa jalur file konfigurasi (misalnya tsc -b src test ).
Sama seperti tsc -p , menentukan nama file konfigurasi itu sendiri tidak perlu jika bernama tsconfig.json .

tsc -b Baris Perintah

Anda dapat menentukan sejumlah file konfigurasi:

 > tsc -b                                # Build the tsconfig.json in the current directory
 > tsc -b src                            # Build src/tsconfig.json
 > tsc -b foo/release.tsconfig.json bar  # Build foo/release.tsconfig.json and bar/tsconfig.json

Jangan khawatir tentang memesan file yang Anda berikan pada baris perintah - tsc akan memesan ulang jika diperlukan sehingga dependensi selalu dibangun terlebih dahulu.

Ada juga beberapa flag khusus untuk tsc -b :

  • --verbose : Mencetak log verbose untuk menjelaskan apa yang terjadi (dapat digabungkan dengan flag lain)
  • --dry : Menunjukkan apa yang akan dilakukan tetapi tidak benar-benar membangun apa pun
  • --clean : Menghapus output dari proyek yang ditentukan (dapat digabungkan dengan --dry )
  • --force : Bertindak seolah-olah semua proyek sudah ketinggalan zaman
  • --watch : Mode tontonan (tidak boleh digabungkan dengan bendera apa pun kecuali --verbose )

Peringatan

Biasanya, tsc akan menghasilkan output ( .js dan .d.ts ) dengan adanya sintaks atau kesalahan ketik, kecuali noEmitOnError aktif.
Melakukan ini dalam sistem pembangunan inkremental akan sangat buruk - jika salah satu dependensi Anda yang kedaluwarsa mengalami kesalahan baru, Anda hanya akan melihatnya sekali karena pembangunan berikutnya akan melewatkan pembangunan proyek yang sekarang diperbarui.
Untuk alasan ini, tsc -b secara efektif bertindak seolah-olah noEmitOnError diaktifkan untuk semua proyek.

Jika Anda memeriksa keluaran build apa pun ( .js , .d.ts , .d.ts.map , dll.), Anda mungkin perlu menjalankan build --force setelah kontrol sumber tertentu operasi tergantung pada apakah alat kontrol sumber Anda mempertahankan peta waktu antara salinan lokal dan salinan jarak jauh.

msbuild

Jika Anda memiliki proyek msbuild, Anda dapat mengaktifkan mode build dengan menambahkan

    <TypeScriptBuildMode>true</TypeScriptBuildMode>

ke file proj Anda. Ini akan memungkinkan pembuatan inkremental otomatis serta pembersihan.

Perhatikan bahwa seperti halnya tsconfig.json / -p , properti proyek TypeScript yang ada tidak akan dihormati - semua pengaturan harus dikelola menggunakan file tsconfig Anda.

Beberapa tim telah menyiapkan alur kerja berbasis msbuild di mana file tsconfig memiliki urutan grafik implisit yang sama dengan proyek terkelola yang dipasangkan dengan mereka.
Jika solusi Anda seperti ini, Anda dapat terus menggunakan msbuild dengan tsc -p bersama dengan referensi proyek; ini sepenuhnya dapat dioperasikan.

Panduan

Struktur Keseluruhan

Dengan lebih banyak file tsconfig.json , Anda biasanya ingin menggunakan warisan file Konfigurasi untuk memusatkan opsi kompiler umum Anda.
Dengan cara ini Anda dapat mengubah pengaturan dalam satu file daripada harus mengedit banyak file.

Praktik baik lainnya adalah memiliki file tsconfig.json "solusi" yang hanya memiliki references untuk semua proyek simpul daun Anda.
Ini menyajikan titik masuk sederhana; misalnya dalam repo TypeScript kita cukup menjalankan tsc -b src untuk membangun semua titik akhir karena kita mencantumkan semua subproyek di src/tsconfig.json
Perhatikan bahwa mulai dari 3.0, tidak ada lagi kesalahan untuk memiliki array files kosong jika Anda memiliki setidaknya satu reference dalam file tsconfig.json .

Anda dapat melihat pola ini di repo TypeScript - lihat src/tsconfig_base.json , src/tsconfig.json , dan src/tsc/tsconfig.json sebagai contoh utama.

Penataan untuk modul relatif

Secara umum, tidak banyak yang diperlukan untuk mentransisikan repo menggunakan modul relatif.
Cukup tempatkan file tsconfig.json di setiap subdirektori dari folder induk yang diberikan, dan tambahkan reference s ke file konfigurasi ini agar sesuai dengan lapisan program yang diinginkan.
Anda perlu menyetel outDir ke subfolder eksplisit dari folder output, atau menyetel rootDir ke root umum semua folder proyek.

Penataan untuk outFiles

Tata letak untuk kompilasi menggunakan outFile lebih fleksibel karena jalur relatif tidak terlalu penting.
Satu hal yang perlu diingat adalah bahwa Anda biasanya tidak ingin menggunakan prepend hingga proyek "terakhir" - ini akan meningkatkan waktu pembuatan dan mengurangi jumlah I/O yang dibutuhkan dalam setiap bangunan.
Repo TypeScript sendiri adalah referensi yang bagus di sini - kami memiliki beberapa proyek "perpustakaan" dan beberapa proyek "titik akhir"; proyek "titik akhir" disimpan sekecil mungkin dan hanya menarik perpustakaan yang mereka butuhkan.

Penataan untuk monorepos

TODO: Eksperimen lebih banyak dan cari tahu ini. Rush dan Lerna tampaknya memiliki model berbeda yang menyiratkan hal berbeda di pihak kami

Semua 147 komentar

Ya Tuhan!

:+1:

Ya! Ini sangat masuk akal untuk kasus penggunaan yang Anda berikan. Menyediakan alat yang kami gunakan dengan pandangan yang lebih baik tentang bagaimana kode kami dimaksudkan untuk dikonsumsi jelas merupakan hal yang benar untuk dilakukan. Setiap kali saya F12 ke dalam file .d.ts secara tidak sengaja, saya merasa seperti mencekik anak kucing!

Jonatan,

Terima kasih banyak atas umpan balik yang baik dan telah memutuskan untuk menerima ini. TypeScript adalah alat yang hebat dan fungsi ini akan membantu banyak orang yang ingin membuat komponen basis kode berukuran sedang mereka yang tidak dapat membenarkan inefisiensi yang diamanatkan oleh proyek-proyek besar yang bergantung pada pembagian perhatian yang ketat (misalnya portal Azure atau proyek Monacos of dunia dengan > 100kloc dan banyak tim independen). Dengan kata lain, ini akan sangat membantu "orang biasa". Juga, yang lain telah mengusulkan hal-hal untuk ini, misalnya @NoelAbrahams (#2180), dan lainnya jadi saya tidak dapat mengklaim orisinalitas di sini. Ini hanya sesuatu yang saya butuhkan untuk sementara waktu.

Saya pikir proposal Anda sangat bagus. Satu-satunya kekurangan yang saya lihat dibandingkan proposal saya (#3394), yang sekarang telah saya tutup, adalah tidak adanya mekanisme mundur untuk referensi.

Pertimbangkan skenario dunia nyata berikut yang saya perinci di sini: https://github.com/Microsoft/TypeScript/issues/3394#issuecomment -109359701

Saya memiliki proyek TypeScript grunt-ts yang bergantung pada proyek csproj2ts yang berbeda. Hampir tidak ada orang yang bekerja di grunt-ts juga ingin bekerja di csproj2ts karena memiliki cakupan fungsionalitas yang sangat terbatas. Namun, untuk orang seperti saya - Akan sangat bagus untuk dapat mengerjakan kedua proyek secara bersamaan dan melakukan refactoring/buka definisi/temukan semua referensi di antara mereka.

Ketika saya membuat proposal saya, saya menyarankan agar objek dependensi menjadi objek literal dengan fallback bernama. Versi yang lebih sesuai dengan proposal Anda adalah:

"dependencies": {
   "csproj2ts": ["../csproj2ts","node_modules/csproj2ts/csproj2ts.d.ts"],
   "SomeRequiredLibrary": "../SomeRequiredLibraryWithNoFallback"
}

Untuk mempermudah hal itu masih menjadi sebuah array, saya sarankan pelaksanaan alternatif berikut masa depan yang hipotetis dependencies bagian dari mendengus-ts tsconfig.json berkas:

"dependencies": [
   ["../csproj2ts","node_modules/csproj2ts/csproj2ts.d.ts"],
   "../SomeRequiredLibraryWithNoFallback"
]

Aturan resolusi untuk setiap item tipe array di dependencies adalah: item _first_ yang ditemukan di masing-masing item adalah item yang digunakan, dan sisanya diabaikan. Item tipe string ditangani seperti yang dinyatakan oleh proposal Jonathan.

Ini adalah solusi yang sedikit lebih rumit untuk diterapkan, namun memberikan pengembang (dan penulis perpustakaan) _jauh lebih besar_ fleksibilitas. Untuk pengembang yang tidak perlu mengembangkan di csproj2ts (dan karena itu tidak memiliki file ../csproj2ts/tsconfig.json ), dependensi hanya akan menjadi file definisi yang ditambahkan ke konteks kompilasi. Untuk pengembang yang _melakukan_ file ../csproj2ts/tsconfig.json , proposal akan bekerja persis seperti yang Anda jelaskan di atas.

Dalam contoh di atas, "../SomeRequiredLibraryWithNoFallback" akan diminta untuk ada di sana seperti dalam proposal Anda yang ada, dan ketidakhadirannya akan menjadi kesalahan kompiler.

Terima kasih banyak telah mempertimbangkan hal ini.

Ada dua masalah di sini yang perlu kita pecahkan, ada yang membangun, dan ada dukungan layanan bahasa.

Untuk Build, saya tidak berpikir tsconfig adalah tempat yang tepat untuk ini. ini jelas merupakan masalah sistem build. dengan proposal ini kompiler TypeScript harus berada dalam bisnis:

  • mencari tahu ketergantungan
  • pemeriksaan terkini dari pernyataan
  • manajemen konfigurasi (rilis vs. debug)

Ini semua jelas merupakan tanggung jawab sistem pembangunan; ini adalah masalah yang sulit dan sudah ada alat yang melakukan itu, misalnya MSBuild, grunt, gulp, dll.
Setelah tsconfig dan tsc menjadi driver build, Anda akan menginginkannya menggunakan semua CPU untuk membangun subtree yang tidak terkait, atau memiliki perintah post dan pre build untuk setiap proyek, dan mungkin juga membangun proyek lain. sekali lagi, saya pikir ada alat build di luar sana yang bagus dalam apa yang mereka lakukan, dan tidak perlu bagi kita untuk membuatnya kembali.

Untuk Layanan Bahasa,
Saya pikir itu baik-baik saja untuk perkakas untuk mengetahui tentang beberapa file tsconfig dan dapat menyimpulkan dari itu dan membantu Anda lebih banyak, tetapi itu seharusnya tidak memengaruhi build Anda. saya akan mempertimbangkan sesuatu seperti:

"files" : [
    "file1.ts",
    {
        "path": "../projectB/out/projectB.d.ts",
         "sourceProject": "../projectB/"
     }
]

Di mana tsc hanya akan melihat "jalur" tetapi alat dapat melihat informasi lain dan mencoba membantu semampu mereka.

Saya mengakui adanya masalah tetapi tidak menganggap lumping build dan tooling adalah solusi yang tepat. tsconfig.json harus tetap menjadi tas konfigurasi (yaitu alternatif json untuk file respons) dan tidak menjadi sistem pembangunan. satu tsconfig.json mewakili satu permintaan tsc. tsc harus tetap sebagai kompiler proyek tunggal.

Proyek MSBuild di VS adalah contoh penggunaan sistem build untuk membangun fitur IDE dan sekarang ppl tidak senang dengannya karena terlalu besar.

Terima kasih atas balasan Anda, Muhammad. Biarkan saya menyatakan kembali untuk melihat apakah saya mengerti:

  • Menurut Anda, tugas mengoordinasikan pembangunan multi-proyek harus tetap menjadi domain alat pembangunan khusus.
  • Anda berpikir bahwa mungkin ada sesuatu untuk saran ini untuk layanan bahasa TypeScript.
  • Anda berpikir bahwa menjalankan tsc --project pada tsconfig.json akan sama dengan menjalankan tsc file1.ts ../project/out/project.d.ts . Namun, membuka proyek semacam itu di VS atau editor lain dengan layanan bahasa TypeScript akan memungkinkan "go to definition" untuk membawa pengembang ke _actual TypeScript file_ tempat fitur itu didefinisikan (bukan definisi di projectB.d.ts )

Apakah saya memiliki hak itu?

Jika demikian, saya pikir ini sangat adil. Dalam proposal asli saya ( https://github.com/Microsoft/TypeScript/issues/3394 ), saya memang mengatakan bahwa ide saya tidak lengkap karena tidak menyertakan langkah menyalin hasil yang dipancarkan dari tempat mereka akan dikeluarkan di perpustakaan yang direferensikan ke tempat perpustakaan referensi mengharapkannya saat runtime. Saya pikir Anda mengatakan "mengapa pergi setengah jalan untuk membangun ketika yang benar-benar dibutuhkan adalah dukungan layanan bahasa".

Untuk sedikit mengubah data dalam contoh Anda, apakah Anda bersedia mendukung sesuatu seperti ini?

"files" : [
    "file1.ts",
    {
        "path": "externalLibraries/projectB.d.ts",
         "sourceProject": "../projectB/"
     }
]

Asumsinya adalah bahwa proyek saat ini akan dikirimkan dengan definisi untuk projectB yang akan digunakan secara default, tetapi jika sumber aktual untuk projectB tersedia, sumber aktual akan digunakan sebagai gantinya.

@nycdotnet Anda menyimpulkannya dengan benar; saya ingin membuat sistem yang digabungkan secara longgar dan memungkinkan pencampuran dan pencocokan alat pembuatan yang berbeda dengan IDE yang berbeda tetapi tetap mendapatkan pengalaman waktu desain yang hebat.

Kedengarannya bagus!

Saya setuju dengan @mhegazy dan sebenarnya menurut saya penting bagi TypeScript untuk berhenti menganggap dirinya sebagai 'compiler' dan mulai menganggap dirinya sebagai 'type-checker' dan 'transpiler'. Sekarang ada dukungan transpilasi file tunggal Saya tidak melihat alasan untuk membuat file JavaScript yang dikompilasi kecuali untuk saat runtime/bundling. Saya juga tidak mengerti mengapa perlu untuk menghasilkan definisi referensi eksternal selama pengecekan tipe ketika sumber TypeScript yang sebenarnya tersedia.

Resolusi file dan paket adalah tanggung jawab sistem build yang Anda gunakan (browserify, systemjs, webpack dll), jadi agar perkakas berfungsi, layanan bahasa harus dapat menyelesaikan file dengan cara yang sama seperti sistem/platform build apa pun yang Anda gunakan. sedang menggunakan. Ini berarti mengimplementasikan LanguageServicesHost kustom untuk setiap sistem build atau menyediakan alat untuk masing-masing sistem yang menghasilkan entri pemetaan yang benar di tsconfig.json. Salah satu dari ini dapat diterima.

@nycdotnet Saya pikir kasus penggunaan Anda untuk beberapa jalur mundur akan lebih baik ditangani menggunakan npm link ../csproj2ts ?

Saya setuju dengan @mhegazy bahwa kita harus memisahkan build dari compiler/transpiler. Saya suka menyertakan ketergantungan tsconfig -> tsconfig di bagian file dengan asumsi bahwa jika bagian tersebut tidak mencantumkan file *.ts, ia masih memindainya. Misalnya

"berkas" : [
{
"path": "externalLibraries/projectB.d.ts",
"sourceProject": "../projectB/"
}
]

Akan tetap menyertakan semua file ts dalam direktori dan subdirektori yang berisi file tsconfig.json.

@dbaeumer Anda kemudian ingin memilikinya di properti yang berbeda, benar? saat ini, jika file didefinisikan, itu selalu digunakan dan kami mengabaikan bagian include *.ts.

@mhegazy belum tentu bagian yang berbeda meskipun pada akhirnya akan membuat segalanya lebih jelas. Yang ingin saya hindari adalah dipaksa untuk membuat daftar semua file jika saya menggunakan tsconfig -> tsconfig dependensi. Dalam contoh di atas saya masih ingin untuk tidak mencantumkan file *.ts untuk memasukkannya ke dalam kompiler.

Saya rasa ini sangat dibutuhkan. Saya tidak berpikir kita bisa menghindari pertanyaan build. Itu tidak berarti kita perlu menerapkan sistem pembangunan bersama dengan proposal ini, tetapi kita harus memikirkan beberapa panduan bagus yang berfungsi dalam konfigurasi seperti yang diusulkan. Tidak akan mudah untuk memperbaikinya (dan kita perlu menyelesaikannya untuk Visual Studio).

Dalam proposal di atas (di mana .d.ts dan sumber direferensikan), apakah itu mendeteksi jika .d.ts kedaluwarsa (yaitu perlu dibangun kembali)? Apakah operasi seperti Refactor/Rename bekerja di seluruh proyek (yaitu memperbarui nama di sumber proyek yang direferensikan, bukan hanya file .d.ts yang akan ditimpa build berikutnya)? Apakah GoToDef membawa saya ke kode asli dalam proyek yang direferensikan (bukan di tengah file .d.ts raksasa untuk keseluruhan proyek)? Ini tampaknya menyiratkan perlu untuk menyelesaikan, dan dalam beberapa kasus menganalisis, sumber proyek yang direferensikan, dalam hal mana .d.ts yang berguna?

Solusi umum, yang kita miliki hari ini, Anda memiliki .d.ts sebagai output build dari satu proyek, dan kemudian dirujuk sebagai input di proyek lain. Ini berfungsi dengan baik untuk build, jadi tidak perlu mengubahnya.

Masalahnya adalah skenario pengeditan. Anda tidak ingin melalui file yang dihasilkan saat mengedit. Solusi yang saya usulkan adalah memberikan "petunjuk" dari mana .d.ts yang dihasilkan berasal. Layanan bahasa kemudian tidak akan memuat .d.ts, dan sebagai gantinya memuat "proyek" dari jalur petunjuk. cara ini goto def akan membawa Anda ke file implementasi alih-alih .d.ts dan kesalahan serupa akan bekerja tanpa perlu kompilasi.

operasi seperti mengganti nama, akan "menyebar" dari satu proyek ke proyek lain, juga menemukan referensi, akan dilakukan.

Hari ini sepenuhnya tergantung pada host (IDE, apa pun) untuk menemukan file tsconfig.json, meskipun TS kemudian menyediakan API untuk membaca dan menguraikannya. Bagaimana Anda membayangkan ini bekerja jika ada beberapa tsconfig.json yang terletak secara hierarkis? Apakah tuan rumah masih bertanggung jawab untuk menyelesaikan file awal tetapi tidak yang lain atau apakah tuan rumah akan bertanggung jawab untuk menyelesaikan semua tsconfig?

Sepertinya ada tradeoff antara kenyamanan/konvensi dan fleksibilitas.

Bukankah ini akan dimulai dengan kemampuan untuk membuat file d.ts seperti yang dijelaskan di #2568 (atau setidaknya memiliki impor relatif)?

@spion saya tidak yakin saya melihat ketergantungan di sini. Anda dapat memiliki beberapa keluaran proyek, Anda tidak harus menjadi satu file delectation. sistem build harus dapat mengetahuinya dan menghubungkannya sebagai input ke proyek yang bergantung.

@mhegazy Ups, maaf. Melihat masalah lagi, tampaknya ini lebih terkait dengan layanan bahasa. Saya membaca yang berikut ini

  • Proyek berukuran sedang: proyek dengan build standar dan komponen bersama

dan secara otomatis menganggapnya terkait dengan dukungan yang lebih baik untuk npm/browserify (atau webpack) membangun worfklow di mana bagian dari proyek adalah modul eksternal.

AFAIK belum ada cara untuk menghasilkan file .d.ts untuk modul eksternal? Jika demikian, satu-satunya cara layanan bahasa dapat menautkan proyek yang mengimpor modul eksternal adalah dengan memiliki sesuatu seperti ini di tsconfig.json :

{ 
  "provides": "external-module-name"
}

yang akan menginformasikan LS ketika proyek direferensikan di tsconfig.json

AFAIK belum ada cara untuk menghasilkan file .d.ts untuk modul eksternal?

Saya tidak berpikir ini benar. memanggil tsc --m --d akan menghasilkan file deklarasi yang merupakan modul eksternal itu sendiri. logika resolusi akan mencoba menemukan .ts dan jika tidak maka .d.ts dengan nama yang sama,

@spion TypeScript dapat menghasilkan file d.ts untuk modul eksternal seperti yang dikatakan @mhegazy , tetapi ini menghasilkan rasio definisi 1: 1 ke file sumber yang berbeda dari cara definisi TypeScript perpustakaan biasanya dikonsumsi. Salah satu cara untuk mengatasinya adalah perpustakaan TypeStrong ini: https://github.com/TypeStrong/dts-bundle

@mhegazy maaf, maksud saya untuk "modul eksternal ambient" yaitu jika saya menulis external-module-name di TypeScript dan mengimpor salah satu kelasnya dari modul lain:

import {MyClass} from 'external-module-name'

tidak ada cara untuk membuat tsc menghasilkan file .d.ts yang sesuai yang menyatakan 'external-module-name'

@nycdotnet Saya mengetahui dts-bundle dan dts-generator tetapi masih jika layanan bahasa mengetahui tentang sumber proyek saya yang lain, ia juga harus tahu nama modul apa yang disediakannya untuk dapat melacak impor dengan benar

Apa status fitur ini? tampaknya ini adalah opsi penting untuk proyek ukuran sedang. Bagaimana Anda mengonfigurasi proyek yang memiliki sumber di folder berbeda dengan konfigurasi "requirejs" tertentu?

@llgcode silakan lihat di https://github.com/Microsoft/TypeScript/issues/5039 , ini harus tersedia di typescript@next .

Saya tidak begitu mengerti apa yang sulit tentang menulis gulpfile dengan tugas-tugas yang mengkompilasi sub-proyek seperti yang Anda butuhkan untuk proyek berukuran sedang. Saya bahkan melakukan ini dalam proyek berukuran kecil. Satu-satunya alasan saya menggunakan tsconfig.json adalah untuk Kode VS

Pertama saya tidak menggunakan gulp. Kedua, ini bisa menjadi proyek besar di mana Anda tidak ingin mengkompilasi ulang setiap saat. Tetapi jika Anda memiliki solusi yang baik dengan tegukan, beri tahu saya bagaimana melakukan ini.

@llgcode Yah, tegukan adalah pelari tugas. Anda menulis gulpfile.js di mana Anda mendefinisikan tugas sebanyak yang Anda suka dengan gulp.task() . Di dalam tugas Anda, Anda dapat mengambil aliran file input dengan gulp.src() dan kemudian .pipe() mereka melalui pipa transformasi, seperti kompilasi, penggabungan, minifikasi, peta sumber, menyalin aset ... Anda dapat lakukan apa pun yang mungkin dengan modul Node dan NPM.
Jika Anda harus mengkompilasi beberapa proyek, cukup tentukan tugas yang melakukan ini. Jika Anda ingin menggunakan beberapa tsconfig.json, gulp -typescript memiliki dukungan untuk itu, atau Anda bisa membaca file json. Build tambahan juga dimungkinkan. Saya tidak tahu bagaimana proyek Anda terstruktur, jika Anda memilikinya di repo yang berbeda dan menggunakan submodul, atau apa pun. Tapi tegukan 100% fleksibel.

Ok terima kasih tampaknya menjadi alat yang hebat. jika saya memerlukan pemetaan seperti require("mylibs/lib") dan file saya misalnya dalam folder project/src/lib.js maka penyelesaian tidak akan berfungsi di atom dan saya tidak tahu bagaimana TypeScript atau gulp akan menyelesaikannya pemetaan/konfigurasi dilakukan dengan "mylibs" dan jalur lokal. jadi saya pikir jalur opsi baru di #5039 ini adalah solusi yang baik untuk masalah ini.

@llgcode Nah dengan https://www.npmjs.com/package/gulp-typescript#resolve -files.

Saya hanya berpikir TypeScript mencoba melakukan banyak hal di sini, ini adalah transpiler dan bukan alat build. Mengelola "dependensi" seperti yang disebutkan dalam proposal benar-benar tugas manajer paket atau sistem kontrol versi dan menghubungkannya bersama-sama adalah tugas membangun alat.

@felixfbecker saya tidak setuju. Setiap kompiler (dengan pemeriksaan tipe) yang saya tahu memiliki opsi seperti ini. Misalnya:
gcc -> sertakan file
Java -> classpath & sourcepath
pergi -> GOPATH
python -> PYTHONPATH
kompiler/transpiler perlu mengetahui file sumber apa yang perlu ditranspilasikan file sumber apa yang hanya termasuk/lib file.
Membangun alat seperti gulp diperlukan untuk mengetahui apa yang harus dilakukan ketika sebuah file berubah.

Setuju dengan @llgcode . Selain itu, selain mengekspos sebagai kompiler, TypeScript juga mengekspos sebagai layanan bahasa, yang menyediakan sorotan sintaks (sebenarnya deteksi) dan fungsionalitas penyelesaian ke IDE. Dan ITU juga perlu berjalan di pohon ketergantungan.

@llgcode @unional Poin yang valid. Satu hal yang mungkin juga membantu adalah membuat properti files di tsconfig.json menerima gumpalan sehingga Anda dapat menentukan semua file di semua folder yang ingin Anda sertakan. Tapi saya melihat dari mana Anda berasal dan mengapa seseorang mungkin menginginkan beberapa tsconfig.json untuk proyek yang lebih besar.

AFAIK untuk CommonJS ini sudah didukung melalui node_modules dan npm link ../path/to/other-project

npm link tidak berfungsi segera setelah Anda mulai menggunakan kembali perpustakaan di seluruh proyek. Jika Anda menggunakan perpustakaan umum antara dua proyek terpisah Anda sendiri, (mengambil rxjs sebagai contoh) TypeScript akan memberi tahu Anda bahwa 'Observable is not assignable to Observable'. Itu karena jalur sertakan mengikuti folder symlink ke dua folder node_modules yang berbeda dan meskipun merupakan perpustakaan yang sama. Solusi menghasilkan tugas teguk atau repo npm lokal/pribadi, pada dasarnya kembali ke opsi proyek besar.

@EricABC itu mungkin karena mereka menggunakan deklarasi modul eksternal ambient, dalam hal ini mereka juga harus menyertakan definisi untuk file .d.ts berbasis node_modules baru didukung. Selain itu, seharusnya tidak ada masalah karena tipe TS hanya diperiksa secara struktural, jadi tidak masalah jika mereka berasal dari modul yang berbeda atau memiliki nama yang berbeda selama strukturnya cocok.

Terima kasih @spion , anggap saja itu berbasis file, sepertinya Anda akan menyelamatkan saya dari rasa sakit yang diderita sendiri.

Satu hal yang mungkin juga membantu adalah membuat properti files di tsconfig.json menerima gumpalan...

Ada properti include dalam diskusi

Pertanyaan dan komentar:

  • dependencies harus mengizinkan jalur tsconfig.json penuh karena tsc mengizinkannya
  • Mengapa memperkenalkan kata kunci baru ( dependencies ) ketika files sudah ada dan baik-baik saja?
    Contoh:
{
    "compilerOptions": {
        // ...
    },
    "files": [
        "../common/tsconfig.json", // <== takes the `files` part of the tsconfig.json
        "../common/tsconfig.util.json", // <==
        "core.ts",
        "sys.ts"
    ]
}
  • Apa yang terjadi jika dependensi tsconfig.json juga menentukan compilerOptions ?


Mari kita melangkah lebih jauh/liar :-) dan mungkin mengizinkan (di masa depan) compilerOptions , exclude ... untuk referensi tsconfig.json lain:

// File app/tsconfig.json
{
    "compilerOptions": "../common/tsconfig.compilerOptions.json",
    "files": [
        "../common/tsconfig.json",
        "../common/tsconfig.util.json",
        "core.ts",
        "sys.ts"
    ],
    "exclude": "../common/exclude.json"
}

// File ../common/tsconfig.compilerOptions.json
{
    "compilerOptions": {
        "module": "commonjs",
        "noImplicitAny": true,
        "sourceMap": true
    }
}

// File ../common/exclude.json
{
    "exclude": [
        "node_modules",
        "wwwroot"
    ]
}

// File ../common/tsconfig.util.json
{
    "files": [
        "foo.ts",
        "bar.ts"
    ]
}

Anda mendapatkan logikanya: files , compilerOptions , exclude ... dapat mereferensikan file tsconfig.json lain dan itu hanya akan "mengambil" bagian kata kunci yang cocok dari tsconfig lain File .json => mudah dan skalabel. Dengan demikian, Anda dapat membagi tsconfig.json menjadi beberapa file jika Anda mau dan menggunakannya kembali.

Membaca bagian dari diskusi Anda, tampaknya paling relevan untuk mendapatkan "layanan bahasa"/definisi goto ini dengan benar. Debugger JavaScript menggunakan sourceMaps. Sekarang, jika tsc menghasilkan data sourceMap tidak hanya di .js tetapi juga di file .d.ts...

Di luar itu saya benar-benar tidak melihat banyak manfaat dalam memicu pembangunan proyek anak dari dalam file tsconfig.json. Jika Anda memerlukan dependensi waktu pembuatan semacam ini, skrip shell sederhana akan melakukan pekerjaan itu. Jika Anda membutuhkan bangunan inkremental yang cerdas, di sisi lain, pendekatan yang diusulkan tampaknya terlalu sederhana. Dalam banyak skenario, tsc berakhir hanya sebagai satu langkah pembangunan di antara yang lain. Seberapa aneh dependensi penulisan untuk tsc di tsconfig.json tetapi beberapa file lain untuk sisanya? Sekali lagi, untuk hal-hal sederhana dengan tsc menjadi satu-satunya langkah pembuatan yang akan dilakukan skrip Shell.

Bagaimanapun, bagaimana menghasilkan pemetaan sumber dalam file .d.ts seperti pada file .js?

kami hanya menggunakan modul node + tautan npm, satu-satunya hal yang tidak berfungsi adalah node moduleResolution: tidak kompatibel dengan modul ES6, yang memungkinkan pengoptimalan inlining / tree-shaking (lihat juga #11103 )

Bukan untuk keluar dari topik, tetapi dalam beberapa hal, ini tampaknya paralel dengan tantangan bekerja dengan beberapa proyek paket Node secara lokal. Saya tidak berpikir itu sesederhana hanya menggunakan "tautan npm." Mereka mungkin memiliki skrip build yang berbeda, Anda harus menjalankan semuanya dalam urutan yang benar, lebih sulit untuk melakukannya secara bertahap, lebih sulit untuk menggunakan mode tontonan, lebih sulit untuk men-debug sesuatu, dan lebih sulit untuk menyelesaikan peta sumber. Tergantung pada editor pilihan Anda, ini mungkin lebih menantang.

Umumnya saya hanya menyerah, memasukkan semuanya ke dalam satu proyek raksasa, lalu membaginya menjadi paket-paket terpisah setelah mereka stabil, tetapi itu hanya membantu karena tantangannya lebih jarang dihadapi. Saya menemukan seluruh pengalaman benar-benar menjengkelkan. Apakah saya melewatkan sesuatu?

Jadi, apa pun akhirnya, saya hanya berharap saya akhirnya dapat memiliki solusi yang elegan untuk seluruh pengalaman pengembangan ini.

Hanya berdentang bahwa ini akan bagus untuk pekerjaan kita sehari-hari!

Karena sifat pengembangan web, kami memiliki beberapa proyek ts dengan setiap proyek berisi beberapa file ts yang dikompilasi ke dalam satu file js ( --outFile ). Ini adalah proyek seperti aplikasi (mereka melakukan hal tertentu atau menambahkan fitur tertentu) atau proyek seperti lib (kode yang dapat digunakan kembali untuk aplikasi). Seringkali kami mengerjakan beberapa proyek ts ini secara bersamaan, meningkatkan perpustakaan untuk memfasilitasi pengembangan pada aplikasi. Tapi saya rasa tidak ada rekan pengembang saya yang memiliki semua proyek ts kami di lingkungan lokal mereka kapan saja.

Untuk meningkatkan alur kerja kami, opsi kami saat ini adalah

  • Lempar semuanya ke dalam proyek 1 ts

    • Kami dapat mereferensikan file .ts secara langsung, yang jauh lebih bagus daripada menggunakan file d.ts

    • Tetapi kita memerlukan alat eksternal untuk memetakan dan menggabungkan kumpulan file, karena kita perlu membatasi file js yang diminta melalui interweb sambil mempertahankan modularitas aplikasi (yang khusus untuk fitur atau halaman).

    • Seperti yang disebutkan, tidak semua proyek ts ini diperlukan setiap saat untuk semua orang sehingga ini akan menambah banyak kembung pada sistem file. Seseorang yang mengerjakan proyek X mungkin membutuhkan proyek A, B dan D tetapi seseorang yang mengerjakan Y mungkin membutuhkan A dan C.

  • Pisahkan proyek (situasi kami saat ini)

    • Kita perlu mereferensikan file d.ts yang dikompilasi dari proyek ts lain karena menyertakan file .ts secara langsung akan menambahkannya ke output. Akan jauh lebih cepat jika kita bisa f12 langsung ke kode sumber kita sendiri.

    • Dan kita perlu menambahkan alat/skrip untuk mengkompilasi beberapa proyek ini secara bersamaan. Saat ini kami memulai perintah tsc -d -w dari beberapa terminal, atau menjalankan skrip yang melakukan itu untuk semua subdirektori tempat tsconfig ditemukan.

    • Saya mengerti alat lain dapat membantu dengan ini (misalnya tegukan) atau mungkin kita dapat menemukan sesuatu dengan gumpalan file di tsconfigs, namun itu tidak akan membantu dengan masalah pertama file d.ts.

Proyek kami tidak cukup besar untuk memisahkan pengembangan perpustakaan dari aplikasi, tetapi tidak cukup kecil sehingga kami dapat menggabungkan semuanya. Kami menemukan diri kami kekurangan pilihan anggun dengan TypeScript.

Jika dependencies bisa menjadi pilihan terbaik dari kedua dunia, itu akan luar biasa; fungsi daritag ke semua file ts dependensi, tetapi kompilasi output sesuai dengan file tsconfig.

Apakah ada pembaruan tentang topik ini. Bagaimana kita bisa memiliki beberapa proyek TypeScript yang dikompilasi secara independen satu sama lain? Bagaimana kita bisa menggambarkan ketergantungan seperti itu di tsconfig.json?

Ini sekarang termasuk dalam peta jalan di bagian mendatang dengan judul "Dukungan untuk referensi proyek". Jadi, saya kira file .tsconfig akan dapat menautkan file .tsconfig sebagai dependensi.

Apakah ada pembaruan tentang topik ini. Bagaimana kita bisa memiliki beberapa proyek TypeScript yang dikompilasi secara independen satu sama lain? Bagaimana kita bisa menggambarkan ketergantungan seperti itu di tsconfig.json?

Ketergantungan build harus dikodekan dalam sistem build Anda. membangun sistem seperti gulp, grunt, brokoli, msbuild, basal, dll. dibangun untuk menangani kasus seperti itu.
Untuk informasi tipe, output dari satu proyek harus menyertakan .d.ts dan itu harus diteruskan sebagai input ke proyek lainnya.

@mhegazy Proyek kami bekerja seperti ini. Kami memiliki sejumlah paket dalam lerna monorepo, setiap paket memiliki dependensinya sendiri di package.json, dan dependensi yang sama di properti "types" di tsconfig.json . Setiap proyek dikompilasi dengan --outFile (ini adalah proyek lama yang belum pindah ke modul ES), dan kunci "typings" package.json ke paket .d.ts berkas.

Kami menggunakan gulp untuk bundling/watching.

Ini berfungsi untuk sebagian besar, tetapi ada beberapa masalah:

  • Karena masalah seperti #15488 dan #15487, kami perlu memiliki tautan eksplisit agar referensi berfungsi dengan benar.
  • Go-to-definition akan membawa Anda ke file .d.ts dibundel. Idealnya ini akan membawa Anda ke sumber di proyek lain.
  • Cara tercepat untuk melakukan full build adalah lerna run build --sort (efektif tsc di setiap direktori), yang memiliki overhead tambahan karena akan menelurkan satu proses kompiler TypeScript untuk setiap paket, melakukan banyak pekerjaan berulang .

Saya terus memperhatikan masalah ini karena kami juga berada dalam situasi yang sama seperti yang dijelaskan orang lain.
Beberapa "proyek", masing-masing dengan file tsconfig.json-nya.

Kami memiliki proses build yang berfungsi seperti yang ditunjukkan @mhegazy : setiap proyek mengeluarkan file .d.ts dan itu digunakan sebagai input untuk proyek yang bergantung.

Masalah sebenarnya adalah dukungan IDE: ketika mencari referensi, mereka hanya ditemukan dalam lingkup tsconfig.json tunggal. Lebih buruk lagi, efek cascading dari file yang diubah tidak menyebar ke seluruh proyek karena tergantung file di luar lingkup tsconfig.json tidak dikompilasi ulang. Ini sangat buruk untuk pemeliharaan proyek kami dan terkadang menyebabkan kesalahan build yang bisa saja tertangkap di IDE.

It's happening

YA TUHAN

Skenario yang diperbarui di mana saya ingin ini melibatkan komponen React. Kami memiliki repo komponen yang berisi modul JSX (atom, molekul, dan organisme) yang membuat komponen UI sesuai untuk semua aplikasi di perusahaan kami. Repo komponen ini digunakan oleh semua pengembang front-end saat mereka mengerjakan aplikasi masing-masing. Akan SANGAT BAIK jika saya dapat memiliki pengalaman layanan bahasa TypeScript yang memungkinkan saya untuk mengedit UI aplikasi khusus saya dan "Pergi ke definisi" ke dalam repo komponen UI umum. Hari ini kita harus menggabungkan komponen-komponen ini satu per satu dan menyalinnya. Ini adalah masalah "buat pipa proyek Anda sendiri" yang ingin saya perbaiki (untuk itu ada cerita yang sangat bagus di dunia .NET dengan proyek di bawah solusi).

Referensi Proyek: Skalabilitas Bawaan untuk TypeScript

pengantar

TypeScript telah ditingkatkan ke proyek ratusan ribu baris, tetapi tidak secara asli mendukung skala semacam ini sebagai perilaku bawaan. Tim telah mengembangkan solusi dengan berbagai efektivitas dan tidak ada cara standar untuk mewakili proyek besar. Meskipun kami telah sangat meningkatkan kinerja pemeriksa tipe dari waktu ke waktu, masih ada batasan keras dalam hal seberapa cepat TS bisa mendapatkan,
dan kendala seperti ruang alamat 32-bit yang mencegah layanan bahasa meningkatkan skala "tanpa batas" dalam skenario interaktif.

Secara intuitif, mengubah satu baris BEJ di komponen front-end seharusnya tidak memerlukan pengecekan ulang seluruh komponen logika bisnis inti dari proyek 500.000 LOC. Tujuan dari referensi proyek adalah untuk memberikan alat pengembang untuk mempartisi kode mereka menjadi blok yang lebih kecil. Dengan mengaktifkan alat untuk beroperasi pada bagian pekerjaan yang lebih kecil pada satu waktu, kami dapat meningkatkan daya tanggap dan mengencangkan loop pengembangan inti.

Kami percaya arsitektur kami saat ini hanya memiliki sedikit "makan siang gratis" yang tersisa dalam hal peningkatan drastis dalam kinerja atau konsumsi memori. Sebaliknya, partisi ini adalah pertukaran eksplisit yang meningkatkan kecepatan dengan mengorbankan beberapa pekerjaan di muka. Pengembang harus meluangkan waktu untuk mempertimbangkan grafik ketergantungan sistem mereka, dan fitur interaktif tertentu (misalnya penggantian nama lintas proyek) mungkin tidak tersedia sampai kami menyempurnakan alat lebih lanjut.

Kami akan mengidentifikasi kendala utama yang diberlakukan oleh sistem ini dan menetapkan pedoman untuk ukuran proyek, struktur direktori, dan pola pembangunan.

Skenario

Ada tiga skenario utama yang perlu dipertimbangkan.

Modul Relatif

Beberapa proyek secara ekstensif menggunakan impor relatif . Impor ini secara jelas diselesaikan ke file lain di disk. Jalur seperti ../../core/utils/otherMod akan umum ditemukan, meskipun struktur direktori yang lebih datar biasanya lebih disukai dalam repo ini.

Contoh

Berikut ini contoh dari proyek perseus Khan Academy:

Diadaptasi dari https://github.com/Khan/perseus/blob/master/src/components/graph.jsx

const Util = require("../util.js");
const GraphUtils = require("../util/graph-utils.js");
const {interactiveSizes} = require("../styles/constants.js");
const SvgImage = require("../components/svg-image.jsx");

Pengamatan

Sementara struktur direktori menyiratkan struktur proyek, itu belum tentu definitif. Dalam contoh Khan Academy di atas, akan dapat menyimpulkan bahwa util , styles , dan components mungkin akan menjadi proyek mereka sendiri. Tetapi mungkin juga direktori ini cukup kecil dan sebenarnya akan dikelompokkan ke dalam satu unit build.

Mono-repo

Mono-repo terdiri dari sejumlah modul yang diimpor melalui jalur non-relatif . Impor dari sub-modul (misalnya import * as C from 'core/thing ) mungkin umum. Biasanya, tetapi tidak selalu, setiap modul root sebenarnya diterbitkan di NPM.

Contoh

Diadaptasi dari https://github.com/angular/angular/blob/master/packages/forms/src/validators.ts

import {InjectionToken, ɵisObservable as isObservable, ɵisPromise as isPromise} from '@angular/core';
import {forkJoin} from 'rxjs/observable/forkJoin';
import {map} from 'rxjs/operator/map';
import {AbstractControl, FormControl} from './model';

Pengamatan

Unit pembagian tidak harus menjadi bagian utama dari nama modul. rxjs , misalnya, sebenarnya mengkompilasi subbagiannya ( observable , operator ) secara terpisah, seperti halnya paket cakupan (misalnya @angular/core ).

file keluar

TypeScript dapat menggabungkan file inputnya menjadi file JavaScript output tunggal. Arahan referensi, atau pemesanan file di tsconfig.json, membuat urutan output deterministik untuk file yang dihasilkan. Ini jarang digunakan untuk proyek baru, tetapi masih lazim di antara basis kode lama (termasuk TypeScript itu sendiri).

Contoh

https://github.com/Microsoft/TypeScript/blob/master/src/compiler/tsc.ts

/// <reference path="program.ts"/>
/// <reference path="watch.ts"/>
/// <reference path="commandLineParser.ts"/>

https://github.com/Microsoft/TypeScript/blob/master/src/harness/unittests/customTransforms.ts

/// <reference path="..\..\compiler\emitter.ts" />
/// <reference path="..\harness.ts" />

Pengamatan

Beberapa solusi yang menggunakan konfigurasi ini akan memuat setiap outFile melalui tag script (atau yang setara), tetapi yang lain (misalnya TypeScript sendiri) memerlukan penggabungan file sebelumnya karena mereka sedang membangun keluaran monolitik .

Referensi Proyek: Unit isolasi baru

Beberapa pengamatan kritis dari interaksi dengan proyek nyata:

  • TypeScript biasanya "cepat" (< 5-10 detik) saat memeriksa proyek di bawah 50.000 LOC kode implementasi (non-.d.ts)
  • File .d.ts, terutama di bawah skipLibCheck , hampir "gratis" dalam hal pengecekan tipe dan biaya memori
  • Hampir semua perangkat lunak dapat dibagi lagi menjadi komponen yang lebih kecil dari 50.000 LOC
  • Hampir semua proyek besar sudah menerapkan beberapa penataan file mereka berdasarkan direktori dengan cara yang menghasilkan subkomponen berukuran sedang
  • Sebagian besar pengeditan terjadi pada komponen leaf-node atau near-leaf-node yang tidak memerlukan pemeriksaan ulang atau pemancaran ulang seluruh solusi

Menyatukan ini, jika mungkin untuk hanya memeriksa satu 50.000 LOC potongan kode implementasi sekaligus, hampir tidak ada interaksi "lambat" dalam skenario interaktif, dan kami hampir tidak pernah kehabisan memori.

Kami memperkenalkan konsep baru, referensi proyek , yang mendeklarasikan jenis ketergantungan baru antara dua unit kompilasi TypeScript di mana kode implementasi unit dependen tidak dicentang; alih-alih kita cukup memuat output .d.ts dari lokasi deterministik.

Sintaksis

Opsi references (TODO: Bikeshed!) ditambahkan ke tsconfig.json :

{
  "extends": "../tsproject.json",
  "compilerOptions": {
    "outDir": "../bin",
    "references": [
      { "path": "../otherProject" }
    ]
  }
}

Array references menentukan satu set proyek lain untuk referensi dari proyek ini.
Setiap references objek path menunjuk ke file tsconfig.json atau folder yang berisi file tsconfig.json .
Pilihan lain dapat ditambahkan ke objek ini saat kami menemukan kebutuhan mereka.

Semantik

Referensi proyek mengubah perilaku berikut:

  • Ketika resolusi modul akan diselesaikan ke file .ts di subdirektori dari proyek rootDir , alih - .d.ts di proyek itu outDir

    • Jika resolusi ini gagal, kami mungkin dapat mendeteksinya dan mengeluarkan kesalahan yang lebih cerdas, misalnya Referenced project "../otherProject" is not built daripada "file tidak ditemukan" sederhana

  • Tidak ada yang lain (TODO: sejauh ini?)

Batasan untuk Kinerja Proyek yang Direferensikan

Untuk meningkatkan kinerja build secara bermakna, kita perlu memastikan untuk membatasi perilaku TypeScript saat melihat referensi proyek.

Secara khusus, hal-hal berikut harus benar:

  • Jangan pernah membaca atau mengurai file input .ts dari proyek yang direferensikan
  • Hanya tsconfig.json dari proyek yang direferensikan yang harus dibaca dari disk
  • Pemeriksaan terkini seharusnya tidak melanggar batasan di atas

Untuk memenuhi janji ini, kami perlu memberlakukan beberapa batasan pada proyek yang Anda referensikan.

  • declaration secara otomatis disetel ke true . Ini adalah kesalahan untuk mencoba menimpa pengaturan ini
  • rootDir default ke "." (direktori yang berisi file tsconfig.json ), daripada disimpulkan dari kumpulan file input
  • Jika array files disediakan, itu harus memberikan nama semua file input

    • Pengecualian: File yang disertakan sebagai bagian dari referensi tipe (mis. yang ada di node_modules/@types ) tidak perlu ditentukan

  • Setiap proyek yang dirujuk harus memiliki array references (yang mungkin kosong).

Mengapa "declaration": true ?

Referensi proyek meningkatkan kecepatan build dengan menggunakan file deklarasi (.d.ts) sebagai pengganti file implementasinya (.ts).
Jadi, tentu saja, setiap proyek yang direferensikan harus memiliki pengaturan declaration .
Ini tersirat oleh "project": true

Mengapa mengubah rootDir ?

rootDir mengontrol bagaimana file input dipetakan ke nama file output. Perilaku default TypeScript adalah menghitung direktori sumber umum dari grafik lengkap file input. Misalnya, kumpulan file input ["src/a.ts", "src/b.ts"] akan menghasilkan file output ["a.js", "b.js"] ,
tetapi kumpulan file input ["src/a.ts", "b.ts"] akan menghasilkan file output ["src/a.js", "b.js"] .

Menghitung kumpulan file input memerlukan penguraian setiap file root dan semua referensinya secara rekursif,
yang mahal dalam proyek besar. Tetapi kita tidak dapat mengubah perilaku ini hari ini tanpa merusak proyek yang ada dengan cara yang buruk, jadi perubahan ini hanya terjadi ketika array references disediakan.

Tidak Ada Lingkaran

Secara alami, proyek mungkin tidak membentuk grafik dengan sirkularitas apa pun. (TODO: Masalah apa yang sebenarnya disebabkan oleh hal ini, selain mimpi buruk orkestrasi build?) Jika ini terjadi, Anda akan melihat pesan kesalahan yang menunjukkan jalur melingkar yang terbentuk:

TS6187: Project references may not form a circular graph. Cycle detected:
    C:/github/project-references-demo/core/tsconfig.json ->
    C:/github/project-references-demo/zoo/tsconfig.json ->
    C:/github/project-references-demo/animals/tsconfig.json ->
    C:/github/project-references-demo/core/tsconfig.json

tsbuild

Proposal ini sengaja dibuat kabur tentang bagaimana itu akan digunakan dalam sistem pembangunan "nyata". Sangat sedikit proyek yang melampaui batas "cepat" 50.000 LOC tanpa memperkenalkan sesuatu selain tsc untuk mengkompilasi kode .ts.

Skenario pengguna "Anda tidak dapat membuat foo karena bar belum dibuat" adalah jenis tugas "Ambil itu" yang harus ditangani oleh komputer, bukan dari beban mental pada pengembang.

Kami berharap alat seperti gulp , webpack , dll, (atau plugin TS masing-masing) akan membangun pemahaman tentang referensi proyek dan menangani dependensi build ini dengan benar, termasuk pemeriksaan terkini.

Untuk memastikan bahwa ini memungkinkan , kami akan menyediakan implementasi referensi untuk alat orkestrasi build TypeScript yang menunjukkan perilaku berikut:

  • Pemeriksaan cepat terkini
  • Pemesanan grafik proyek
  • Membangun paralelisasi
  • (TODO: yang lain?)

Alat ini hanya boleh menggunakan API publik, dan didokumentasikan dengan baik untuk membantu pembuat alat memahami cara yang benar untuk mengimplementasikan referensi proyek.

MELAKUKAN

Bagian yang harus diisi untuk melengkapi proposal ini

  • Bagaimana Anda mentransisikan proyek yang sudah ada

    • Pada dasarnya cukup masukkan file tsconfig.json dan kemudian tambahkan referensi yang diperlukan untuk memperbaiki kesalahan pembuatan

  • Dampak pada baseUrl

    • Membuat implementasi menjadi sulit tetapi secara efektif tidak ada dampak pengguna akhir

  • Diskusi singkat tentang proyek bersarang (TL; DR perlu diizinkan)
  • Garis besar skenario untuk membagi proyek yang telah tumbuh "terlalu besar" menjadi proyek yang lebih kecil tanpa merusak konsumen
  • Cari tahu skenario Lerna

    • Titik data yang tersedia (N = 1) mengatakan mereka tidak membutuhkan ini karena build mereka sudah terstruktur secara efektif dengan cara ini

    • Temukan lebih banyak contoh atau contoh tandingan untuk lebih memahami bagaimana orang melakukan ini

  • Apakah kita memerlukan pengaturan dtsEmitOnly untuk orang-orang yang mem-pipe JS mereka melalui mis. webpack/babel/rollup?

    • Mungkin references + noEmit menyiratkan ini

Fantastis!

Cari tahu skenario Lerna

  • Titik data yang tersedia (N = 1) mengatakan mereka tidak membutuhkan ini karena build mereka sudah terstruktur secara efektif dengan cara ini

Apakah "ini" merujuk pada proposal atau implementasi pembangunan referensi? Meskipun Anda dapat menggunakan lerna untuk melakukan pembangunan (tim saya melakukannya), itu sangat kasar dan akan jauh lebih efisien jika TS (atau alat yang dibuat dari proposal ini) menangani dirinya sendiri.

Bagian TODO adalah TODO untuk keseluruhan proposal

Bagus!

Setiap proyek yang direferensikan harus memiliki larik referensi (yang mungkin kosong).

Apakah ini benar-benar diperlukan? Tidakkah cukup jika paket seperti itu memiliki file .d.ts ?
(Dalam hal ini, bahkan mungkin tidak perlu karena ada tsconfig.json , juga?)

Kasus penggunaan saya: pertimbangkan proyek (misalnya pihak ketiga) yang tidak menggunakan outDir , jadi .ts , .js dan .d.ts akan berada di sebelah satu sama lain, dan TS saat ini akan mencoba mengkompilasi .ts daripada menggunakan .d.ts .

Alasan untuk tidak menggunakan outDir bagi saya adalah untuk lebih mudah mengizinkan impor import "package/subthing" -style, yang seharusnya misalnya import "package/dist/subthing" dengan outDir: "dist" .
Dan untuk dapat menggunakan paket NPM, atau repositori sumbernya secara langsung (misalnya dengan npm link ).

(Akan sangat membantu jika package.json diizinkan menentukan direktori di main , tapi sayangnya...)

Apakah kita memerlukan pengaturan dtsEmitOnly untuk orang-orang yang menyalurkan JS mereka melalui misalnya webpack/babel/rollup?

Sangat! Ini adalah bagian besar yang hilang saat ini. Saat ini Anda bisa mendapatkan satu file d.ts saat menggunakan outFile , tetapi ketika Anda beralih ke modul dan menggunakan bundler, Anda kehilangan ini. Mampu memancarkan satu file d.ts untuk titik masuk modul (dengan export as namespace MyLib ) akan luar biasa. Saya tahu alat eksternal dapat melakukan ini tetapi akan sangat bagus jika diintegrasikan ke dalam emitor dan layanan bahasa.

Apakah ini benar-benar diperlukan? Tidakkah cukup jika paket seperti itu memiliki file .d.ts?

Kami membutuhkan sesuatu di tsconfig target yang memberi tahu kami di mana diharapkan file output berada. Versi sebelumnya dari proposal ini memiliki "Anda harus menentukan rootDir eksplisit " yang agak rumit (Anda harus menulis "rootDir": "." di setiap tsconfig). Karena kami ingin membalik berbagai perilaku di dunia ini, lebih masuk akal untuk mengatakan bahwa Anda mendapatkan perilaku "proyek" jika Anda memiliki larik referensi dan menjadikannya sebagai hal yang dimatikan, daripada menentukan sekelompok flag yang harus Anda nyatakan secara eksplisit.

Proposal ini akan sejalan dengan bagaimana kami telah menyusun proyek TypeScript kami. Kami telah membagi lagi menjadi unit yang lebih kecil yang masing-masing memiliki tsconfig.json dan dibangun secara independen melalui gulp. Proyek referensi satu sama lain dengan referensi file d.ts.

Di dunia yang ideal, proyek yang direferensikan tidak perlu dibuat sebelumnya. yaitu. TypeScript melakukan "build" dari proyek yang direferensikan dan mempertahankan "d.ts" yang setara dalam memori dalam layanan bahasa. ini akan memungkinkan perubahan yang dibuat dalam proyek "sumber" muncul di proyek "bergantung" tanpa perlu membangun kembali.

Kami membutuhkan sesuatu di tsconfig target yang memberi tahu kami di mana diharapkan file output berada.

Itu hanya benar ketika outDir digunakan, bukan?

Seperti pada: jika saya memiliki tsconfig yang:

  • TIDAK menggunakan outDir (tetapi memiliki declaration: true , tentu saja), maka kita tidak perlu rootDir , atau references
  • memang memiliki outDir , maka Anda perlu references dan/atau rootDir (dan declaration: true ) untuk disetel

Alasan untuk bertanya adalah bahwa saya kemudian dapat mengaktifkan 'mode proyek' untuk paket TS apa pun hanya dengan merujuknya, yaitu dalam kendali saya.

Dalam hal ini, akan lebih baik jika juga bekerja segera setelah menemukan file .d.ts yang dicari (yaitu tidak akan mengeluh jika tidak ada file .ts, atau file tsconfig). Karena itu akan memungkinkan kasus lain untuk 'mengganti' versi NPM (yang mungkin hanya memiliki file .d.ts) dengan versi sumbernya bila diperlukan.

Misalnya, pertimbangkan paket NPM MyApp dan SomeLib.
SomeLib dapat memiliki tsconfig: declaration: true .

Repositori seperti:

package.json
tsconfig.json
index.ts
sub.ts

Dikompilasi, ini menjadi:

package.json
tsconfig.json
index.ts
index.d.ts
index.js
sub.ts
sub.d.ts
sub.js

Struktur ini memungkinkan misalnya

// somewhere in MyApp
import something from "SomeLib/sub";

Dalam paket NPM yang diterbitkan, saat ini saya selalu harus menghapus file .ts, jika tidak, semua sumber akan dikompilasi ulang oleh TS jika MyApp menggunakan SomeLib:

Jadi, pada NPM, ini menjadi:

package.json
index.d.ts
index.js
sub.d.ts
sub.js

Sekarang, jika saya memasukkan references: ["SomeLib"] di tsconfig MyApp, akan lebih baik jika berfungsi 'apa adanya' untuk versi NPM dan versi sumber SomeLib , yaitu bahwa ia tidak akan mengeluh tentang misalnya hilang tsconfig, selama itu menemukan sub.d.ts di tempat yang tepat.


Terkait, tetapi pertanyaan yang berbeda:

Saya sekarang menyadari, bahwa JIKA penulis SomeLib menempatkan references di tsconfig-nya, ini akan memungkinkan untuk menerbitkan paket NPM DENGAN file .ts, di masa mendatang. Tapi kemudian, saya kira TS masih akan selalu mengkompilasi ulang ini ketika paket dependen apa pun tidak secara eksplisit memasukkan references: ["SomeLib"] di tsconfig mereka.

Atau apakah maksud juga bahwa references di MyLib akan secara otomatis juga memperkenalkan 'batas proyek' ketika hanya import 'menyimpannya (yaitu bukan references 'ing itu)?

IIRC, salah satu ide awalnya adalah jika sebuah modul misalnya terletak melalui node_modules , maka file .d.ts akan lebih disukai daripada file .ts , tetapi ini kemudian diubah kembali , karena heuristik ("melalui node_modules ") secara umum terlalu bermasalah. Mungkinkah memiliki 'batas proyek' eksplisit akan menyelesaikan ini (misalnya projectRoot: true , alih-alih atau selain memiliki references )?

Untuk kasus lerna, saya mengharapkan solusi yang lebih sederhana.

  1. Di direktori paket individu, paket tidak boleh mengetahui apa pun tentang struktur monorepo. File tsconfig json individual tidak boleh berisi referensi apa pun.
  2. Di repo "ruang kerja" root (yang dapat berisi semua kode, tetapi juga dapat dengan mudah mengkloning repo lain), miliki referensi di tsconfig.json-nya

    • ini dilakukan agar perkakas dapat mengenali dan mengikuti referensi sampai ke sumbernya alih-alih masuk ke file .d.ts.

Seluruh kekhawatiran saya adalah bahwa setelah Anda menambahkan referensi menggunakan jalur relatif turun "../xx" ke file konfigurasi proyek individu, mereka tidak lagi dapat digunakan sebagai modul yang berdiri sendiri - mereka harus berada dalam struktur ruang kerja tertentu.

Menambahkan konsep baru "ruang kerja" tsconfig.json memecahkan masalah ini. Dengan begitu jika Anda misalnya "git clone" paket individu, menginstal dependensinya dengan cara biasa (misalnya menggunakan npm atau yarn) akan membiarkan Anda mengerjakannya secara terpisah, karena dependensi yang dikompilasi akan membawa file definisinya. Jika Anda mengkloning seluruh ruang kerja dan menjalankan perintah untuk memasukkan semua paket, konfigurasi ruang kerja akan memungkinkan Anda menavigasi semua sumber.

Perhatikan bahwa ruang kerja tsconfig.json juga selaras sempurna dengan ruang kerja Benang package.json https://yarnpkg.com/lang/en/docs/workspaces/

Saya melakukan sedikit bukti konsep di sini

https://github.com/spion/typescript-workspace-plugin

Cukup tambahkan plugin ke semua file tsconfig.json dari masing-masing repo

{
  "plugins": [{"name": "typescript-workspace-plugin"}]
}

Kemudian di package.json tingkat atas di samping entri "ruang kerja" benang, tambahkan entri "sumber ruang kerja":

{
  "workspaces": ["packages/*"],
  "workspace-sources": {
    "*": ["packages/*/src"]
  }
}

Bidang ini bekerja sangat mirip dengan bidang "jalur" di tsconfig.json tetapi hanya memengaruhi layanan bahasa dari masing-masing proyek, mengarahkannya ke sumber paket. Mengembalikan fungsionalitas "pergi ke definisi/ketik" yang tepat dan serupa.

Itu hanya benar ketika outDir digunakan, bukan?

Benar. Kami telah berhipotesis bahwa hampir semua orang dengan proyek besar menggunakan outDir . Saya akan tertarik untuk mendengar tentang proyek yang tidak

Sekarang, jika saya meletakkan referensi: ["SomeLib"] di tsconfig MyApp, akan lebih baik jika berfungsi 'apa adanya' untuk versi NPM dan versi sumber SomeLib

Penggemar berat, saya sangat menyukai ide ini. Saya perlu memikirkan apakah itu benar-benar diperlukan atau tidak.

Satu peringatan di sini adalah bahwa saya pikir paket penulis perlu baik) mempublikasikan baik ts dan file tsconfig bersama-sama di tempat di mana TS menemukan mereka, atau b) menerbitkan tidak dan hanya memiliki file .d.ts terjangkau. Dalam kasus (a) kami akan mengikuti referensi proyek secara rekursif dan hal yang benar akan terjadi dan dalam (b) kami tidak akan menjelajah ke tempat yang salah.

Atau maksud juga bahwa referensi di MyLib akan secara otomatis juga memperkenalkan 'batas proyek' ketika hanya mengimpornya (yaitu tidak mereferensikannya)?

Berbicara dengan @mhegazy dan kami pikir sebenarnya ada model sederhana tentang bagaimana perilaku referensi proyek: proyek apa pun dengan array references tidak pernah "melihat" file .ts luar folder proyek - ini termasuk file di bawah direktori exclude d. Perubahan ini saja membuat skenario lerna bekerja ("bekerja" yang berarti "referensi modul selalu diselesaikan ke .d.ts") di luar kotak, serta yang lainnya.

Saya perlu melihat model "ruang kerja" lebih banyak.

Itu hanya benar ketika outDir digunakan, bukan?

Benar. Kami telah berhipotesis bahwa hampir semua orang dengan proyek besar menggunakan outDir. Saya akan tertarik untuk mendengar tentang proyek yang tidak

Kami memiliki 67 Proyek TS dalam solusi studio visual yang dikompilasi tanpa outdir dan postbuild gruntasks untuk membuat struktur direktori keluaran (dan uglify dan postprocessing lainnya).

Sebagian besar proyek memiliki tsconfig.json

 "include": [
    "../baseProj/Lib/jquery.d.ts",
    "../baseProj/baseProj.d.ts"
  ]

Saya meluangkan waktu untuk membaca proposal referensi, dan mengoreksi - AFAICT lerna dan pengguna ruang kerja benang tidak memerlukan fungsionalitas ruang kerja yang diusulkan di sini:

  1. Kami sudah memiliki grafik ketergantungan berdasarkan package.json sehingga kami tahu urutan menjalankan build. Faktanya, lerna memiliki perintah run generik yang dapat menjalankan ini secara berurutan, dan tidak sulit untuk menulis alat yang juga menambahkan paralelisme jika dapat diterapkan. skipLibCheck seharusnya membuat dampak kinerja diabaikan, tetapi saya belum memeriksanya.
  2. Lerna dan Yarn sudah membuat symlink ke modul lain di lokasi node_modules yang sesuai. Akibatnya, semua tanggungan dapat mengikuti package.json modul lain, membaca bidang types/typings dan menemukan file definisi tipe module.d.ts yang direferensikan.

Apa yang tidak kami miliki, dan apa yang disediakan oleh plugin yang saya tulis, adalah cara untuk memuat semua sumber secara bersamaan. Ketika saya perlu membuat perubahan pada dua atau lebih modul secara bersamaan, saya tidak ingin "pergi ke definisi" dan "ke jenis definisi" untuk mengirim saya ke file .d.ts. Saya ingin mengirim saya ke lokasi kode sumber asli, sehingga mungkin saya dapat mengeditnya. Jika tidak, saya hanya akan memuat direktori proyek individu dan symlink node_modules yang dibuat oleh lerna/yarn hanya akan berfungsi.

Hal yang sama untuk kita. Alih-alih Lerna, kami menggunakan Rush untuk menghitung grafik ketergantungan kami, tetapi efeknya sama. Saat kita membangun proyek, tsc hanyalah salah satu dari banyak tugas yang perlu dijalankan. Opsi kompiler kami dihitung oleh sistem build yang lebih besar, dan kami pindah ke model di mana tsconfig.json bukan file input, melainkan output yang dihasilkan (terutama untuk kepentingan VS Code).

Apa yang tidak kami miliki, dan apa yang disediakan oleh plugin yang saya tulis, adalah cara untuk memuat semua sumber secara bersamaan. Ketika saya perlu membuat perubahan pada dua atau lebih modul secara bersamaan, saya tidak ingin "pergi ke definisi" dan "ke jenis definisi" untuk mengirim saya ke file .d.ts. Saya ingin mengirim saya ke lokasi kode sumber asli, sehingga mungkin saya dapat mengeditnya.

+1 ini akan luar biasa.

Jika kita memimpikan dukungan multi-proyek yang lebih baik, permintaan pertama saya adalah layanan kompiler, seperti cara kerja VS Code IntelliSense. Pembuatan kami akan jauh lebih cepat jika Rush dapat memanggil tsc 100 kali tanpa harus memutar mesin kompiler 100 kali. Kompiler adalah salah satu langkah pembuatan kami yang paling mahal. Dalam monorepo, waktu pembuatan sangat penting.

@iclanton @nickpape-msft @qz2017

Ya silahkan!

Saya pikir salah satu hasil yang paling berguna dari sistem proyek adalah jika
'pergi ke definisi' pergi ke file sumber alih-alih file d.ts dan
'temukan semua referensi' yang dicari melalui pohon referensi proyek.

Agaknya ini juga akan membuka refactoring tipe 'ganti nama global'.

Pada Thu, Nov 9, 2017 at 09:30 Salvatore Previti [email protected]
menulis:

Ya silahkan!


Anda menerima ini karena Anda berlangganan utas ini.
Balas email ini secara langsung, lihat di GitHub
https://github.com/Microsoft/TypeScript/issues/3469#issuecomment-343356868 ,
atau matikan utasnya
https://github.com/notifications/unsubscribe-auth/AANX6d19Zz7TCd_GsP7Kzb-9XJAisG6Hks5s07VXgaJpZM4E-oPT
.

Berbicara dengan @mhegazy dan kami pikir sebenarnya ada model sederhana tentang bagaimana perilaku referensi proyek: proyek apa pun dengan array referensi tidak pernah "melihat" file .ts di luar folder proyek - ini termasuk file di bawah direktori yang dikecualikan.

Bagus, dan dalam hal ini, mengapa seseorang harus menentukan referensi spesifik sama sekali?
Tampaknya cukup memiliki flag (seperti projectRoot: true ).
Misalnya, apa perbedaan antara references: ["foo"] dan hanya references: [] ?
Karena jika saya import "foo" atau import "bar" , keduanya akan mengabaikan file .ts .

Jadi, dalam hal ini, proposal menjadi:

Diberikan tsconfig.json ini (TODO bikeshed pada projectRoot ):

{
  "extends": "../tsproject.json",
  "compilerOptions": {
    "projectRoot": true
   }
}

Ketika tsc kemudian perlu menyelesaikan sesuatu di luar folder proyek (termasuk file di bawah direktori yang dikecualikan), itu hanya akan melihat file .d.ts (sebagai alternatif, mungkin hanya _prefer_ .d.ts file, dan kembali ke tsconfig dan/atau .ts jika hanya melihatnya).

Ini membuat resolusi selama kompilasi cepat dan sederhana.
Ia bekerja untuk referensi monorepo (yaitu import "../foo" ) dan referensi berbasis paket (yaitu import "foo" ).
Ini berfungsi untuk paket NPM dan representasi kode sumbernya.
Dan itu menghilangkan kebutuhan untuk menyelesaikan mesin tsconfig.json selama kompilasi, meskipun pesan kesalahan jika tidak dapat menemukan .d.ts akan kurang membantu.

Kedengarannya agak terlalu bagus untuk menjadi kenyataan, jika memang sesederhana ini, jadi saya mungkin mengabaikan sesuatu yang penting :)


Seperti yang juga ditunjukkan oleh orang lain, masih sangat penting bahwa 'IntelliSense' tetap bekerja dengan file .ts.

Jadi, jika permintaan untuk 'go to definition', 'find references' dll dibuat, itu harus menggunakan beberapa pemetaan terbalik untuk menemukan file .ts sesuai dari file .d.ts yang digunakannya jauh.

Pemetaan ini dapat dilakukan dengan menggunakan misalnya:

  • menggunakan string komentar yang disematkan seperti //# sourceURL = ../src/foo.ts di .d.ts

    • peta sumber yang lebih rumit dapat digunakan untuk memetakan dari .d.ts 'digulung' kembali ke .ts asalnya

  • menyelesaikan file .js , dan menggunakan peta sumbernya untuk menemukan `.ts

Ini memang memperkenalkan topik membangun kembali .d.ts ketika .ts itu diubah, tetapi saya tidak yakin itu harus diselesaikan dengan proposal ini. Sebagai contoh, sudah menjadi kasus hari ini bahwa perlu ada beberapa proses untuk membangun kembali file .js , bahkan dari proyek root itu sendiri. Jadi saya kira akan aman untuk berasumsi bahwa jika itu ada, akan ada juga sesuatu untuk membangun kembali dependensi. Bisa berupa sekumpulan tsc paralel untuk setiap paket, bisa berupa tsbuild , bisa berupa IDE pintar dengan compileOnSave -seperti perilaku, dll.

@pgonzal @michaelaird https://github.com/spion/typescript-workspace-plugin tidak hanya itu - memulihkan pergi ke definisi dan menemukan semua referensi untuk-tsconfig multi-benang / Lerna / etc ruang kerja proyek.

Menarik... Aku ingin tahu apakah kita bisa membuat ini bekerja dengan Rush. Kami akan melihat.

FYI alat sederhana lain yang kami buat sebagai bagian dari upaya ini adalah wsrun

Mirip dengan lerna run , ia menjalankan perintah untuk semua paket di ruang kerja.

Karena dependensi TypeScript perlu dikompilasi secara berurutan, wsrun mampu menjalankan perintah paket dalam urutan topologi berdasarkan dependensi package.json . Ini mendukung paralelisme selama pembuatan. Memang tidak paralel secara optimal, tapi itu bisa diperbaiki nanti.

Sekedar catatan, oao adalah alat monorepo lain untuk benang. Baru-baru ini menambahkan dukungan untuk pemesanan perintah 'topologis' juga.

Saya hanya ingin memposting kata "refactoring" di sini karena ini adalah tujuan penting bagi kami, meskipun mungkin bersinggungan dengan proposal saat ini (https://github.com/Microsoft/TypeScript/issues/3469#issuecomment-341317069) dan tidak disebutkan dalam masalah ini sangat sering.

Kasus penggunaan kami adalah monorepo dengan beberapa proyek TS, pada dasarnya dapat direduksi menjadi common-library ditambah beberapa aplikasi: app1 dan app2 . Saat bekerja di IDE, itu harus diperlakukan sebagai satu proyek, misalnya, rename refactoring harus bekerja di ketiga modul, tetapi app1 dan app2 juga merupakan dua target build yang terpisah. Meskipun saya setuju bahwa build umumnya merupakan masalah yang terpisah, kenyataannya adalah bahwa aplikasi kami cukup kecil dan melakukan sesuatu seperti cd app1 && tsc akan baik-baik saja bagi kami.

Jika TypeScript muncul dengan cara yang baik untuk mendukung ini, itu akan luar biasa.

Untuk refactoring/referensi lintas proyek monorepo, saya menemukan pengaturan ini berfungsi untuk saya jika Anda bekerja di vscode:

root tsconfig:

"compilerOptions": {
   "baseUrl": ".",
   // global types are different per project
   "types": [],
   "paths": {
      "lib": ["packages/lib/src"],
      "xyz1": ["packages/xyz1/src"],
      "xyz2": ["packages/xyz2/src"],
   }
},
"include": ["./stub.ts"], // empty file with export {} to stop vscode complaining about no input files
"exclude": ["node_modules"]

paket/xyz1/tsconfig.json

{
  "extends": "../../tsconfig",
   "compilerOptions": {
      "types": ["node"],
   },
   "include": ["src/**/*"]
}

paket/xyz2/tsconfig.json

{
  "extends": "../../tsconfig",
   "compilerOptions": {
      "types": ["webpack-env"]
   },
  "include": ["src/**/*"]
} 

paket/lib/tsconfig.json

{
   "extends": "../../tsconfig",
    "compilerOptions": { ... },
    "include": ["src/**/*"],
    // special file to load referenced projects when inside in lib package, without it they won't be 
    // visible until you open some file in these projects 
    "files": ["./references.ts"],
}

paket/lib/tsconfig-build.json

{
   "extends": "./tsconfig",
    // exclude referenced projects when building
   "files": []
}

package/lib/references.ts

import "xyz1";
import "xyz2";

export {};

Anda memerlukan properti main dalam paket package.json dan mungkin types bahkan untuk paket tanpa lib, misalnya:

  "main": "src/main.tsx",
  "types": "src/main.tsx",

Dengan cara ini memfaktorkan ulang/mengganti nama sesuatu di lib juga akan memfaktorkan ulang referensi di xyz1 dan xyz2 . Juga proyek dapat memiliki global/target lib yang berbeda dengan cara ini.

Di Gradle, mereka hanya menyebutnya - composite build .

Omong-omong, dapatkah saya memulai jika saya ingin berkontribusi pada kompiler TypeScript? Saya telah mengkloning repo dan itu bukan masalah kecil (saya biasa membaca sumber: angular, ionic, express ketika saya tidak bisa mendapatkannya dari dokumen atau jauh dari internet ...) Saya sangat membutuhkan bantuan dari satu untuk menunjukkan saya jalan untuk pergi, silakan.

Terima kasih!
Masa depan cerah untuk TypeScript.

Saya memiliki prototipe yang ingin saya coba jika mereka menggunakan jalur modul relatif. Ada contoh repo di https://github.com/RyanCavanaugh/project-references-demo yang menguraikan skenario dasar dan menunjukkan cara kerjanya.

Untuk mencoba secara lokal:

git clone https://github.com/RyanCavanaugh/TypeScript
git checkout pr-lkg
npm install
npm run build
npm link

Kemudian di folder Anda yang lain:

npm link typescript

Saya akan menjaga tag pr-lkg menunjuk pada komit kerja terbaru saat semuanya berubah. Selanjutnya tentang todos saya:

  • [x] Tambahkan pesan kesalahan yang lebih baik saat proyek dependen tidak dibangun
  • [ ] Terapkan perilaku pengalihan ke jalur modul nonrelatif
  • [ ] Mengekspos API untuk membangun alat untuk dikonsumsi

@RyanCavanaugh Saya tidak dapat benar-benar membangunnya karena kesalahan seperti kehilangan modul del atau Error: Cannot find module 'C:\github\TypeScript\built\local\tsc.js' (mungkin jalur lokal Anda?) tetapi secara keseluruhan, strukturnya tampak hebat.

Apakah ini tsc -saja atau akankah ini juga memperhitungkan refactoring seluruh proyek di VSCode dengan server bahasa?

...juga tag pr-lkg tidak ada.

Tag ada di sana (bukan cabang). Lihat https://github.com/RyanCavanaugh/TypeScript/tree/pr-lkg

references di tsconfig.json adalah keikutsertaan per-dependensi, bukankah lebih masuk akal untuk diterapkan pada semua yang diselesaikan di luar rootDir ?

Saya membayangkan sesuatu seperti properti sandbox yang bisa terlihat seperti:

# tsconfig.json
{
  "compilerOptions": {
    "outDir": "lib",
    "sandbox": "."
  },
  "include": ["src/index.ts"]
}

Sandbox juga akan menyetel rootDir ke nilai yang sama. Alih-alih secara eksplisit memberikan jalur ke direktori yang berisi tsconfig.json , resolusi modul normal akan diterapkan, dan Anda dapat mencari pohon FS untuk menemukan tsconfig.json secara otomatis.

# package.json
{
  "name": "animals",
  "module": "src",
  "typings": "lib",
  "dependencies": {
    "core": "*"
  }
}

Cara ini:

  • Tidak harus mempertahankan dua daftar yang disinkronkan ( references dan dependencies ).
  • Paket tidak memiliki pengetahuan tentang sistem file di luar miliknya sendiri.
  • Gunakan strategi resolusi modul node alih-alih jalur kustom.

@RyanCavanaugh , sejauh yang saya mengerti, saya hanya dapat bekerja secara lokal dengan perubahan ini dan saya tidak akan dapat mengirim proyek tersebut untuk pengujian, misalnya, di travis-ci.org. Benar?

Catatan dari pertemuan hari ini dengan @billti / @mhegazy


  • Temukan Referensi / Ganti nama harus berfungsi, setidaknya untuk skenario di mana konteks kompilasi yang diperlukan untuk menentukan penutupan proyek sesuai dengan memori
  • Penggantian nama di seluruh solusi akan berjalan untuk menemukan file "solusi", bekerja mundur untuk menemukan proyek referensi, dan kemudian memuat implementasi bagian grafik dari mana simbol terlihat. Ini mungkin proses berulang untuk menemukan deklarasi asal yang sebenarnya
  • tsb perlu menangani mode -w
  • Solusi mungkin tidak memiliki subproyek yang berasal dari luar folder solusi
  • Perlu dokumentasi yang jelas untuk misalnya gulp, webpack

Sidebar: Ganti nama ini tidak berfungsi hari ini

function f() {
  if (Math.random() > 0.5) {
    return { foo: 10 };
  } else {
    return { foo: 20 };
}
// rename foo here doesn't rename *both* instances in the function body
f().foo;

Terima kasih Ryan, Mohamed, dan Bill. Membuat skenario Find References/Rename bekerja di seluruh proyek adalah salah satu kasus penggunaan inti yang ada dalam pikiran saya ketika saya mengajukan keluhan awal tentang TypeScript yang tidak mendukung proyek berukuran sedang. Proyek berukuran sedang bersifat modular tetapi tidak besar. Proposal dan pekerjaan yang saya lihat di sini sejauh ini terasa lebih seperti permainan skalabilitas. Ini sangat penting untuk kesehatan TypeScript jangka panjang, tetapi sebagian besar bermanfaat untuk proyek besar, bukan menengah. Hal-hal yang saya dengar dalam komentar dari Ryan ini terdengar lebih sejalan dengan apa yang dibutuhkan untuk meningkatkan ergonomi pengembangan proyek berukuran sedang di TypeScript.

Seperti biasa, terima kasih banyak kepada seluruh tim TypeScript atas upaya Anda! Anda melakukan pekerjaan yang luar biasa.

Ada trik dengan ruang kerja lerna/benang yang akan membuat hidup Anda lebih mudah.
Arahkan entri main dan types di package.json Anda dari subproyek ke file src/index. ts , dan skenario Temukan Referensi/Ganti Nama akan berfungsi.
Dan Anda akan dapat mengkompilasi seluruh proyek Anda dengan menjalankan satu tsc.
Anda dapat melakukannya untuk beberapa paket Anda, Anda dapat melakukannya untuk semua. panggilanmu.

Ada beberapa kelemahan dan jebakan (Jika Anda memiliki augmentasi dalam satu paket, atau mengimpor simbol global apa pun, itu akan mencemari seluruh program Anda), tetapi secara umum itu bekerja dengan sangat baik.
Saat Anda ingin mempublikasikan ke NPM, Anda cukup mengatur main & types ke nilai yang sesuai (sebagai bagian dari build Anda, atau lebih)

Dengan pengaturan di atas, saya mendapatkan kurang lebih semua fitur yang diharapkan

inilah trik dengan ruang kerja lerna/benang yang akan membuat hidup Anda lebih mudah.
Arahkan entri main dan types di package.json Anda dari sub proyek ke file src/index.ts Anda, dan skenario Find References/Rename akan bekerja.

Dalam pengalaman saya, masalah dengan pengaturan itu adalah TypeScript akan mulai memperlakukan file ts dari paket _external_ seolah-olah itu adalah _sumber_ dari paket yang membutuhkannya, bukan sebagai perpustakaan eksternal. Hal ini menyebabkan sejumlah masalah.

  • Paket eksternal dikompilasi beberapa kali, setiap kali menggunakan tsconfig dari paket _requiring_. Jika paket yang membutuhkan memiliki tsconfig yang berbeda (misalnya lib yang berbeda), hal ini dapat menyebabkan kesalahan kompilasi palsu muncul pada paket yang diperlukan hingga paket tersebut dikompilasi lagi.

  • Paket yang diperlukan juga dikompilasi lebih lambat karena menyertakan lebih banyak file daripada yang diperlukan.

  • rootDir dari semua paket menjadi direktori tingkat atas, berpotensi memungkinkan penyertaan langsung file TS apa pun dari paket apa pun, alih-alih hanya menyertakan dari index . Jika pengembang tidak berhati-hati, mereka dapat melewati API paket yang diperlukan. Juga, jika proses pembuatannya tidak kuat, paket yang diperlukan mungkin akan berisi kode duplikat dari paket yang diperlukan yang dimaksudkan untuk menjadi eksternal.

Dalam proyek kami, kami telah mengesampingkan tergantung pada file TS karena kekurangannya. Semua dependensi antar-paket ada di file index.d.ts , jadi kompiler memperlakukannya sebagai eksternal dan semuanya baik-baik saja.

Tentu saja tergantung pada .d.ts memiliki masalah memerlukan pembangunan multi-langkah (tidak mungkin out-of-the-box dengan alat seperti webpack) dan masalah pengalaman IDE yang buruk (mengganti nama, referensi tidak melintasi batas paket ).

Saya setuju dengan beberapa sentimen lain - TypeScript adalah kompiler, bukan sistem build. Kami membutuhkan alat kami untuk mendukung pembangunan multi proyek yang lebih baik. Saya tahu ada beberapa opsi di komunitas yang mulai melakukan ini. Sebagai contoh, C# memiliki compiler bernama Roslyn dan alat build bernama MSBuild.

Diskusi hari ini dengan @mhegazy tentang cara membuat rename bekerja dengan sedikit rasa sakit dan praktis.

Kasus terburuk yang tidak merosot untuk penggantian nama terlihat seperti ini:

// alpha.ts
const v = { a: 1 };
export function f() { return v; }
export function g() { return v; }

// alpha.d.ts (generated)
export function f(): { a: number };
export function g(): { a: number };

// beta.ts (in another project)
import { f } from '../etc/alpha';
f().a;

// gamma.ts (in yet another project)
import { g } from '../etc/alpha';
g().a;

Pengamatan utama adalah bahwa tidak mungkin untuk mengetahui bahwa mengganti nama f().a harus mengubah nama g().a kecuali Anda dapat melihat alpha.ts untuk menghubungkan keduanya.

Sketsa kasar rencana implementasi:

  • Memiliki representasi SourceFile dalam memori "kaya" dan "ramping" dari file .d.ts. File "Lean" dibaca dari disk; yang "kaya" diproduksi sebagai hasil dari generasi .d.ts dalam memori
  • "Kaya" .d.ts SourceFiles memiliki referensi dari simpul pengenalnya ke nama aslinya dalam file sumber asli
  • Selama rename, pertama-tama kita melakukan go-to-def pada simbol yang dimaksud, seperti biasa. Jika ini berasal dari .d.ts yang direferensikan proyek, kami mengimplementasikannya dan membuat file .d.ts "Kaya"

    • Catatan: proses ini berulang, yaitu mungkin memerlukan penelusuran kembali beberapa level hingga mendarat di file implementasi nyata (yang bukan pengalihan .d.ts karena referensi proyek)

  • Sekarang gunakan pointer "kaya" untuk mencari tahu pengidentifikasi lain mana dalam .d.ts proyek yang berasal dari pengidentifikasi file sumber yang sama
  • Di setiap proyek hilir, pindai teks untuk pengidentifikasi yang diganti namanya dan lihat apakah hasil "go-to-def"-nya adalah salah satu dari lokasi "dimulai dari simbol yang sama" di .d.ts
  • Lakukan penggantian nama di file implementasi

@RyanCavanaugh akan pergi ke definisi/menemukan semua referensi akan bekerja dengan model ini?

Catatan dari diskusi sebelumnya dengan Anders dan Mohamed seputar sejumlah besar pertanyaan terbuka

  • Apakah prepend juga berlaku untuk .d.ts ? Ya
  • Apa yang kita lakukan dengan @internal di cabang dogfood? Kita perlu menyimpan deklarasi internal di file .d.ts lokal tetapi tidak ingin mereka muncul di versi keluaran

    • Hapus --stripInternal

    • Tapi jangan mencelanya (belum...?)

    • Ryan untuk menulis alat remove-internal (selesai)

    • dibangun -> proses LKG menghapus deklarasi @internal

  • Apa yang terjadi jika Anda mengubah file .d.ts dari misalnya @types ?

    • Perlu memaksa pembangunan kembali secara manual jika Anda ingin melihat kemungkinan kesalahan baru ️

    • Akhirnya bisa menulis file "file yang saya lihat.txt" ke folder output jika ini menjadi sangat bermasalah

  • Apakah noEmitOnError wajib? Ya.

    • Kalau tidak, pembangunan kembali akan menyembunyikan kesalahan!

  • referenceTarget -> composable
  • Bagaimana dengan proyek leaf-node yang tidak ingin deklarasi menyala, tetapi ingin membangun kembali dengan cepat?

    • tsbuild atau yang setara dapat memeriksa untuk melihat kepatuhan mereka terhadap persyaratan yang tidak relevan dengan hulu composable

  • Referensi melingkar, (bagaimana) cara kerjanya?

    • Secara default, tidak

    • Anda dapat menentukan misalnya { path: "../blah", circular: true } jika Anda ingin melakukan ini

    • Jika ya, terserah Anda untuk memastikan build Anda deterministik dan selalu mencapai titik tetap (mungkin tidak?!)

    • Pemetaan ulang dari circular:true import adalah opsional (tetapi diprioritaskan) remap

Varia

  • @weswigham punya ide alternatif untuk rename yang perlu kita diskusikan dengan @mhegazy

Aku sudah kalah. Saya kebanyakan hanya ingin menjaga interpretasi peta sumber dari kompiler (tanggung jawab terpisah untuk alat terpisah) tetapi ketika Anda pergi, saya tetap bekerja untuk menambahkannya (karena tampaknya mulus masuk ke def diinginkan).

@RyanCavanaugh
Haruskah mengganti nama/menemukan semua referensi berfungsi di seluruh proyek yang direferensikan setelah menggabungkan #23944 ? Juga haruskah kita menggunakan composite: true dan projectReferences: [] jika hanya layanan bahasa (tetapi bukan itu) yang diperlukan?

Haruskah mengganti nama/menemukan semua referensi berfungsi di seluruh proyek yang direferensikan setelah menggabungkan #23944 ?

belum. tapi kami sedang mengerjakan ini selanjutnya.

Juga haruskah kita menggunakan composite: true dan projectReferences: [] jika hanya layanan bahasa (tetapi bukan itu) yang diperlukan?

tidak yakin saya mengerti pertanyaannya .. apa maksud Anda "layanan bahasa" dan bukan "membangun"?

tidak yakin saya mengerti pertanyaannya .. apa maksud Anda "layanan bahasa" dan bukan "membangun"?

Saya hanya tertarik pada dukungan editor (ganti nama/temukan semua referensi/dll...) di beberapa proyek di monorepo, bukan pada alat build baru (alias build mode ) (#22997) karena saya menggunakan babel untuk kompilasi saya.

Itu hanya harus bekerja. build adalah fitur opt-in, Anda tidak perlu menggunakannya jika Anda tidak ingin.. mirip dengan bagaimana tsc tidak diperlukan untuk pengalaman layanan bahasa Anda di VSCode misalnya.

Anda mungkin perlu membangun dengan deklarasi dan peta deklarasi, untuk menghasilkan metadata yang diperlukan agar referensi lintas proyek berfungsi.

Saya tidak yakin apakah saya memahami semua aspek proposal dengan benar, tetapi apakah mungkin untuk tidak meminta proyek individu merujuk orang lain melalui jalur, tetapi dengan nama? Proyek ruang kerja harus memiliki cara untuk menentukan setiap jalur proyek, mirip dengan ruang kerja benang melalui gumpalan, atau mungkin dengan mencantumkan setiap nama proyek individu:

Pada dasarnya, alih-alih:

"dependencies": [
    "../common", 
    "../util"
],

Bisakah kita memiliki?

"dependencies": [
    "common", 
    "util"
],

dan memiliki ruang kerja tsconfig.json

"workspace": {
  "common": "packages/common",
  "util": "packages/util"
}

Atau lebih baik lagi, sintaks jalur:

"workspace": {
  "*":"packages/*"
}

Manfaat:

  • kemampuan untuk menentukan aturan pencarian yang berbeda tergantung pada sistem modul
  • kemampuan untuk misalnya mundur ke node_modules ketika paket diunduh di luar ruang kerja
  • kemampuan untuk secara bebas menggabungkan beberapa ruang kerja untuk dikerjakan dengan mengkloning beberapa repo dan memiliki konfigurasi jalur yang berbeda, sehingga Anda dapat mengerjakan lebih banyak paket secara paralel.

Atau paling tidak, bisakah kita memiliki nama non-jalur (yang tidak dimulai dengan './' atau '../') dicadangkan untuk penggunaan di masa mendatang...

Saya tidak yakin seberapa besar hubungannya, tetapi Benang 1.7 memperkenalkan konsep "ruang kerja terfokus" baru-baru ini, lihat posting blog ini .

Apakah ada orang di sini cukup akrab dengan kedua ruang kerja dan pekerjaan @RyanCavanaugh melakukan sekitar naskah modus referensi proyek / build untuk mungkin menjatuhkan komentar menjelaskan jika mereka berhubungan sama sekali? Perasaan saya adalah bahwa _somewhere_ antara ruang kerja Benang (npm akan mendapatkannya juga tahun ini) dan versi TypeScript yang akan datang merupakan dukungan yang baik untuk monorepo dengan banyak proyek dan perpustakaan bersama. (Kami merasakan sakitnya, saat ini.)

Saya sangat ingin mendapatkan pembaruan tentang kemajuan fitur ini. Kami berencana untuk memindahkan Aurelia vNext ke monorepo sekitar bulan depan. Versi baru kami adalah 100% TypeScript dan kami ingin menggunakan sistem proyek TS resmi daripada Lerna, jika kami bisa. Kami juga senang menjadi pengguna awal/penguji fitur baru :)

Dukungan inti dan goto def menggunakan dukungan tsc --b untuk dukungan build sudah ada dan terikat untuk TS 3.0. Basis kode TypeScript telah pindah untuk menggunakannya. Kami sedang menguji dukungan ini menggunakan repo TypeScript.

Apa yang masih perlu dilakukan saat ini: 1. get find all references/rename to work on multi project scenarios. 2. menangani pembaruan file .d.ts di latar belakang editor, dan 3. dukungan --watch untuk skenario multi-proyek. juga banyak dan banyak pengujian.

Tiket ini telah dia pesan selama 3 tahun. Masih 3/6 item yang beredar?

@claudeduguay Ini adalah perubahan mendasar untuk proyek apa yang didukung TypeScript, waktunya untuk merayakan bukan? Saya sangat senang untuk ini!

@mhegazy Ini adalah berita bagus. Saya sangat senang mendengar bahwa tim TS juga melakukan dogfood pada proyek mereka sendiri. Menunggu beberapa hal terakhir selesai dan menjadikan ini sebagai opsi untuk Aurelia :) Segera setelah ada beberapa dokumentasi tentang pengaturannya, kami akan memindahkan vNext kami ke sistem proyek baru. Tidak sabar!

@mhegazy Bisakah Anda menjelaskan bagaimana semua ini akan bekerja dengan file dan proyek package.json berdasarkan modul ES2015? Sebagai contoh, di Aurelia vNext, kita memiliki paket seperti @aurelia/kernel , @aurelia/runtime , @aurelia/jit , dll. Itulah nama-nama modul yang akan digunakan di import pernyataan di seluruh berbagai proyek. Bagaimana kompiler TS memahami bahwa nama modul ini dipetakan ke berbagai folder yang direferensikan? Apakah akan mengambil file package.json yang ditempatkan di setiap folder yang direferensikan? Bagaimana ini akan berbeda dari Lerna atau Yarn Workspaces? Pandangan awal saya ke tautan di atas membuat saya berpikir saya perlu menggunakan proyek TS (build) dalam kombinasi dengan Lerna (dep linking dan penerbitan) untuk mendapatkan solusi yang berfungsi, tetapi saya tidak melihat bagaimana TS akan membangun dengan benar jika tidak dapat berintegrasi dengan package.json dan node_modules. Sumber repo TS sangat berbeda dari proyek Lerna rata-rata Anda (tidak ada yang benar-benar seperti itu), jadi saya mulai bertanya-tanya apakah ini akan dapat memenuhi kebutuhan kita. Informasi lebih lanjut yang dapat Anda berikan, dan khususnya. pengaturan solusi demo yang berfungsi mirip dengan yang saya jelaskan di sini, akan sangat membantu. Terima kasih!

Saya berbagi pertanyaan yang sama dengan @EisenbergEffect. Secara khusus saya juga berharap ini akan bekerja dengan baik dengan lerna -managed monorepo.

Dua skenario monorepo untuk dipertimbangkan

Mari kita mulai dengan pengaturan di mana Anda telah menghubungkan semuanya dengan lerna:

/packages
  /a
    /node_modules
      /b -> symlink to b with package.json "types" pointing to dist/index.d.ts
  /b
    /dist
      /index.d.ts -> built output of entry point declaration file

Hal utama yang kita inginkan terjadi di sini adalah untuk membangun kembali b kita bangun a jika a sudah kedaluwarsa. Jadi kami akan menambahkan "references": [ { "path": "../b" } ] ke a 's tsconfig.json dan menjalankan tsc --build di a untuk mendapatkan build upstream yang benar dari b . Di dunia ini, referensi proyek hanya berfungsi sebagai representasi dari grafik build dan memungkinkan untuk membangun kembali peningkatan yang lebih cerdas. Idealnya lerna dan TS dapat bekerja sama di sini dan mencerminkan dependensi package.json menjadi tsconfig.json jika sesuai.

Skenario lain (mungkin kurang umum) adalah jika Anda tidak menghubungkan tetapi masih ingin "bertindak seolah-olah" Anda sedang mengerjakan serangkaian paket langsung. Anda dapat melakukannya hari ini dengan beberapa pemetaan jalur yang cukup membosankan, dan beberapa orang melakukannya. Referensi proyek di sini juga akan membantu dengan pemesanan build, tetapi akan sangat diinginkan untuk memiliki dukungan untuk properti di file tsconfig referensi untuk secara otomatis membuat pemetaan jalur kapan pun itu direferensikan; misalnya jika Anda punya

{
  "compilerOptions": { "outDir": "bin" },
  "package": "@RyanCavanaugh/coolstuff"
}

kemudian menambahkan "references": [{ "path": "../cool" }] akan secara otomatis menambahkan pemetaan jalur dari @RyanCavanaugh/coolstuff -> ../cool/bin/ . Kami belum menambahkan ini tetapi dapat melihat ke dalamnya jika ternyata menjadi skenario yang lebih umum.

Idealnya lerna dan TS dapat bekerja sama di sini dan mencerminkan dependensi package.json ke tsconfig.json jika sesuai

Daripada mengandalkan alat eksternal, kami dapat memilih untuk membaca package.json (asalkan ada di samping tsconfig Anda) sebagai referensi potensial jika composite: true disetel (periksa untuk melihat apakah setiap paket yang diselesaikan memiliki tsconfig.json , jika ada, anggap itu sebagai simpul proyek yang dapat dibangun dan berulang). Karena semuanya terhubung ke tempatnya, kita bahkan tidak perlu mengubah resolusi (banyak? ada?) untuk menangani ruang kerja. Lerna tidak benar-benar mengatur hal-hal khusus ts (atau khusus bangunan) seperti afaik, itu hanya menghubungkan semuanya ke tempatnya dan mengelola pembuatan versi. Ini akan menjadi optimasi atas apa yang kita lakukan hari ini, yaitu memuat file ts (karena kita lebih memilih itu daripada deklarasi) dan mengkompilasi ulang semuanya terlepas dari kedaluwarsa.

@RyanCavanaugh Ini terdengar sangat menarik. Adakah ide apakah itu akan bekerja dengan strategi symlinking Rush ? Singkatnya, Rush membuat paket sintetis common/temp/package.json yang berisi superset dari semua dependensi untuk semua paket dalam repo. Kemudian kami menggunakan pnpm untuk melakukan operasi instalasi tunggal untuk paket sintetis ini. (PNPM menggunakan symlink untuk membuat grafik berarah-asiklik alih-alih struktur pohon NPM, yang menghilangkan contoh perpustakaan yang diduplikasi). Kemudian Rush membuat folder node_modules untuk setiap proyek di repo, terbuat dari symlink yang menunjuk ke folder yang sesuai di bawah common/temp . Hasilnya sepenuhnya kompatibel dengan TypeScript dan algoritma resolusi NodeJS standar. Ini sangat cepat karena ada satu file shrinkwrap dan satu persamaan versi untuk seluruh repo, sambil tetap mengizinkan setiap paket untuk menentukan dependensinya sendiri.

Kami tidak memasukkan sesuatu yang istimewa di tsconfig.json untuk model ini. Jika beberapa konfigurasi TypeScript khusus diperlukan untuk fitur goto-definition, kami idealnya ingin membuat otomatis selama instalasi daripada menyimpannya di Git.

@pgonzal Terima kasih atas tautan ke Rush! Saya belum melihat itu. Aku akan memeriksanya malam ini.

@RyanCavanaugh Terima kasih atas penjelasannya. Skenario pertama Anda dengan lerna paling dekat dengan apa yang kita miliki. Inilah repo UX kami dengan TS dan lerna sebagai contoh dari sesuatu yang kami ingin gunakan dukungan proyek baru di https://github.com/aurelia/ux

@weswigham Kedengarannya seperti yang Anda gambarkan akan sesuai dengan skenario kami juga. Contoh repo di atas.

Sekedar catatan bahwa dalam kasus ruang kerja benang, modul tidak disinkronkan di setiap direktori paket individual, melainkan disinkronkan di ruang kerja tingkat atas node_modules .

Itulah mengapa saya berpikir bahwa referensi yang tidak dimulai dengan titik ('./' atau '../') harus dicadangkan untuk masa mendatang. Mudah-mudahan itu akan berakhir menjadi "referensi bernama", ditangani melalui strategi resolusi modul aktif alih-alih diperlakukan sebagai jalur relatif.

@spion kami hanya akan menggunakan nama properti selain path untuk itu jika diperlukan (misalnya "references": [ { "module": "@foo/baz" } ] ); Saya tidak ingin menimbulkan kebingungan dimana "bar" dan "./bar" arti yang sama di files tetapi hal yang berbeda di references

Dokumen/posting blog sedang dalam proses di bawah (akan mengedit ini berdasarkan umpan balik)

Saya akan mendorong siapa pun yang mengikuti utas ini untuk mencobanya. Saya sedang mengerjakan skenario monorepo sekarang untuk memperbaiki bug/fitur terakhir di sana dan akan segera mendapatkan panduan tentangnya


Referensi Proyek

Referensi proyek adalah fitur baru di TypeScript 3.0 yang memungkinkan Anda untuk menyusun program TypeScript Anda menjadi bagian yang lebih kecil.

Dengan melakukan ini, Anda dapat sangat meningkatkan waktu pembuatan, menerapkan pemisahan logis antar komponen, dan mengatur kode Anda dengan cara baru dan lebih baik.

Kami juga memperkenalkan mode baru untuk tsc , flag --build , yang bekerja bersama dengan referensi proyek untuk memungkinkan pembuatan TypeScript yang lebih cepat.

Contoh Proyek

Mari kita lihat program yang cukup normal dan lihat bagaimana referensi proyek dapat membantu kita mengaturnya dengan lebih baik.
Bayangkan Anda memiliki proyek dengan dua modul, converter dan units , dan file pengujian yang sesuai untuk masing-masing:

/src/converter.ts
/src/units.ts
/test/converter-tests.ts
/test/units-tests.ts
/tsconfig.json

File pengujian mengimpor file implementasi dan melakukan beberapa pengujian:

// converter-tests.ts
import * as converter from "../converter";

assert.areEqual(converter.celsiusToFahrenheit(0), 32);

Sebelumnya, struktur ini agak canggung untuk digunakan jika Anda menggunakan satu file tsconfig:

  • File implementasi dapat mengimpor file pengujian
  • Tidak mungkin membangun test dan src bersamaan tanpa src muncul di nama folder keluaran, yang mungkin tidak Anda inginkan
  • Mengubah hanya internal dalam file implementasi memerlukan pemeriksaan ketik pengujian lagi, meskipun ini tidak akan pernah menyebabkan kesalahan baru
  • Mengubah hanya tes yang diperlukan, memeriksa implementasi lagi, bahkan jika tidak ada yang berubah

Anda dapat menggunakan beberapa file tsconfig untuk menyelesaikan beberapa masalah tersebut, tetapi yang baru akan muncul:

  • Tidak ada pemeriksaan terkini, jadi Anda akhirnya selalu menjalankan tsc dua kali
  • Memanggil tsc dua kali menimbulkan lebih banyak overhead waktu startup
  • tsc -w tidak dapat dijalankan pada beberapa file konfigurasi sekaligus

Referensi proyek dapat menyelesaikan semua masalah ini dan banyak lagi.

Apa itu Referensi Proyek?

File tsconfig.json memiliki properti tingkat atas baru, references . Ini adalah array objek yang menentukan proyek untuk referensi:

{
    "compilerOptions": {
        // The usual
    },
    "references": [
        { "path": "../src" }
    ]
}

Properti path dari setiap referensi dapat menunjuk ke direktori yang berisi file tsconfig.json , atau ke file konfigurasi itu sendiri (yang mungkin memiliki nama apa pun).

Saat Anda mereferensikan sebuah proyek, hal-hal baru terjadi:

  • Mengimpor modul dari proyek yang direferensikan akan memuat file deklarasi keluarannya ( .d.ts )
  • Jika proyek yang direferensikan menghasilkan outFile , deklarasi file .d.ts file output akan terlihat dalam proyek ini
  • Mode build (lihat di bawah) akan secara otomatis membangun proyek yang direferensikan jika diperlukan

Dengan memisahkan menjadi beberapa proyek, Anda dapat sangat meningkatkan kecepatan pengecekan dan kompilasi, mengurangi penggunaan memori saat menggunakan editor, dan meningkatkan penegakan pengelompokan logis program Anda.

composite

Proyek yang direferensikan harus mengaktifkan setelan composite .
Pengaturan ini diperlukan untuk memastikan TypeScript dapat dengan cepat menentukan di mana menemukan output dari proyek yang direferensikan.
Mengaktifkan flag composite mengubah beberapa hal:

  • Pengaturan rootDir , jika tidak disetel secara eksplisit, default ke direktori yang berisi file tsconfig
  • Semua file implementasi harus dicocokkan dengan pola include atau terdaftar dalam larik files . Jika batasan ini dilanggar, tsc akan memberi tahu Anda file mana yang tidak ditentukan
  • declaration harus diaktifkan

declarationMaps

Kami juga telah menambahkan dukungan untuk peta sumber deklarasi .
Jika Anda mengaktifkan --declarationMap , Anda akan dapat menggunakan fitur editor seperti "Buka Definisi" dan Ganti Nama untuk menavigasi dan mengedit kode secara transparan melintasi batas proyek di editor yang didukung.

prepend dengan outFile

Anda juga dapat mengaktifkan prepending output dari dependensi menggunakan opsi prepend dalam referensi:

   "references": [
       { "path": "../utils", "prepend": true }
   ]

Memulai proyek akan mencakup keluaran proyek di atas keluaran proyek saat ini.
Ini berfungsi untuk file .js dan file .d.ts , dan file peta sumber juga akan dipancarkan dengan benar.

tsc hanya akan pernah menggunakan file yang ada di disk untuk melakukan proses ini, jadi dimungkinkan untuk membuat proyek di mana file output yang benar tidak dapat dihasilkan karena beberapa output proyek akan ada lebih dari sekali dalam file yang dihasilkan .
Sebagai contoh:

  ^ ^ 
 /   \
B     C
 ^   ^
  \ /
   D

Dalam situasi ini, penting untuk tidak menambahkan di setiap referensi, karena Anda akan mendapatkan dua salinan A dalam output D - ini dapat menyebabkan hasil yang tidak diharapkan.

Peringatan untuk Referensi Proyek

Referensi proyek memiliki beberapa trade-off yang harus Anda ketahui.

Karena proyek dependen menggunakan file .d.ts yang dibuat dari dependensinya, Anda harus memeriksa keluaran build tertentu atau membangun proyek setelah mengkloningnya sebelum Anda dapat menavigasi proyek di editor tanpa melihat yang palsu kesalahan.
Kami sedang mengerjakan proses pembuatan .d.ts di balik layar yang seharusnya dapat mengurangi hal ini, tetapi untuk saat ini kami menyarankan untuk memberi tahu pengembang bahwa mereka harus membangun setelah kloning.

Selain itu, untuk menjaga kompatibilitas dengan alur kerja build yang ada, tsc tidak akan secara otomatis membangun dependensi kecuali dipanggil dengan sakelar --build .
Mari pelajari lebih lanjut tentang --build .

Membangun Mode untuk TypeScript

Fitur yang telah lama ditunggu-tunggu adalah build inkremental cerdas untuk proyek TypeScript.
Di 3.0 Anda dapat menggunakan flag --build dengan tsc .
Ini secara efektif merupakan titik masuk baru untuk tsc yang berperilaku lebih seperti orkestra build daripada kompiler sederhana.

Menjalankan tsc --build ( singkatnya tsc -b ) akan melakukan hal berikut:

  • Temukan semua proyek yang dirujuk
  • Deteksi jika mereka mutakhir
  • Bangun proyek kedaluwarsa dalam urutan yang benar

Anda dapat memberikan tsc -b dengan beberapa jalur file konfigurasi (misalnya tsc -b src test ).
Sama seperti tsc -p , menentukan nama file konfigurasi itu sendiri tidak perlu jika bernama tsconfig.json .

tsc -b Baris Perintah

Anda dapat menentukan sejumlah file konfigurasi:

 > tsc -b                                # Build the tsconfig.json in the current directory
 > tsc -b src                            # Build src/tsconfig.json
 > tsc -b foo/release.tsconfig.json bar  # Build foo/release.tsconfig.json and bar/tsconfig.json

Jangan khawatir tentang memesan file yang Anda berikan pada baris perintah - tsc akan memesan ulang jika diperlukan sehingga dependensi selalu dibangun terlebih dahulu.

Ada juga beberapa flag khusus untuk tsc -b :

  • --verbose : Mencetak log verbose untuk menjelaskan apa yang terjadi (dapat digabungkan dengan flag lain)
  • --dry : Menunjukkan apa yang akan dilakukan tetapi tidak benar-benar membangun apa pun
  • --clean : Menghapus output dari proyek yang ditentukan (dapat digabungkan dengan --dry )
  • --force : Bertindak seolah-olah semua proyek sudah ketinggalan zaman
  • --watch : Mode tontonan (tidak boleh digabungkan dengan bendera apa pun kecuali --verbose )

Peringatan

Biasanya, tsc akan menghasilkan output ( .js dan .d.ts ) dengan adanya sintaks atau kesalahan ketik, kecuali noEmitOnError aktif.
Melakukan ini dalam sistem pembangunan inkremental akan sangat buruk - jika salah satu dependensi Anda yang kedaluwarsa mengalami kesalahan baru, Anda hanya akan melihatnya sekali karena pembangunan berikutnya akan melewatkan pembangunan proyek yang sekarang diperbarui.
Untuk alasan ini, tsc -b secara efektif bertindak seolah-olah noEmitOnError diaktifkan untuk semua proyek.

Jika Anda memeriksa keluaran build apa pun ( .js , .d.ts , .d.ts.map , dll.), Anda mungkin perlu menjalankan build --force setelah kontrol sumber tertentu operasi tergantung pada apakah alat kontrol sumber Anda mempertahankan peta waktu antara salinan lokal dan salinan jarak jauh.

msbuild

Jika Anda memiliki proyek msbuild, Anda dapat mengaktifkan mode build dengan menambahkan

    <TypeScriptBuildMode>true</TypeScriptBuildMode>

ke file proj Anda. Ini akan memungkinkan pembuatan inkremental otomatis serta pembersihan.

Perhatikan bahwa seperti halnya tsconfig.json / -p , properti proyek TypeScript yang ada tidak akan dihormati - semua pengaturan harus dikelola menggunakan file tsconfig Anda.

Beberapa tim telah menyiapkan alur kerja berbasis msbuild di mana file tsconfig memiliki urutan grafik implisit yang sama dengan proyek terkelola yang dipasangkan dengan mereka.
Jika solusi Anda seperti ini, Anda dapat terus menggunakan msbuild dengan tsc -p bersama dengan referensi proyek; ini sepenuhnya dapat dioperasikan.

Panduan

Struktur Keseluruhan

Dengan lebih banyak file tsconfig.json , Anda biasanya ingin menggunakan warisan file Konfigurasi untuk memusatkan opsi kompiler umum Anda.
Dengan cara ini Anda dapat mengubah pengaturan dalam satu file daripada harus mengedit banyak file.

Praktik baik lainnya adalah memiliki file tsconfig.json "solusi" yang hanya memiliki references untuk semua proyek simpul daun Anda.
Ini menyajikan titik masuk sederhana; misalnya dalam repo TypeScript kita cukup menjalankan tsc -b src untuk membangun semua titik akhir karena kita mencantumkan semua subproyek di src/tsconfig.json
Perhatikan bahwa mulai dari 3.0, tidak ada lagi kesalahan untuk memiliki array files kosong jika Anda memiliki setidaknya satu reference dalam file tsconfig.json .

Anda dapat melihat pola ini di repo TypeScript - lihat src/tsconfig_base.json , src/tsconfig.json , dan src/tsc/tsconfig.json sebagai contoh utama.

Penataan untuk modul relatif

Secara umum, tidak banyak yang diperlukan untuk mentransisikan repo menggunakan modul relatif.
Cukup tempatkan file tsconfig.json di setiap subdirektori dari folder induk yang diberikan, dan tambahkan reference s ke file konfigurasi ini agar sesuai dengan lapisan program yang diinginkan.
Anda perlu menyetel outDir ke subfolder eksplisit dari folder output, atau menyetel rootDir ke root umum semua folder proyek.

Penataan untuk outFiles

Tata letak untuk kompilasi menggunakan outFile lebih fleksibel karena jalur relatif tidak terlalu penting.
Satu hal yang perlu diingat adalah bahwa Anda biasanya tidak ingin menggunakan prepend hingga proyek "terakhir" - ini akan meningkatkan waktu pembuatan dan mengurangi jumlah I/O yang dibutuhkan dalam setiap bangunan.
Repo TypeScript sendiri adalah referensi yang bagus di sini - kami memiliki beberapa proyek "perpustakaan" dan beberapa proyek "titik akhir"; proyek "titik akhir" disimpan sekecil mungkin dan hanya menarik perpustakaan yang mereka butuhkan.

Penataan untuk monorepos

TODO: Eksperimen lebih banyak dan cari tahu ini. Rush dan Lerna tampaknya memiliki model berbeda yang menyiratkan hal berbeda di pihak kami

Juga mencari umpan balik di #25164

@RyanCavanaugh Tulisan yang sangat bagus, dan fitur luar biasa, akan sangat menyenangkan untuk dicoba, khususnya. setelah saya menghabiskan berhari-hari mengatur proyek besar kami menjadi sub-proyek dengan referensi file konfigurasi.

Saya punya beberapa catatan:

  1. Apa itu monorepo? Akan lebih baik untuk menggambarkan kasus penggunaan ini sedikit lebih banyak.
  2. Dalam kebanyakan kasus (terutama benar untuk proyek besar), ada banyak artefak tambahan yang dihasilkan selama pembangunan. Dalam kasus kami ini adalah CSS, HTML, file Gambar, dll, melalui gulp. Saya bertanya-tanya bagaimana penggunaan alat build seperti itu akan diadopsi ke cara baru dalam melakukan sesuatu. Katakanlah, saya ingin menjalankan watch tidak hanya pada file *.ts, tetapi pada semua file kami yang lain (gaya, markup, dll). Bagaimana cara melakukannya? Perlu dijalankan, katakan gulp watch dan tsc -b -w secara paralel?

@vvs a monorepo adalah kumpulan paket NPM yang biasanya dikelola oleh alat seperti Rush atau Lerna

Jika Anda menggunakan gulp, Anda ingin menggunakan loader yang memahami referensi proyek secara asli untuk mendapatkan pengalaman terbaik. @rbuckton telah melakukan beberapa pekerjaan di sini karena kami memiliki beberapa pengembang yang menggunakan gulpfile secara internal; mungkin dia bisa mempertimbangkan seperti apa pola yang bagus di sana

@RyanCavanaugh Ini terlihat bagus. Saya sangat tertarik dengan bimbingan Lerna :)

@RyanCavanaugh ini tampak hebat, saat ini saya sedang berusaha mencobanya dengan lerna monorepo kami.

Satu-satunya hal yang tidak jelas bagi saya dalam tulisan Anda adalah opsi prepend . Saya tidak begitu mengerti masalah apa yang ditanganinya, dalam situasi apa Anda ingin menggunakannya, dan apa yang terjadi jika Anda tidak menggunakannya.

Ini luar biasa! Saya bekerja pada ts-loader dan proyek terkait. Apakah perubahan mungkin diperlukan untuk mendukung ini dalam proyek yang menggunakan LanguageServiceHost / WatchHost TypeScript?

(Lihat https://github.com/TypeStrong/ts-loader/blob/master/src/servicesHost.ts untuk contoh dari apa yang saya maksud.)

Jika demikian, semua bimbingan / PR diterima dengan senang hati! Bahkan jika Anda ingin ini diuji di dunia webpack, saya akan dengan senang hati membantu mendorong versi ts-loader yang mendukung ini.

Tentu saja jika itu "berhasil" itu lebih baik :senyum:

Kerja bagus!

@yortus @EisenbergEffect Saya telah menyiapkan contoh lerna repo di https://github.com/RyanCavanaugh/learn-a dengan README yang menguraikan langkah-langkah yang saya ambil untuk membuatnya berfungsi.

Jika saya mengerti dengan benar, tsc -b X tidak akan melakukan apa-apa jika semuanya (X dan semua dependensinya dan dependensi transitif) mutakhir? Ingin tahu apakah itu sesuatu yang bisa kita dapatkan bahkan tanpa flag -b untuk masing-masing proyek tanpa referensi? (dikurangi dependensi dalam kasus itu, tentu saja)

Ini cukup keren. Saya cenderung menggunakan konfigurasi Lerna seperti ini (untuk memisahkan mono repo berdasarkan fungsi). Saya kira itu akan bekerja dengan baik.

{
"lerna": "2.11.0",
"paket": [
"paket/komponen/ ","paket/perpustakaan/ ",
"paket/kerangka/ ","paket/aplikasi/ ",
"paket/alat/*"
],
"versi": "0.0.0"
}

Jadi ini tersedia di typescript@next ?

Saya akan menguji ini dengan repo ruang kerja benang kami. Kita harus menggunakan nohoist untuk beberapa modul yang belum mendukung ruang kerja jadi akan menyenangkan untuk melihat bagaimana menanganinya.

@RyanCavanaugh saya mengambil repo untuk uji coba malam ini. Saya membuka masalah pada repo untuk melaporkan beberapa masalah yang saya miliki. Terima kasih lagi untuk menempatkan ini bersama-sama. Saya tidak sabar untuk segera menggunakannya.

Sangat menarik! Saat ini di perusahaan saya, kami menggunakan alat saya sendiri yang disebut mtsc untuk mendukung mode menonton beberapa proyek secara bersamaan. Kami memiliki sekitar 5 proyek yang perlu dikompilasi dan ditonton dalam repo yang sama.

Proyek memiliki konfigurasi yang berbeda seperti; Penargetan ECMA (es5, es6), jenis (node, lelucon, DOM dll), memancarkan (beberapa menggunakan webpack dan beberapa mengkompilasi ke js sendiri). Mereka semua berbagi satu hal, dan itu adalah plugin tslint , sisanya bisa berbeda. Alat saya juga menjalankan tslint setelah kompilasi proyek (per proyek dan berhenti jika proyek dikompilasi ulang sebelum tslint selesai).

Perhatian utama saya dengan proposal saat ini adalah Anda tidak dapat mengatakan proyek mana yang berbagi sumber daya mana. Kami memiliki server dan proyek klien, yang keduanya menggunakan folder utilitas khusus, tetapi kami tidak ingin melihat kesalahan kompilasi dua kali. Tapi itu bisa diperbaiki dengan filter, jadi itu bukan masalah besar :)

Saya telah mencoba mode --build dengan lerna monorepo kami, yang saat ini terdiri dari 17 paket yang saling bergantung. Butuh beberapa saat untuk membuat semuanya berfungsi, tetapi sekarang semuanya berfungsi, dan mampu membangun secara bertahap adalah peningkatan besar bagi kami.

Saya memang mengalami beberapa masalah yang saya jelaskan di bawah ini. Saya harap ini adalah umpan balik yang berguna untuk tim TS dan dapat membantu orang lain untuk membuat mode --build bekerja untuk proyek mereka.

Umpan balik untuk mode tsc --build

1. Palsu "\sudah kedaluwarsa karena file keluaran '2.map' tidak ada"

Saya mendapat pesan ini untuk setiap paket di setiap build, jadi setiap build menjadi build ulang penuh meskipun tidak ada yang diubah. Saya perhatikan @RyanCavanaugh telah memperbaiki ini di #25281, jadi tidak masalah lagi jika Anda memperbarui ke 20180628 atau lebih baru setiap malam. Masalah berikut mengasumsikan Anda telah memperbarui setidaknya 20180628 setiap malam.

2. "\up to date dengan file .d.ts dari dependensinya" padahal tidak

EDIT: dilaporkan di #25337.

Untuk mereproduksi masalah ini, atur repo sampel learn-a @RyanCavanaugh sesuai instruksinya . Jalankan tsc -b packages --verbose untuk melihat semuanya dibangun pertama kali. Sekarang ubah baris 1 di pkg1/src/index.ts menjadi import {} from "./foo"; dan simpan. Jalankan tsc -b packages --verbose lagi. Build untuk pkg2 dilewati, meskipun pkg1 diubah sedemikian rupa sehingga merusak source pkg2 . Anda sekarang dapat melihat coretan merah di pkg2/src/index.ts . Bangun lagi dengan tsc -b packages --force dan kesalahan pembuatan ditampilkan. Masalah berikut mengasumsikan membangun dengan --force untuk mengatasi ini.

3. File .d.ts dihasilkan menyebabkan kesalahan pembuatan 'Pengidentifikasi duplikat' dalam paket hilir

EDIT: dilaporkan di #25338.

Untuk mereproduksi masalah ini, atur repo sampel learn-a @RyanCavanaugh sesuai instruksinya . Sekarang jalankan lerna add @types/node untuk menambahkan pengetikan Node.js ke ketiga paket. Jalankan tsc -b packages --force untuk mengonfirmasi bahwa itu masih berfungsi dengan baik. Sekarang tambahkan kode berikut ke pkg1/src/index.ts :

// CASE1 - no build errors in pkg1, but 'duplicate identifier' build errors in pkg2
// import {parse} from 'url';
// export const bar = () => parse('bar');

// CASE2 - no build errors in pkg1 or in downstream packages
// import {parse, UrlWithStringQuery} from 'url';
// export const bar = (): UrlWithStringQuery => parse('bar');

// CASE3 - no build errors in pkg1 or in downstream packages
// export declare const bar: () => import("url").UrlWithStringQuery;

// CASE4 - no build errors in pkg1, but 'duplicate identifier' build errors in pkg2
// import {parse} from 'url';
// type UrlWithStringQuery = import("url").UrlWithStringQuery;
// export const bar = (): UrlWithStringQuery => parse('bar');

Batalkan komentar satu per satu dan jalankan tsc -b packages --force . Kasus 1 dan 4 menyebabkan banjir kesalahan build di pkg2 . Dengan kasus 2 dan 3, tidak ada kesalahan pembuatan. Perbedaan penting dengan kasus 1 dan 4 tampaknya menjadi baris pertama dalam pkg1/lib/index.d.ts dihasilkan :

/// <reference path="../node_modules/@types/node/index.d.ts" />

Kasus 2 dan 3 tidak menghasilkan baris ini. Ketika pkg2 dibuat dalam kasus 1 dan 4, itu mencakup dua salinan identik dari deklarasi @types/node di jalur yang berbeda, dan itu menyebabkan kesalahan 'pengidentifikasi duplikat'.

Mungkin ini dirancang karena kasus 2 dan 3 berfungsi. Namun tampaknya cukup membingungkan. Tidak ada kesalahan atau peringatan build di pkg1 untuk salah satu dari 4 kasus ini, tetapi perilaku build downstream sangat sensitif terhadap gaya yang tepat dari deklarasi yang diekspor. Saya pikir (a) pkg1 harus error untuk kasus 1 & 4, atau (b) keempat kasus harus memiliki perilaku build hilir yang sama, atau (c) harus ada panduan yang jelas dari tim TS tentang bagaimana menulis deklarasi untuk menghindari masalah ini.

4. Masalah dengan import jenis di dihasilkan .d.ts file ketika menggunakan ruang kerja benang

Ketika mencoba untuk mendapatkan modus membangun kerja dengan 17 paket monorepo kami, saya bekerja melalui sejumlah kesalahan membangun disebabkan oleh path relatif di import jenis di dihasilkan .d.ts file. Saya akhirnya menemukan bahwa masalah yang terkait dengan pengangkatan modul. Yaitu, ketika menggunakan ruang kerja benang, semua modul yang diinstal diangkat ke direktori monorepo-root node_modules , termasuk symlink untuk semua paket di monorepo. Saya mengubah monorepo untuk menggunakan properti packages di lerna.json , yang menyebabkan lerna menggunakan algoritma bootstrap non-hoisting sendiri, dan itu memecahkan masalah. Bagaimanapun, ini adalah pendekatan yang lebih baik/aman, meskipun lebih lambat.

Saya tidak yakin apakah TS bermaksud untuk mendukung pengaturan yang mengangkat modul, jadi saya belum mengembangkan repro untuk masalah yang saya temui, tetapi saya dapat mencoba membuatnya jika ada minat. Saya pikir masalahnya mungkin beberapa build mendapatkan tipe yang sama melalui direktori packages (sesuai pengaturan tsconfig) dan direktori node_modules (sesuai import dalam file .d.ts dihasilkan). Ini terkadang berfungsi karena pengetikan struktural, tetapi gagal untuk hal-hal seperti simbol unik yang diekspor.

5. Konfigurasi berulang

Menyiapkan monorepo untuk menggunakan lerna pada dasarnya hanya membutuhkan meletakkan sesuatu seperti "packages": ["packages/*"] di lerna.json . Lerna mengerjakan daftar paket yang tepat dengan memperluas globstars, dan kemudian mengerjakan grafik dependensi yang tepat dengan melihat dependensi yang dideklarasikan dalam package.json setiap paket. Anda dapat menambah dan menghapus paket dan dependensi sesuka hati, dan lerna terus berjalan tanpa perlu menyentuh konfigurasinya.

Mode TypeScript --build melibatkan sedikit lebih banyak upacara. Pola Glob tidak diakui, sehingga semua paket harus secara eksplisit terdaftar dan dipelihara (misalnya di packages/tsconfig.json ) di @RyanCavanaugh 's learn-a repo sampel. Mode build tidak melihat dependensi package.json , jadi setiap paket harus mempertahankan daftar paket lain yang bergantung pada file package.json (di bawah "dependencies" ) serta itu adalah file tsconfig.json (di bawah "references" ).

Ini adalah ketidaknyamanan kecil, tetapi saya memasukkannya di sini karena saya menemukan omong kosong yang terlihat dibandingkan dengan pendekatan lerna's .

6. tsc crash dengan augmentasi modul global

EDIT: dilaporkan di #25339.

Untuk mereproduksi masalah ini, siapkan repo sampel learn-a @RyanCavanaugh sesuai instruksinya . Sekarang jalankan lerna add @types/multer untuk menambahkan pengetikan multer ke ketiga paket. Jalankan tsc -b packages --force untuk mengonfirmasi bahwa itu masih berfungsi dengan baik. Sekarang tambahkan baris berikut ke pkg1/src/index.ts :

export {Options} from 'multer';

Jalankan tsc -b packages --force lagi. Kompiler lumpuh karena pernyataan yang dilanggar. Saya melihat secara singkat jejak dan pernyataan tumpukan, dan tampaknya ada hubungannya dengan augmentasi global dari namespace Express .

terima kasih @yortus atas umpan baliknya. mengandalkan menghargainya. untuk 3, saya pikir itu https://github.com/Microsoft/TypeScript/issues/25278 .

Untuk 4, saya tidak terbiasa dengan modul mengangkat sebagai sebuah konsep. dapatkah Anda menguraikan, dan/atau membagikan repro?

@mhegazy banyak yang menggunakan lerna dan benang menggunakan ruang kerja (termasuk saya sendiri). Info lebih lanjut di sini: https://yarnpkg.com/lang/en/docs/workspaces/

Saat ini saya menggunakan ruang kerja benang, lerna, tsconfig yang diperluas di mana tsconfig dasar menyatakan paths dibagikan untuk semua paket dengan modul hoisted yang ditemukan di bawah root/node_modules . Ketika saya mendengar yarn dan monorepo , saya berpikir workspaces karena itulah maksud dari fitur ini - untuk memudahkan penggunaan dan mengurangi duplikasi. Saya mengharapkan perubahan ini akan dengan mudah menghapus paths saya yang panjang/menyakitkan yang dideklarasikan di tsconfig.

Berikut adalah contoh tsconfig monorepo root kami (jika ada bantuan):

{
  "extends": "./packages/build/tsconfig.base.json",
  "compilerOptions": {
    "baseUrl": "./packages",
    "paths": {
      "@alienfast/build/*": ["./build/src/*"],
      "@alienfast/common-node/*": ["./common-node/src/*"],
      "@alienfast/common/*": ["./common/src/*"],
      "@alienfast/concepts/*": ["./concepts/src/*"],
      "@alienfast/faas/*": ["./faas/src/*"],
      "@alienfast/math/*": ["./math/src/*"],
      "@alienfast/notifications/*": ["./notifications/src/*"],
      "@alienfast/ui/*": ["./ui/src/*"],
      "@alienfast/build": ["./build/src"],
      "@alienfast/common-node": ["./common-node/src"],
      "@alienfast/common": ["./common/src"],
      "@alienfast/concepts": ["./concepts/src"],
      "@alienfast/faas": ["./faas/src"],
      "@alienfast/math": ["./math/src"],
      "@alienfast/notifications": ["./notifications/src"],
      "@alienfast/ui": ["./ui/src"],
    }
  },
  "include": ["./typings/**/*", "./packages/*/src/**/*"],
  "exclude": ["node_modules", "./packages/*/node_modules"]
}

Saya akan mencoba forking untuk sampel:
https://github.com/RyanCavanaugh/learn-a

Ini adalah PR yang tidak dapat digabungkan ke repo
https://github.com/RyanCavanaugh/learn-a/pull/3/files

Kami juga menggunakan modul hoisting di Jupyterlab , dengan lerna dan benang. Hal ini memungkinkan kita untuk pada dasarnya berbagi dependensi terinstal di antara semua paket kita, jadi mereka hanya ada sekali di sistem file, di proyek root.

Saya memahami ruang kerja sedikit lebih bersih daripada harus menggunakan perintah link antara semua paket sehingga mereka dapat mengakses satu sama lain (atau setidaknya mengakses dependensinya).

Seperti di atas, pengangkatan modul memindahkan semua dependensi ke direktori root node_modules . Ini mengambil keuntungan dari fakta bahwa resolusi modul node akan selalu melintasi pohon direktori dan mencari melalui semua direktori node_modules sampai menemukan modul yang diperlukan. Modul individual di monorepo Anda kemudian disinkronkan di root ini node_modules dan semuanya berfungsi. Posting blog benang mungkin menjelaskannya lebih baik daripada yang saya bisa.

Pengangkatan tidak dijamin akan terjadi. Jika Anda memiliki versi yang tidak cocok dari paket yang sama, mereka tidak akan diangkat. Juga, banyak alat yang ada tidak mendukung pengangkatan karena mereka membuat asumsi tentang di mana node_modules akan berada atau mereka tidak mengikuti resolusi modul node dengan benar. Karena itu ada pengaturan nohoist yang dapat menonaktifkan pengangkatan untuk modul atau dependensi tertentu.

Saya menambahkan item keenam ke umpan balik saya tsc lumpuh dalam skenario yang dijelaskan di sana.

@mhegazy Saya tidak yakin item 3 terkait dengan #25278. #25278 menjelaskan emisi deklarasi yang tidak valid. File deklarasi yang saya hasilkan valid secara sintaksis dan semantik, tetapi menyebabkan proyek hilir dibangun dengan dua salinan pengetikan simpul, menghasilkan kesalahan 'pengidentifikasi duplikat'.

Seperti di atas, pengangkatan modul memindahkan semua dependensi ke direktori root node_modules. Ini mengambil keuntungan dari fakta bahwa resolusi modul node akan selalu melintasi pohon direktori dan mencari melalui semua direktori node_modules sampai menemukan modul yang diperlukan.

Btw ada kelemahan model ini, yang mengarah ke "ketergantungan hantu" di mana sebuah proyek dapat mengimpor ketergantungan yang tidak secara eksplisit dideklarasikan dalam file package.json-nya. Saat Anda menerbitkan perpustakaan Anda, ini dapat menyebabkan masalah seperti (1) versi dependensi yang berbeda yang diinstal dari apa yang diuji/diharapkan, atau (2) dependensi hilang sepenuhnya karena diangkat dari proyek yang tidak terkait yang tidak diinstal pada konteks ini. PNPM dan Rush keduanya memiliki pilihan arsitektur yang dimaksudkan untuk melindungi dari ketergantungan hantu.

Saya memiliki pertanyaan umum tentang tsc --build : Apakah kompiler TypeScript berusaha mengambil alih peran mengatur pembangunan untuk proyek dalam monorepo? Biasanya toolchain akan memiliki seluruh jalur tugas, hal-hal seperti:

  • pra-pemrosesan
  • menghasilkan string yang dilokalkan
  • mengonversi aset ke JavaScript (css, gambar, dll)
  • kompilasi (pemeriksaan jenis / transpiling)
  • menggulung file .js (misalnya webpack)
  • menggulung file .d.ts (mis. API Extractor)
  • pasca pemrosesan termasuk pengujian unit dan pembuatan dokumentasi

Biasanya sistem seperti Gulp atau Webpack mengelola saluran ini, dan kompiler hanya satu langkah di tengah rantai. Terkadang alat sekunder juga menjalankan pembangunan dengan cara lain, misalnya Jest+ts-jest untuk jest --watch .

Apakah tsc bertujuan untuk mengelola hal-hal ini sendiri? Dan jika tidak, apakah ada cara bagi orkestra pembangunan konvensional untuk memecahkan grafik ketergantungan itu sendiri, dan misalnya berulang kali memanggil tsc di setiap folder proyek dalam urutan yang benar (setelah prapemrosesan diperbarui)?

Atau, jika desainnya adalah untuk memproses seluruh monorepo dalam satu lintasan (sedangkan hari ini kita membangun setiap proyek dalam proses NodeJs yang terpisah), saya juga ingin tahu bagaimana tugas pembangunan lainnya akan berpartisipasi: Misalnya, apakah kita akan menjalankan webpack di semua proyek sekaligus? (Di masa lalu yang menyebabkan masalah kehabisan memori.) Apakah kita akan kehilangan kemampuan untuk mengeksploitasi konkurensi multi-proses?

Ini bukan kritik BTW. Saya hanya mencoba memahami gambaran besar dan penggunaan yang dimaksudkan.

@pgonzal benar, ada banyak bagian non-tsc untuk membangun monorepo dunia nyata. Untuk lerna monorepo kami, saya mengambil pendekatan berikut:

  • setiap paket dalam monorepo secara opsional mendefinisikan skrip prebuild dan/atau skrip postbuild dalam package.json . Ini berisi aspek non-tsc dari build.
  • di package.json monorepo, ada skrip ini:
    "prebuild": "lerna run prebuild", "build": "tsc --build monorepo.tsconfig.json --verbose", "postbuild": "lerna run postbuild",
  • Itu dia. Menjalankan yarn build pada level monorepo menjalankan skrip prebuild untuk setiap paket yang mendefinisikannya, kemudian menjalankan langkah tsc --build , kemudian menjalankan semua postbuild skrip. (Dengan konvensi di npm dan benang, mengeksekusi npm run foo kira-kira sama dengan npm run prefoo && npm run foo && npm run postfoo .)

Bagaimana Anda menangani jest --watch atau webpack-dev-server ? Misalnya ketika file sumber dimodifikasi, apakah langkah-langkah prebuild/postbuild berjalan lagi?

Apakah ini memiliki implikasi pada ts-node dan alur kerja terkait? Beberapa aplikasi pembantu kami berjalan "langsung" dari TypeScript, seperti "start": "ts-node ./src/app.ts" atau "start:debug": "node -r ts-node/register --inspect-brk ./src/app.ts" .

Melaporkan masalah lain dengan mode build di #25355.

Terima kasih atas semua umpan balik dan investigasi yang luar biasa sejauh ini. Saya sangat menghargai semua orang yang meluangkan waktu untuk mencoba berbagai hal dan menendang ban.

@yortus kembali https://github.com/Microsoft/TypeScript/issues/3469#issuecomment -400439520

Besar write-up, terima kasih lagi untuk menyediakan ini. Masalah Anda berurutan -

  1. Tetap
  2. PR naik di #25370
  3. Membahas pada masalah yang dicatat - tidak segera terlihat apa perbaikan yang tepat, tetapi kami akan melakukan sesuatu
  4. Menyelidiki (di bawah)
  5. Tercatat #25376
  6. Secara teknis tidak terkait dengan --build AFAICT. Ini adalah pernyataan baru yang kami tambahkan baru-baru ini; Nathan sedang menyelidiki

@rosskevin untuk PR di repo learn-a ! Saya akan menggabungkannya menjadi cabang sehingga kita dapat membandingkan dan membedakan dengan lebih baik.

@pgonzal kembali https://github.com/Microsoft/TypeScript/issues/3469#issuecomment -401577442

Saya punya pertanyaan umum tentang tsc --build: Apakah kompiler TypeScript berusaha mengambil alih peran mengatur build untuk proyek dalam monorepo?

Pertanyaan bagus; Saya ingin menjawab yang ini dengan sangat jelas: pasti tidak .

Jika Anda senang hari ini menggunakan tsc untuk membangun proyek Anda, kami ingin Anda bahagia besok menggunakan tsc -b untuk membangun proyek multi-bagian Anda. Jika Anda senang hari ini menggunakan gulp untuk membangun proyek Anda, kami ingin Anda bahagia besok menggunakan gulp untuk membangun proyek multi-bagian Anda. Kami memiliki kendali atas skenario pertama, tetapi membutuhkan pembuat alat dan plugin untuk membantu kami dengan skenario kedua, itulah sebabnya bahkan tsc -b hanyalah pembungkus tipis atas API terbuka yang dapat digunakan oleh pembuat alat untuk membantu referensi proyek bermain dengan baik dalam model bangunan mereka.

Konteks yang lebih luas adalah bahwa ada perdebatan internal yang cukup kuat mengenai apakah tsc -b bahkan harus ada, atau sebagai gantinya menjadi alat / titik masuk yang terpisah - membangun orkestra bangunan tujuan umum adalah tugas yang sangat besar dan bukan tugas kami. mendaftar untuk. Untuk repo kami sendiri, kami menggunakan tsc dengan kerangka kerja pelari tugas ringan dan sekarang menggunakan tsc -b dengan pelari tugas yang sama, dan saya berharap orang lain yang bermigrasi juga mempertahankan rantai pembangunan yang ada di tempatnya dengan hanya tweak kecil.

@borekb kembali https://github.com/Microsoft/TypeScript/issues/3469#issuecomment -401593804

Apakah ini memiliki implikasi pada ts-node dan alur kerja terkait? Beberapa aplikasi pembantu kami berjalan "langsung" dari TypeScript

Untuk skrip file tunggal, yang secara implisit tidak dapat memiliki referensi proyek, tidak ada dampak sama sekali.

@EisenbergEffect memiliki beberapa pertanyaan di repo learn-a tentang penggantian nama lintas proyek dan fitur layanan bahasa lainnya. Pertanyaan besar yang terbuka di sini adalah apakah kita bisa mendapatkan fitur ini dalam keadaan yang dapat digunakan untuk 3.0 atau tidak. Jika demikian, maka penggantian nama lintas-proyek akan "hanya berfungsi", tunduk pada peringatan bahwa jelas tidak mungkin bagi kami untuk secara meyakinkan menemukan semua proyek hilir dan memperbaruinya - ini akan menjadi "upaya terbaik" berdasarkan beberapa heuristik untuk mencari yang lain proyek.

Jika menurut kami penggantian nama lintas proyek tidak dapat diterima stabil+lengkap untuk 3.0, kami kemungkinan akan memblokir operasi penggantian nama hanya ketika simbol yang diganti namanya ada di file keluaran .d.ts dari proyek lain - memungkinkan Anda melakukan ini sangat membingungkan karena file .d.ts akan diperbarui pada build berikutnya dari proyek upstream setelah proyek upstream telah dimodifikasi, yang berarti dapat dengan mudah berhari-hari antara saat Anda membuat penggantian nama lokal dan ketika Anda menyadari bahwa kode yang dideklarasikan belum benar-benar diperbarui.

Untuk fitur seperti Go to Definition, ini berfungsi hari ini di VS Code dan akan berfungsi di luar kotak di versi Visual Studio yang akan datang. Semua fitur ini memerlukan file .d.ts.map untuk diaktifkan (aktifkan declarationMap ). Ada beberapa pekerjaan per-fitur untuk menerangi ini, jadi jika Anda melihat sesuatu tidak berfungsi seperti yang diharapkan, lakukan log bug karena kami mungkin melewatkan beberapa kasus.

Buka masalah yang saya lacak saat ini:

  • Ganti nama lintas proyek - @andy-ms sedang mengimplementasikan
  • Perlu menganalisis pengaturan modul yang diangkat dan memahami implikasinya - pada saya
  • Harus ada versi sampel repo learn-a yang menggunakan yarn , dan versi lain yang menggunakan pnpm , dan versi lain yang menggunakan salah satunya dalam mode hoisted

Pertanyaan-pertanyaan terbuka

  • Haruskah kita menerapkan logika untuk membaca package.json s untuk menyimpulkan referensi proyek? Tercatat #25376
  • Haruskah .d.ts.map memancarkan secara implisit untuk proyek composite ?

@RyanCavanaugh untuk ditambahkan ke

Buka masalah yang saya lacak saat ini

Kami juga telah menyebutkan memiliki cache keluaran tambahan, terpisah dari lokasi keluaran proyek nyata, untuk menangani hal-hal seperti memperbarui deklarasi di latar belakang di LS (hari ini, perubahan tidak menyebar melintasi batas proyek di editor sampai Anda membangun), stripInternal , dan mengubah proses build (di mana output build kami dimutasi di tempatnya sehingga tidak cocok untuk operasi LS).

maaf untuk pertanyaan bodoh, karena sudah diperiksa di peta jalan, bagaimana cara mengaktifkan fitur ini?

@aleksey-bykov Anda dapat menggunakannya di TypeScript@next.

Saya baru saja mencoba ini pada monorepo bertenaga ruang kerja benang kami dan itu bekerja dengan baik.

Satu hal yang saya perhatikan adalah tsc --build --watch melaporkan kesalahan tetapi kemudian tidak mengeluarkan apa pun untuk mengatakan bahwa build sekarang sudah diperbaiki. Mode jam standar tsc di 2.9 telah mulai memberikan hitungan kesalahan dan senang melihat angka nol di sana sehingga Anda tahu bahwa pembangunan telah selesai.

saya memiliki folder yang penuh dengan *.d.ts dan tidak ada lagi yang harus saya lakukan:

  • jadikan itu proyek dan rujuk (mencoba, tidak berhasil)
  • gunakan "sertakan" untuk itu

@timfish umpan balik itu cocok dengan yang lain yang pernah saya dengar; login #25562

@aleksey-bykov https://github.com/Microsoft/TypeScript/issues/3469#issuecomment -400439520 akan membantu menjelaskan beberapa konsep

@RyanCavanaugh sepertinya referensi proyek hanya berfungsi untuk resolusi modul commonjs dan node, bukan?

pada kamu contoh:

import * as p1 from "@ryancavanaugh/pkg1";
import * as p2 from "@ryancavanaugh/pkg2";

p1.fn();
p2.fn4();
  1. apa itu modul @ryancavanaugh , apakah ada hubungannya dengan bagaimana TS menyelesaikan modul?
  2. apakah contoh ini seharusnya berfungsi dengan AMD (resolusi modul klasik)?
  3. apakah outFile diperlukan agar definisi dapat ditemukan?
  4. di mana file d.ts seharusnya berada untuk proyek referensi untuk menemukannya (dapatkah saya masih menggunakan outDir? akankah TS menemukannya di sana?)

saya punya 2 proyek sederhana essentials dan common dan kesamaan tidak dapat menyelesaikan hal-hal yang dikompilasi dalam hal-hal penting:

image

@aleksey-bykov

  1. Itu hanya nama modul yang dicakup, diselesaikan di bawah algoritma resolusi modul node biasa
  2. Anda dapat menggunakan referensi proyek dengan sistem modul apa pun termasuk klasik, tetapi nama contoh (modul cakupan) tidak terlalu ramah untuk digunakan di luar simpul
  3. Tidak
  4. TypeScript mencari file .d.ts berada di tempat di mana proyek yang direferensikan membangunnya

Jika Anda memiliki sampel repo atau sesuatu, saya dapat mendiagnosis mengapa Anda mendapatkan kesalahan itu

@RyanCavanaugh tolong lakukan
contoh.zip

@RyanCavanaugh , sepertinya tsc --build --watch awalnya tidak menampilkan file apa pun sampai ia melihat modifikasi file sumber.

Utas terlalu panjang (dalam ruang dan waktu); yuk ikuti pembahasannya di lucky issue nomor 100*2^8 : #25600

Apakah halaman ini membantu?
0 / 5 - 0 peringkat