Beim Umschalten von rollup-plugin-typescript
auf rollup-plugin-typescript2
um Deklarationsdateien zu erzeugen, werden die *.vue
Dateien nicht mehr erkannt.
[!] (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'.
Versuchen Sie es einfach, indem Sie rollup-plugin-typescript
anstelle von rollup-plugin-typescript2
Paketen problemlos importieren.
Dies könnte mit diesem Problem zusammenhängen, obwohl ich die letzte Version habe (in der Tat von jedem Plugin heute).
Könntest du deine tsconfig und rollup config posten?
Oder ein kleines Repo mit Reproduktion :)
Ich habe leider kein "kleines" Repo. Ich arbeite hier und versuche, von webpack
zu rollup
zu migrieren.
Der Import in rollup.config.js
kann in rollup-plugin-typescript2
geändert werden, um den Unterschied zu sehen.
Hallo.
Zunächst einmal vielen Dank für die Arbeit an diesem Plugin. Es macht in der Tat viel mehr Sinn als rollup-plugin-typescript
.
Ich kann bestätigen, dass dieses Problem besteht und ein kleines Demo-Repository einrichten:
https://github.com/danimoh/rollup-plugin-typescript2-vue-demo
Wenn Sie die Zeile import AnotherComponent from './AnotherComponent.vue';
auskommentieren, wird kompiliert, aber leider nicht mit dieser Zeile aktiviert.
Es ist komisch, dass wir ungefähr zur gleichen Zeit auf dieses Problem gestoßen sind. Vielleicht liegt es an einer kürzlichen Änderung?
Eine Vermutung von meiner Seite mit sehr begrenzten Kenntnissen über Rollup, Rollup-Plugins und Typoskript wäre:
Ist es möglich, dass Typoskript selbst versucht, AnotherComponent
anstelle von Rollup zu importieren oder rollup-plugin-vue
diesen Import zuerst verarbeitet?
Das würde erklären, warum rollup-plugin-typescript
dieses Problem nicht hat, da es pro Datei mit transpileModule
kompiliert wird.
In diesem Fall könnte Folgendes interessant sein: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#customizing -module-resolution
Jede Arbeit zu diesem Thema wird sehr geschätzt.
Auf beiden Repos reproduziert, nicht sicher, ob es sich noch um das gleiche Problem handelt, aber es ist wahrscheinlich.
Um den zweiten Fall zu beheben, müssen wir in der Tat die Modulauflösung an das Rollup zurücksenden, damit das vue-Plugin seine Aufgabe erfüllen kann.
Das Problem beim Verbinden der Modulauflösung und des Typoskripts von Rollup besteht darin, dass Rollup in späteren Versionen ein Promise von context.resolveId(...)
zurückgibt. Die Anrufkette sieht also so aus:
LanguageService.getEmitOutput
LanguageHost.resolveModuleNames
und erwartet, dass aufgelöste Pfade in dieser Funktion zurückgegeben werdenPluginContext.resolveId
LanguageService
scheint streng synchron zu sein: https://github.com/Microsoft/TypeScript/issues/1857
Plugin.transform
kann selbst ein Versprechen zurückgeben, aber die Mechanismen der Verkettung mehrerer Versprechen, die tief in Callbacks auf einem Beobachterobjekt gemacht werden, entgehen mir im Moment.
Etwas verwandt: https://github.com/rollup/rollup/issues/2631
Hallo ezolenko.
Heutzutage bedeuten asynchrone Methoden in Javascript meist Methoden, die Promises zurückgeben. Die neue async
/ await
Syntax ist im Wesentlichen nur syntaktischer Zucker für asynchrone Methoden, der es dem Entwickler ermöglicht, seinen Code ähnlich wie synchronen Code zu schreiben, async
Methoden geben immer noch Versprechen zurück. await
kann jedoch nur in async
Methoden verwendet werden. Wie Sie bemerkt haben, ist die Methode LanguageHost.resolveModuleNames
nicht asynchron und daher ist es nicht möglich, von dieser Methode nur nach dem Warten auf eine Zusage in einfachem Javascript zurückzukehren.
In NodeJs sind solche Dinge jedoch tatsächlich möglich, indem die synchrone Methode im aktuellen Thread zurückgegeben wird, dann zur asynchronen Methode gesprungen und dann zur synchronen Methode zurückgesprungen wird, wenn die asynchrone Methode aufgelöst wird. Siehe Fasern oder Wrapper um es wie synchronize.js .
Daher ist die Sache mit dem asynchronen Methodenaufruf eigentlich kein großes Problem. Es könnte jedoch ein anderes Problem geben. Der Plugin-Kontext bietet zwar eine Methode resolveId
, aber das wird nicht ausreichen. Wir müssen transform
von rollup-plugin-vue
aufrufen, um den Typoskriptcode aus den einzelnen Dateikomponenten von vue zu extrahieren. Der Plugin-Kontext scheint diese Funktionalität jedoch leider nicht zu bieten.
Ein Ansatz zur Lösung dieses Problems könnte darin bestehen, rollup-plugin-vue
als Abhängigkeit zu Ihrem Projekt hinzuzufügen und die transform
direkt im Vue-Plugin auszulösen. Das ist sicher nicht schön und nicht die beabsichtigte Art, mit Rollup-Plugins zu arbeiten.
Ein anderer Ansatz könnte darin bestehen, in einem ersten Durchlauf nur transpileModule
in transform
pro Datei auszuführen, damit Rollup alle Importe sammeln kann, und das Vue-Plugin transform
die Single lassen Dateikomponenten und den extrahierten Typescript-Code zwischenspeichern. Bevor das Rollup abgeschlossen ist, verwerfen Sie den transpilierten Code und führen Sie eine korrekte Typoskript-Kompilierung des Codes durch, den wir in einem renderChunk
oder generateBundle
Plugin-Hook zwischengespeichert haben. Dies kann jedoch andere Plugins stören, die zusätzliche Transformationen auf den Code anwenden, die wir verwerfen würden.
Im Moment sehe ich noch keine schönere Lösung.
Bearbeiten: Beim zweiten Nachdenken ist der zweite Ansatz vielleicht nicht _das_ hässlich. Anstelle von renderChunk
oder generateBundle
Hooks könnte das Plugin sich selbst erkennen, wenn der letzte Import importiert wird, und an diesem Punkt die Kompilierung von Grund auf neu starten und die kompilierte Datei so zur Rollup-Warteschlange hinzufügen, dass sie kann eigentlich auch von allen anderen Plugins verarbeitet werden. Die zuvor generierten Dateien müssen jedoch noch verworfen werden, damit sie nicht im endgültigen Bundle landen.
Trotzdem verschwendet dieser Ansatz einige Verarbeitungszeit, da die anderen Plugins auch auf Dateien zugreifen können, die wir sowieso verwerfen würden.
@danimoh @eddow Workaround für beide Beispiel-Repos deaktiviert die Fehlerprüfung mit // @ts-ignore
direkt über den beleidigenden Importen.
Der Fehler ist im Grunde ein Typoskript, das sich beschwert, dass es nicht weiß, welcher Typ *.vue-Zeug ist ( Cannot find module
bedeutet Modultyp). Sobald das stumm geschaltet ist, scheint alles richtig zu kompilieren. Der Nachteil ist, dass Dinge, die aus vue-Dateien importiert werden, den Typ any
und nicht bei der Fehlerprüfung helfen.
(im minimalen Repo benötigt die erste Komponente eine Referenz auf die zweite, ansonsten schüttelt Rollup Trees sie vom Bundle weg)
@danimoh ja, keine Möglichkeit, die Modulquelle aus dem Rollup über den Kontext abzurufen. Das meiste davon kann auf der Seite des Vue-Plugins durchgeführt werden (ich habe dort einen Fall geöffnet), aber es gibt immer noch potenzielle Fallstricke, wie z. B. rpt2 muss das extrahierte Skript transformiert haben, bevor es ein Skript transformiert, das es importiert.
Ich denke, der Ansatz, den Sie im vue-Problemthread beschreiben, erfordert, dass Typoskript die Dateien einzeln verarbeitet, da es die vue-Dateiimporte im Wesentlichen ignoriert und auf das Rollup wartet, um sie an Typoskript zurückzugeben. Daher würden Sie die Typüberprüfung über Dateien hinweg verlieren.
Als Alternative dazu, das vue-Plugin ts verarbeiten zu lassen, könnte Folgendes ein gültiger Ansatz und eine Art bessere Iteration der hässlichen Hacks sein, die ich zuvor vorgeschlagen habe:
options
Hook verfügbar gemacht?transform
im vue-Plugin aufrufen.CompilerHost
und LanguageServiceHost
mit benutzerdefinierten fileExists
gefüttert werden können readFile
, getScriptSnapshot
und dergleichen..vue
Dateien handelt. Für alle vue-Dateien cachen wir den extrahierten Typescript-Code und überschreiben Methoden wie readFile
, um diesen zwischengespeicherten ts-Code für einen vue
Import zurückzugeben.Bearbeiten: Wenn wir fileExists
und readFile
überschreiben können, müssten wir die Importe nicht selbst sammeln, indem wir den AST durchlaufen, da das Typskript diese Methoden nur für alle Importe aufruft, die importiert werden sollen Sowieso. Wir müssen dann nur noch das vue-Plugin bei Bedarf aufrufen.
Die Vue-Plugin-Instanz ist wahrscheinlich exponiert, ich weiß nicht, ob Rollup erwartet, dass sich Plugins gegenseitig aufrufen und ob in diesem Fall etwas (sofort oder in Zukunft) kaputt geht.
Ihr zweiter Punkt wird funktionieren, genau dafür ist LanguageServiceHost
.
Dieser Ansatz könnte funktionieren, wobei der Hauptnachteil die potenziell fragile Kopplung mit dem Vue-Plugin und zusätzlichen Zyklen für Wegwerfarbeiten ist.
Ich wünschte, Rollup hätte eine Möglichkeit für Plugins, die Transformation abzubrechen und eine zu transformierende Abhängigkeit zu deklarieren, bevor die aktuelle Datei erneut versucht wird, dann könnte dies sauber implementiert werden ...
Ich denke, es gibt eigentlich keine Wegwerfarbeit. Typescript kompiliert den Code nur einmal und auch das Vue-Plugin muss jede Datei nur einmal verarbeiten, wenn wir den extrahierten ts-Code zwischenspeichern. Dieser Ansatz verwirft keine seiner eigenen Ergebnisse oder Ergebnisse anderer Plugins außer meinem vorherigen Vorschlag.
Ja, beim Rollup wären einige Architekturänderungen erforderlich. Vielleicht könnte man dort ein Thema eröffnen, um so etwas zu implementieren, aber es würde wahrscheinlich ewig dauern.
Ich bin mir auch nicht sicher, ob es die Dinge wirklich viel besser macht. Wir müssen immer noch sicherstellen, dass typescript das Ganze auf einmal kompiliert, um die Typprüfung für alle Dateien durchzuführen. Sonst könnten wir auch den Weg laufen diese .
Bei mir funktioniert es mit diesem Setup, um eine einzelne vue-Komponente zu kompilieren:
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' },
],
}
Ich bin mir nicht sicher, ob dies der beste Weg ist, um ein Modul aus einem Vue-SFC mit lang="ts" zu erstellen.
Bei mir funktioniert es mit diesem Setup, um eine einzelne vue-Komponente zu kompilieren:
Richtig, aber das ist kein echter Anwendungsfall. Das ist hallo Welt. Für alle, die Probleme haben, das Problem zu verstehen, habe ich Folgendes herausgefunden.
Warum? hier ist ein beispiel:
<script lang="ts">
import Bar from './Bar.vue';
...
</script>
1) Das Vue-Plugin übergibt das Skript an das Typoskript-Plugin
2) typescript-Plugin trifft auf eine .vue
Datei, kann aber nicht wissen, was damit zu tun ist, da das Rollup keinen Mechanismus für Plugins bietet, um Importe wie Webpack auf andere Plugins zu verschieben. Reguläres JS kann sich auf Plugins verschieben, Code, der bereits von einem Plugin verarbeitet wird, jedoch nicht.
3) Ich verstehe eigentlich nicht, warum das anders ist als lang=scss
oder lang=ts
, aber ich denke, es ist so.
Nun, was kann ich tun?
Nicht viel.
Aber vuetify! buefy!
Vuetify ist Typoskript, verwendet aber keine SFCs. Es sind reine Renderfunktionen.
Buefy verwendet SFCs und Rollup, aber kein Typoskript.
Wirklich, ich kann nichts tun?
Es wird dir nicht gefallen. Für jede Vue-Datei, die Sie aus einer Typescript-Datei importieren müssen, müssen Sie einen regulären Javascript-Datei-Vermittler erstellen.
import Bar from './Bar.vue';
export default Bar;
Dann und nur dann können Sie Ihre Typoskript-SFC-Komponentenbibliothek mit Rollup erstellen.
meine Güte, das ist scheiße
Wenn Sie eine bessere Lösung haben, würde ich mich freuen, sie zu hören.
Hilfreichster Kommentar
Richtig, aber das ist kein echter Anwendungsfall. Das ist hallo Welt. Für alle, die Probleme haben, das Problem zu verstehen, habe ich Folgendes herausgefunden.
Rollup kann das buchstäblich nicht tun
Warum? hier ist ein beispiel:
1) Das Vue-Plugin übergibt das Skript an das Typoskript-Plugin
2) typescript-Plugin trifft auf eine
.vue
Datei, kann aber nicht wissen, was damit zu tun ist, da das Rollup keinen Mechanismus für Plugins bietet, um Importe wie Webpack auf andere Plugins zu verschieben. Reguläres JS kann sich auf Plugins verschieben, Code, der bereits von einem Plugin verarbeitet wird, jedoch nicht.3) Ich verstehe eigentlich nicht, warum das anders ist als
lang=scss
oderlang=ts
, aber ich denke, es ist so.Nicht viel.
Vuetify ist Typoskript, verwendet aber keine SFCs. Es sind reine Renderfunktionen.
Buefy verwendet SFCs und Rollup, aber kein Typoskript.
Es wird dir nicht gefallen. Für jede Vue-Datei, die Sie aus einer Typescript-Datei importieren müssen, müssen Sie einen regulären Javascript-Datei-Vermittler erstellen.
Dann und nur dann können Sie Ihre Typoskript-SFC-Komponentenbibliothek mit Rollup erstellen.
Wenn Sie eine bessere Lösung haben, würde ich mich freuen, sie zu hören.