Rollup-plugin-typescript2: Lihat impor file

Dibuat pada 9 Jan 2019  ·  14Komentar  ·  Sumber: ezolenko/rollup-plugin-typescript2

Saat beralih dari rollup-plugin-typescript ke rollup-plugin-typescript2 untuk menghasilkan file deklarasi, file *.vue tidak dikenali lagi.

[!] (rpt2 plugin) Error: someFolder/index.ts(2,53): semantic error TS2307 Cannot find module './component.vue'.
src\index.ts
Error: someFolder/index.ts(2,53): semantic error TS2307 Cannot find module './component.vue'.

Mencoba dengan hanya mengimpor rollup-plugin-typescript alih-alih rollup-plugin-typescript2 bundel tanpa masalah.

Ini dapat dikaitkan dengan masalah ini meskipun saya memiliki versi terakhir (dari setiap plugin hari ini memang).

bug help wanted

Komentar yang paling membantu

Ini berfungsi untuk saya dengan pengaturan ini, untuk mengkompilasi satu komponen vue:

Benar, tapi itu bukan kasus penggunaan yang sebenarnya. Itu halo dunia. Bagi siapa pun yang kesulitan memahami masalahnya, inilah yang saya kumpulkan.

rollup benar-benar tidak bisa melakukan ini

Mengapa? ini contohnya:

<script lang="ts">
import Bar from './Bar.vue';
...
</script>

1) plugin vue meneruskan skrip ke plugin TypeScript
2) plugin TypeScript menemukan file .vue , tetapi tidak tahu apa yang harus dilakukan dengannya karena rollup tidak menyediakan mekanisme bagi plugin untuk menunda plugin lain pada impor seperti webpack. JS biasa dapat menunda plugin, tetapi kode yang sudah diproses oleh plugin tidak bisa.
3) Saya sebenarnya tidak mengerti mengapa ini berbeda dari lang=scss atau lang=ts , tapi saya rasa.

Nah, apa yang bisa saya lakukan?

Tidak banyak.

Tapi vuetifikasi! gemuk!

Vuetify adalah TypeScript, tetapi tidak menggunakan SFC. Ini adalah fungsi render murni.

Buefy menggunakan SFC dan rollup, tetapi tidak ada TypeScript.

Sungguh, tidak ada yang bisa kulakukan?

Anda tidak akan menyukainya. Untuk setiap file Vue yang perlu Anda impor dari file TypeScript, Anda harus membuat perantara file javascript biasa.

import Bar from './Bar.vue';

export default Bar;

Kemudian dan baru setelah itu Anda dapat membangun lib komponen SFC TypeScript Anda dengan rollup.

astaga, itu menyebalkan

Jika Anda menemukan solusi yang lebih baik, saya akan senang mendengarnya.

Semua 14 komentar

Bisakah Anda memposting konfigurasi tsconfig dan rollup Anda?

Atau repo kecil dengan reproduksi :)

Sayangnya saya tidak memiliki repo "kecil". Saya bekerja di sini , mencoba bermigrasi dari webpack ke rollup .

Impor di rollup.config.js dapat diubah menjadi rollup-plugin-typescript2 untuk melihat perbedaannya.

Halo.

Pertama-tama terima kasih banyak untuk bekerja pada plugin ini. Itu memang lebih masuk akal daripada rollup-plugin-typescript .

Saya dapat mengonfirmasi bahwa masalah ini ada dan menyiapkan repositori demo kecil:
https://github.com/danimoh/rollup-plugin-typescript2-vue-demo

Jika Anda mengomentari baris import AnotherComponent from './AnotherComponent.vue'; , baris ini dapat dikompilasi, tetapi sayangnya tidak dengan baris ini diaktifkan.

Sangat lucu bahwa kami mengalami masalah ini pada waktu yang hampir bersamaan. Mungkin itu disebabkan oleh perubahan baru-baru ini?
Tebakan dari pihak saya dengan pengetahuan yang sangat terbatas tentang rollup, plugin rollup, dan TypeScript adalah:
Mungkinkah TypeScript itu sendiri mencoba mengimpor AnotherComponent alih-alih rollup atau rollup-plugin-vue menangani impor itu terlebih dahulu?

Itu akan menjelaskan mengapa rollup-plugin-typescript tidak memiliki masalah ini karena dikompilasi berdasarkan per file dengan transpileModule .

Dalam hal ini, berikut ini mungkin menarik: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#customizing -module-resolution

Setiap pekerjaan tentang masalah ini sangat dihargai.

Direproduksi pada kedua repo, tidak yakin apakah itu masalah yang sama, tetapi kemungkinan besar.

Untuk memperbaiki kasus kedua, kami memang perlu mengirim resolusi modul kembali ke rollup sehingga plugin vue dapat melakukannya.

Masalah dengan menghubungkan resolusi modul rollup dan TypeScript adalah bahwa rollup di versi yang lebih baru mengembalikan Janji dari context.resolveId(...) . Jadi rantai panggilan terlihat seperti ini:

  • rollup panggilan transformasi plugin
  • plugin memanggil LanguageService.getEmitOutput dari TypeScript
  • layanan bahasa memanggil implementasi plugin dari LanguageHost.resolveModuleNames dan mengharapkan jalur yang diselesaikan dikembalikan dalam fungsi itu
  • panggilan host rollup PluginContext.resolveId
  • rollup mengembalikan Janji
  • jika saya mengerti dengan benar, yang bisa saya lakukan dengan sebuah janji adalah membuat janji lain

LanguageService tampaknya sangat sinkron: https://github.com/Microsoft/TypeScript/issues/1857

Plugin.transform sendiri dapat mengembalikan Janji, tetapi mekanisme rantai beberapa janji yang dibuat jauh di dalam panggilan balik pada objek pengamat menghindari saya saat ini.

Halo ezolenko.

Saat ini metode asinkron dalam Javascript sebagian besar berarti metode yang mengembalikan Janji. Sintaks async / await yang baru pada dasarnya hanyalah gula sintaksis untuk metode asinkron yang memungkinkan pengembang untuk menulis kodenya mirip dengan kode sinkron, metode async masih memberikan janji. await hanya dapat digunakan dalam metode async . Seperti yang Anda perhatikan, metode LanguageHost.resolveModuleNames tidak asinkron dan oleh karena itu tidak mungkin untuk kembali dari metode itu hanya setelah menunggu janji dalam Javascript biasa.

Namun, di NodeJs, hal-hal seperti ini sebenarnya dimungkinkan dengan menghasilkan metode sinkron pada utas saat ini, kemudian melompat ke metode async dan melompat kembali ke metode sinkron ketika metode asinkron selesai. Lihat Serat atau pembungkus di sekitarnya seperti sinkronisasi.js .

Jadi, hal dengan pemanggilan metode async sebenarnya bukan masalah besar. Padahal mungkin ada masalah lain. Sementara konteks plugin menawarkan metode resolveId , itu tidak akan cukup. Kita perlu memanggil transform dari rollup-plugin-vue untuk mengekstrak kode TypeScript dari komponen file tunggal vue. Konteks plugin tampaknya tidak menawarkan fungsionalitas itu sayangnya.

Salah satu pendekatan untuk mengatasi ini mungkin dengan menambahkan rollup-plugin-vue sebagai ketergantungan pada proyek Anda dan memicu transform pada plugin vue secara langsung. Itu pasti tidak indah sama sekali dan bukan cara yang dimaksudkan untuk bekerja dengan plugin rollup.

Pendekatan lain mungkin dengan menjalankan hanya transpileModule di transform berdasarkan per-file dalam menjalankan pertama untuk membiarkan rollup mengumpulkan semua impor, biarkan plugin vue transform tunggal file komponen dan cache kode TypeScript yang diekstraksi. Kemudian sebelum rollup selesai, buang kode transpiled dan lakukan kompilasi TypeScript yang tepat pada kode yang kita cache di pengait plugin renderChunk atau generateBundle . Ini mungkin mengganggu plugin lain yang menerapkan transformasi tambahan pada kode yang akan kita buang.

Untuk saat ini saya belum melihat solusi yang lebih indah.

Sunting: Setelah dipikir-pikir, pendekatan kedua mungkin tidak _itu_ jelek. Alih-alih kait renderChunk atau generateBundle , plugin dapat mendeteksi dirinya sendiri ketika impor terakhir sedang diimpor dan pada saat itu memulai kompilasi dari awal dan menambahkan file yang dikompilasi ke antrian rollup sedemikian rupa sehingga sebenarnya dapat diproses oleh semua plugin lain juga. File yang dihasilkan sebelumnya masih perlu dibuang untuk menghindari file tersebut berakhir di bundel terakhir.
Namun, pendekatan ini membuang waktu pemrosesan karena memungkinkan plugin lain juga pada file yang akan kita buang.

@danimoh @eddow Solusi untuk kedua contoh repo adalah menonaktifkan pemeriksaan kesalahan dengan // @ts-ignore tepat di atas impor yang melanggar.

Kesalahan pada dasarnya adalah TypeScript yang mengeluh bahwa ia tidak tahu apa jenis *.vue stuff itu ( Cannot find module berarti jenis modul). Setelah itu dibungkam, semuanya tampak dikompilasi dengan benar. Kelemahannya adalah hal-hal yang diimpor dari file vue memiliki tipe any dan tidak membantu dengan pemeriksaan kesalahan.

(dalam repo minimal, komponen pertama memerlukan referensi ke yang kedua, jika tidak, gulung treeshake menjauh dari bundel)

@danimoh ya, tidak ada cara untuk mendapatkan sumber modul dari rollup melalui konteks. Sebagian besar dapat dilakukan di sisi plugin vue (saya membuka kasus di sana), tetapi masih ada potensi jebakan, seperti rpt2 perlu mengubah skrip yang diekstraksi sebelum mengubah skrip yang mengimpornya.

Saya pikir pendekatan yang Anda jelaskan di utas masalah vue memerlukan TypeScript untuk memproses file satu per satu karena pada dasarnya mengabaikan impor file vue dan menunggu rollup untuk memasukkannya kembali ke TypeScript. Oleh karena itu Anda akan kehilangan pengecekan tipe di seluruh file.

Sebagai alternatif untuk membiarkan plugin vue menangani ts, berikut ini mungkin pendekatan yang valid dan semacam iterasi yang lebih baik dari peretasan jelek yang saya usulkan sebelumnya:

  • Apakah instance plugin vue diekspos melalui hook options ?
    Dengan begitu kita bisa memanggil metode transform pada plugin vue.
  • Dari https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API tampak bagi saya bahwa ts CompilerHost dan LanguageServiceHost dapat diberi makan kustom fileExists , readFile , getScriptSnapshot dan sejenisnya.
  • Jika keduanya berfungsi, kita dapat membiarkan TypeScript mengurai kode yang kita dapatkan dari plugin vue ke AST dan mengumpulkan impor dari AST itu dan memintanya dari plugin vue jika itu adalah file .vue . Untuk semua file vue, kami men-cache kode TypeScript yang diekstraksi dan menimpa metode seperti readFile untuk mengembalikan kode ts yang di-cache untuk impor vue .

Sunting: Sebenarnya, jika kita dapat menimpa fileExists dan readFile , kita tidak perlu mengumpulkan impor sendiri dengan melintasi AST karena TypeScript hanya akan memanggil metode ini untuk semua impor yang ingin diimpor lagi pula. Kami kemudian hanya perlu memanggil plugin vue sesuai permintaan.

Contoh plugin Vue mungkin terbuka, saya tidak tahu apakah rollup mengharapkan plugin untuk memanggil satu sama lain dan jika ada sesuatu yang rusak (segera atau di masa depan) dalam kasus itu.

Poin kedua Anda akan berhasil, itulah gunanya LanguageServiceHost .

Pendekatan ini mungkin berhasil, kelemahan utama adalah kopling yang berpotensi rapuh dengan plugin vue dan siklus ekstra untuk pekerjaan sekali pakai.

Saya berharap rollup memiliki cara bagi plugin untuk membatalkan transformasi dan mendeklarasikan ketergantungan untuk diubah sebelum file saat ini dicoba ulang, maka ini dapat diimplementasikan dengan bersih ...

Saya pikir sebenarnya tidak ada pekerjaan yang bisa dibuang begitu saja. TypeScript hanya akan mengkompilasi kode sekali dan juga plugin vue perlu memproses setiap file hanya sekali jika kita men-cache kode ts yang diekstrak. Pendekatan ini tidak membuang hasil itu sendiri atau hasil dari plugin lain selain saran saya sebelumnya.

Ya, beberapa perubahan arsitektur akan diperlukan dalam rollup. Mungkin seseorang dapat membuka masalah di sana untuk mengimplementasikan sesuatu seperti ini tetapi mungkin akan memakan waktu lama.
Juga saya tidak yakin apakah itu membuat segalanya menjadi jauh lebih baik. Kami masih harus memastikan bahwa TypeScript mengkompilasi semuanya sekaligus untuk melakukan pengecekan tipe di semua file. Kalau tidak, kita mungkin juga mengalami ini .

Ini berfungsi untuk saya dengan pengaturan ini, untuk mengkompilasi satu komponen vue:

import VuePlugin from 'rollup-plugin-vue'
import typescript from 'rollup-plugin-typescript2'

export default {
  plugins: [
    typescript({
      typescript: require('typescript'),
      objectHashIgnoreUnknownHack: true,
    }),
    VuePlugin(/* VuePluginOptions */),
  ],
  input: 'src/components/HelloWorld.vue',
  output: [
    { file: 'dist/HelloWorld.cjs.js', format: 'cjs' },
    { file: 'dist/HelloWorld.esm.js', format: 'esm' },
  ],
}

Saya tidak yakin apakah ini cara terbaik untuk membuat modul dari Vue SFC dengan lang="ts".

Jika ada yang punya saran, tolong beri tahu saya.

Ini berfungsi untuk saya dengan pengaturan ini, untuk mengkompilasi satu komponen vue:

Benar, tapi itu bukan kasus penggunaan yang sebenarnya. Itu halo dunia. Bagi siapa pun yang kesulitan memahami masalahnya, inilah yang saya kumpulkan.

rollup benar-benar tidak bisa melakukan ini

Mengapa? ini contohnya:

<script lang="ts">
import Bar from './Bar.vue';
...
</script>

1) plugin vue meneruskan skrip ke plugin TypeScript
2) plugin TypeScript menemukan file .vue , tetapi tidak tahu apa yang harus dilakukan dengannya karena rollup tidak menyediakan mekanisme bagi plugin untuk menunda plugin lain pada impor seperti webpack. JS biasa dapat menunda plugin, tetapi kode yang sudah diproses oleh plugin tidak bisa.
3) Saya sebenarnya tidak mengerti mengapa ini berbeda dari lang=scss atau lang=ts , tapi saya rasa.

Nah, apa yang bisa saya lakukan?

Tidak banyak.

Tapi vuetifikasi! gemuk!

Vuetify adalah TypeScript, tetapi tidak menggunakan SFC. Ini adalah fungsi render murni.

Buefy menggunakan SFC dan rollup, tetapi tidak ada TypeScript.

Sungguh, tidak ada yang bisa kulakukan?

Anda tidak akan menyukainya. Untuk setiap file Vue yang perlu Anda impor dari file TypeScript, Anda harus membuat perantara file javascript biasa.

import Bar from './Bar.vue';

export default Bar;

Kemudian dan baru setelah itu Anda dapat membangun lib komponen SFC TypeScript Anda dengan rollup.

astaga, itu menyebalkan

Jika Anda menemukan solusi yang lebih baik, saya akan senang mendengarnya.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat