Rollup-plugin-typescript2: Dateiimport anzeigen

Erstellt am 9. Jan. 2019  ·  14Kommentare  ·  Quelle: ezolenko/rollup-plugin-typescript2

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).

bug help wanted

Hilfreichster Kommentar

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.

Rollup kann das buchstäblich nicht tun

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.

Alle 14 Kommentare

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:

  • Rollup-Aufrufe des Plugins transform
  • Plugin ruft Typskripts LanguageService.getEmitOutput
  • Sprachdienst ruft die Plugin-Implementierung von LanguageHost.resolveModuleNames und erwartet, dass aufgelöste Pfade in dieser Funktion zurückgegeben werden
  • Host ruft Rollups PluginContext.resolveId
  • Rollup gibt ein Versprechen zurück
  • Wenn ich das richtig verstehe, kann ich mit einem Versprechen nur ein weiteres Versprechen geben

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.

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:

  • Wird die vue-Plugin-Instanz durch den options Hook verfügbar gemacht?
    Auf diese Weise könnten wir die Methode transform im vue-Plugin aufrufen.
  • Von https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API scheint es mir, dass die ts CompilerHost und LanguageServiceHost mit benutzerdefinierten fileExists gefüttert werden können readFile , getScriptSnapshot und dergleichen.
  • Wenn beides funktioniert, könnten wir den Code, den wir vom vue-Plugin erhalten, zu einem AST mit Typescript parsen lassen und die Importe von diesem AST sammeln und sie vom vue-Plugin anfordern, wenn es sich um .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.

Wenn jemand einen Rat hat, lass es mich wissen.

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.

Rollup kann das buchstäblich nicht tun

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.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen