Rollup-plugin-typescript2: Vue file import

Créé le 9 janv. 2019  ·  14Commentaires  ·  Source: ezolenko/rollup-plugin-typescript2

En passant de rollup-plugin-typescript à rollup-plugin-typescript2 afin de produire des fichiers de déclaration, les fichiers *.vue ne sont plus reconnus.

[!] (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'.

Essayer en important simplement rollup-plugin-typescript au lieu de rollup-plugin-typescript2 bundles sans problème.

Cela pourrait être lié à ce problème même si j'ai la dernière version (de chaque plugin aujourd'hui en effet).

bug help wanted

Commentaire le plus utile

Cela fonctionne pour moi avec cette configuration, pour compiler un seul composant vue :

D'accord, mais ce n'est pas un cas d'utilisation réel. C'est bonjour le monde. Pour ceux qui ont du mal à comprendre le problème, voici ce que j'ai glané.

rollup ne peut littéralement pas faire cela

Pourquoi? voici un exemple :

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

1) le plugin vue passe le script au plugin tapuscrit
2) le plugin typescript rencontre un fichier .vue , mais n'a aucun moyen de savoir quoi en faire car le rollup ne fournit pas de mécanisme permettant aux plugins de s'en remettre à d'autres plugins lors des importations comme webpack. JS standard peut s'en remettre aux plugins, mais pas le code déjà traité par un plugin.
3) En fait, je ne comprends pas pourquoi c'est différent de lang=scss ou lang=ts , mais je suppose que c'est le cas.

Eh bien, que puis-je faire?

Pas beaucoup.

Mais vuetify ! bonjour !

Vuetify est dactylographié, mais n'utilise pas de SFC. Ce sont des fonctions de rendu pures.

Buefy utilise les SFC et le rollup, mais pas de script dactylographié.

Vraiment, il n'y a rien que je puisse faire ?

Vous n'allez pas aimer ça. Pour chaque fichier Vue que vous devez importer à partir d'un fichier dactylographié, vous devrez créer un intermédiaire de fichier javascript régulier.

import Bar from './Bar.vue';

export default Bar;

Alors et seulement alors, vous pourrez créer votre bibliothèque de composants SFC dactylographiés avec rollup.

bon sang, c'est nul

Si vous avez trouvé une meilleure solution, je serais ravi de l'entendre.

Tous les 14 commentaires

Pourriez-vous poster votre configuration tsconfig et rollup ?

Ou un petit repo avec reproduction :)

Je n'ai malheureusement pas de "petit" repo. Je travaille ici , j'essaie de migrer de webpack vers rollup .

L'importation dans rollup.config.js peut être changée en rollup-plugin-typescript2 pour voir la différence.

Salut.

Tout d'abord merci beaucoup d'avoir travaillé sur ce plugin. Cela a en effet beaucoup plus de sens que rollup-plugin-typescript .

Je peux confirmer que ce problème existe et configurer un petit référentiel de démonstration :
https://github.com/danimoh/rollup-plugin-typescript2-vue-demo

Si vous commentez la ligne import AnotherComponent from './AnotherComponent.vue'; cela se compile, mais malheureusement pas avec cette ligne activée.

C'est drôle que nous ayons rencontré ce problème à peu près au même moment. Peut-être est-ce dû à un changement récent ?
Une supposition de mon côté avec des connaissances très limitées sur le rollup, les plugins rollup et le dactylographe serait :
Est-il possible que le script lui-même essaie d'importer AnotherComponent au lieu de rollup ou que rollup-plugin-vue gère cette importation en premier ?

Cela expliquerait pourquoi rollup-plugin-typescript n'a pas ce problème car il compile fichier par fichier avec transpileModule .

Dans ce cas, ce qui suit peut être intéressant : https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#customizing -module-resolution

Tout travail sur cette question est très apprécié.

Reproduit sur les deux dépôts, je ne sais pas encore si c'est le même problème, mais c'est probable.

Pour résoudre le deuxième cas, nous devons en effet renvoyer la résolution du module au rollup afin que le plugin vue puisse faire son travail.

Le problème avec le raccordement de la résolution du module et du script dactylographié du rollup est que le rollup dans les versions ultérieures renvoie une promesse de context.resolveId(...) . La chaîne d'appel ressemble donc à ceci :

  • la transformation du plug-in d'appels de cumul
  • le plugin appelle les LanguageService.getEmitOutput
  • le service de langue appelle l'implémentation du plugin de LanguageHost.resolveModuleNames et s'attend à ce que les chemins résolus soient renvoyés dans cette fonction
  • le cumul des appels d'hôte PluginContext.resolveId
  • le cumul renvoie une promesse
  • si je comprends bien, tout ce que je peux faire avec une promesse c'est faire une autre promesse

LanguageService semble être strictement synchrone : https://github.com/Microsoft/TypeScript/issues/1857

Plugin.transform peut lui-même renvoyer une promesse, mais la mécanique de l'enchaînement de plusieurs promesses faites au fond des rappels sur un objet observateur m'échappe pour le moment.

Bonjour ezolenko.

De nos jours, les méthodes asynchrones en Javascript signifient principalement des méthodes renvoyant des promesses. La nouvelle syntaxe async / await est essentiellement du sucre syntaxique pour les méthodes asynchrones qui permet au développeur d'écrire son code similaire au code synchrone, les méthodes async retournent toujours des promesses. Cependant, await ne peut être utilisé que dans les méthodes async . Comme vous l'avez remarqué, la méthode LanguageHost.resolveModuleNames n'est pas asynchrone et il n'est donc pas possible de revenir de cette méthode uniquement après avoir attendu une promesse en Javascript simple.

Cependant, dans NodeJs, des choses comme celle-ci sont en fait possibles en produisant la méthode synchrone sur le thread actuel, puis en passant à la méthode asynchrone et en revenant à la méthode synchrone lorsque la méthode asynchrones est résolue. Voir Fibres ou wrappers autour comme synchroniser.js .

Ainsi, le problème avec l'invocation de la méthode async n'est pas vraiment un problème. Il pourrait y avoir un autre problème cependant. Alors que le contexte du plugin propose une méthode resolveId , cela ne suffira pas. Nous devons appeler le transform de rollup-plugin-vue pour extraire le code tapuscrit des composants de fichier unique de vue. Le contexte du plugin ne semble malheureusement pas offrir cette fonctionnalité.

Une approche pour résoudre ce problème pourrait être d'ajouter rollup-plugin-vue tant que dépendance à votre projet et de déclencher directement le transform sur le plugin vue. Ce n'est certainement pas beau du tout et ce n'est pas la manière prévue de travailler avec les plugins de cumul.

Une autre approche pourrait consister à exécuter uniquement transpileModule dans transform sur une base par fichier dans une première exécution pour permettre au rollup de collecter toutes les importations, laissez le plugin vue transform le single composants du fichier et mettre en cache le code dactylographié extrait. Ensuite, avant la fin du cumul, supprimez le code transpilé et effectuez une compilation dactylographiée appropriée sur le code que nous avons mis en cache dans un crochet de plugin renderChunk ou generateBundle . Cela pourrait interférer avec d'autres plugins qui appliquent des transformations supplémentaires au code que nous supprimerions.

Pour l'instant je ne vois pas encore de plus belle solution.

Edit : À la réflexion, la deuxième approche n'est peut-être pas _that_ laid. Au lieu de crochets renderChunk ou generateBundle , le plugin pourrait se détecter lorsque la dernière importation est importée et à ce stade démarrer la compilation à partir de zéro et ajouter le fichier compilé à la file d'attente de cumul de telle sorte qu'il peut en fait être traité par tous les autres plugins également. Les fichiers générés précédemment doivent toujours être supprimés pour éviter qu'ils ne se retrouvent dans le paquet final.
Pourtant, cette approche fait perdre du temps de traitement car elle laisse les autres plugins également sur des fichiers que nous écarterions de toute façon.

@danimoh @eddow La solution de contournement pour les deux exemples de dépôts désactive la vérification des erreurs avec // @ts-ignore juste au-dessus des importations incriminées.

L'erreur est essentiellement un script dactylographié se plaignant qu'il ne sait pas de quel type *.vue est le truc ( Cannot find module signifie le type de module). Une fois que cela est réduit au silence, tout semble se compiler correctement. L'inconvénient est que les éléments importés à partir des fichiers vue ont le type any et n'aident pas à la vérification des erreurs.

(dans le référentiel minimal, le premier composant a besoin d'une référence au second, sinon l'arbre de cumul l'éloigne du bundle)

@danimoh oui , aucun moyen d'obtenir la source du module à partir du cumul via le contexte. La majeure partie peut être effectuée côté plugin vue (j'ai ouvert un dossier là-bas), mais il existe encore des pièges potentiels, comme rpt2 devra avoir transformé le script extrait avant de transformer un script qui l'importe.

Je pense que l'approche que vous décrivez dans le fil de discussion sur le problème de vue nécessite que le script dactylographié traite les fichiers un par un, car il ignore essentiellement les importations du fichier vue et attend que le rollup les renvoie au script dactylographié. Par conséquent, vous perdriez la vérification de type dans les fichiers.

Au lieu de laisser le plugin vue gérer ts, ce qui suit pourrait être une approche valide et une sorte de meilleure itération des vilaines hacks que j'ai proposés plus tôt :

  • L'instance du plugin vue est-elle exposée via le hook options ?
    De cette façon, nous pourrions appeler la méthode transform sur le plugin vue.
  • De https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API, il me semble que les ts CompilerHost et LanguageServiceHost peuvent être alimentés de manière personnalisée fileExists , readFile , getScriptSnapshot et autres.
  • Si les deux fonctionnent, nous pourrions laisser Typescript analyser le code que nous obtenons du plugin vue vers un AST et collecter les importations de cet AST et les demander au plugin vue s'il s'agit .vue fichiers readFile pour renvoyer ce code ts mis en cache pour une importation vue .

Edit: En fait, si nous pouvons écraser fileExists et readFile , nous n'aurions pas besoin de collecter les importations nous-mêmes en traversant l'AST car le script dactylographié va simplement appeler ces méthodes pour toutes les importations qu'il souhaite importer de toute façon. Il suffit ensuite d'appeler le plugin vue à la demande.

L'instance de plug-in Vue est probablement exposée, je ne sais pas si le rollup s'attend à ce que les plug-ins s'appellent et si quelque chose se brisera (immédiatement ou dans le futur) dans ce cas.

Votre deuxième point fonctionnera, c'est exactement à quoi sert LanguageServiceHost .

Cette approche pourrait fonctionner, le principal inconvénient étant un couplage potentiellement fragile avec le plugin vue et des cycles supplémentaires pour le travail jetable.

Je souhaite que le rollup ait un moyen pour les plugins d'abandonner la transformation et de déclarer une dépendance à transformer avant que le fichier actuel ne soit réessayé, alors cela pourrait être implémenté proprement ...

Je pense qu'il n'y a en fait pas de travail jetable. Typescript ne compilera le code qu'une seule fois et le plugin vue n'aura également besoin de traiter chaque fichier qu'une seule fois si nous mettons en cache le code ts extrait. Cette approche ne rejette aucun de ses propres résultats ou des résultats d'autres plugins autres que ma suggestion précédente.

Oui, un changement architectural serait nécessaire dans le cumul. On pourrait peut-être ouvrir un problème là-bas pour mettre en œuvre quelque chose comme ça, mais cela prendrait probablement des années.
De plus, je ne sais pas si cela améliore vraiment les choses. Nous devons toujours nous assurer que typescript compile le tout en même temps pour effectuer une vérification de type sur tous les fichiers. Sinon, nous pourrions également rencontrer cela .

Cela fonctionne pour moi avec cette configuration, pour compiler un seul composant 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' },
  ],
}

Je ne sais pas si c'est la meilleure façon de créer un module à partir d'un Vue SFC avec lang="ts".

Si quelqu'un a des conseils, merci de me le faire savoir.

Cela fonctionne pour moi avec cette configuration, pour compiler un seul composant vue :

D'accord, mais ce n'est pas un cas d'utilisation réel. C'est bonjour le monde. Pour ceux qui ont du mal à comprendre le problème, voici ce que j'ai glané.

rollup ne peut littéralement pas faire cela

Pourquoi? voici un exemple :

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

1) le plugin vue passe le script au plugin tapuscrit
2) le plugin typescript rencontre un fichier .vue , mais n'a aucun moyen de savoir quoi en faire car le rollup ne fournit pas de mécanisme permettant aux plugins de s'en remettre à d'autres plugins lors des importations comme webpack. JS standard peut s'en remettre aux plugins, mais pas le code déjà traité par un plugin.
3) En fait, je ne comprends pas pourquoi c'est différent de lang=scss ou lang=ts , mais je suppose que c'est le cas.

Eh bien, que puis-je faire?

Pas beaucoup.

Mais vuetify ! bonjour !

Vuetify est dactylographié, mais n'utilise pas de SFC. Ce sont des fonctions de rendu pures.

Buefy utilise les SFC et le rollup, mais pas de script dactylographié.

Vraiment, il n'y a rien que je puisse faire ?

Vous n'allez pas aimer ça. Pour chaque fichier Vue que vous devez importer à partir d'un fichier dactylographié, vous devrez créer un intermédiaire de fichier javascript régulier.

import Bar from './Bar.vue';

export default Bar;

Alors et seulement alors, vous pourrez créer votre bibliothèque de composants SFC dactylographiés avec rollup.

bon sang, c'est nul

Si vous avez trouvé une meilleure solution, je serais ravi de l'entendre.

Cette page vous a été utile?
0 / 5 - 0 notes