Rollup-plugin-typescript2: Ver importación de archivos

Creado en 9 ene. 2019  ·  14Comentarios  ·  Fuente: ezolenko/rollup-plugin-typescript2

Al cambiar de rollup-plugin-typescript a rollup-plugin-typescript2 para producir archivos de declaración, los archivos *.vue ya no se reconocen.

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

Intentando simplemente importando rollup-plugin-typescript lugar de rollup-plugin-typescript2 paquetes sin ningún problema.

Esto podría estar vinculado a este problema, aunque tengo la última versión (de todos los complementos de hoy).

bug help wanted

Comentario más útil

Me funciona con esta configuración, para compilar un solo componente vue:

Correcto, pero ese no es un caso de uso real. Eso es hola mundo. Para cualquiera que tenga problemas para comprender el problema, esto es lo que he obtenido.

rollup literalmente no puede hacer esto

¿Por qué? aquí hay un ejemplo:

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

1) el complemento vue pasa el script al complemento mecanografiado
2) el complemento mecanografiado encuentra un archivo .vue , pero no tiene forma de saber qué hacer con él porque el resumen no proporciona un mecanismo para que los complementos difieran a otros complementos en importaciones como el paquete web. JS normal puede ceder a los complementos, pero el código que ya está siendo procesado por un complemento no puede.
3) En realidad, no entiendo por qué esto es diferente a lang=scss o lang=ts , pero supongo que lo es.

Bueno, que puedo hacer?

No mucho.

¡Pero vuetifica! buefy!

Vuetify es mecanografiado, pero no usa SFC. Son funciones de renderizado puro.

Buefy usa SFC y rollup, pero no mecanografiado.

Sin embargo, ¿no hay nada que pueda hacer?

No te va a gustar. Para cada archivo Vue que necesite importar desde un archivo mecanografiado, deberá crear un intermediario de archivos javascript normal.

import Bar from './Bar.vue';

export default Bar;

Entonces, y solo entonces, podrá construir su biblioteca de componentes SFC de mecanografiado con rollup.

Dios, eso apesta

Si ha encontrado una solución mejor, me encantaría escucharla.

Todos 14 comentarios

¿Podrías publicar tu configuración tsconfig y rollup?

O un pequeño repositorio con reproducción :)

Lamentablemente, no tengo un repositorio "pequeño". Estoy trabajando aquí , intentando migrar de webpack a rollup .

La importación en rollup.config.js se puede cambiar a rollup-plugin-typescript2 para ver la diferencia.

Hola.

En primer lugar, muchas gracias por trabajar en este complemento. De hecho, tiene mucho más sentido que rollup-plugin-typescript .

Puedo confirmar que existe este problema y configurar un pequeño repositorio de demostración:
https://github.com/danimoh/rollup-plugin-typescript2-vue-demo

Si comenta la línea import AnotherComponent from './AnotherComponent.vue'; se compila, pero desafortunadamente no con esta línea habilitada.

Es curioso que encontremos este problema al mismo tiempo. ¿Quizás fue causado por un cambio reciente?
Una suposición de mi parte con un conocimiento muy limitado sobre rollup, rollup plugins y mecanografiado sería:
¿Es posible que el mecanografiado esté intentando importar AnotherComponent lugar de un resumen o rollup-plugin-vue manejando esa importación primero?

Eso explicaría por qué rollup-plugin-typescript no tiene este problema, ya que se compila por archivo con transpileModule .

En este caso, lo siguiente puede ser interesante: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#customizing -module-resolution

Cualquier trabajo sobre este tema es muy apreciado.

Reproducido en ambos repositorios, no estoy seguro de si es el mismo problema todavía, pero es probable.

Para solucionar el segundo caso, de hecho, necesitamos enviar la resolución del módulo al paquete acumulativo para que el complemento vue pueda hacer su trabajo.

El problema de conectar la resolución del módulo del rollup y el mecanografiado es que el rollup en versiones posteriores devuelve una Promise de context.resolveId(...) . Entonces, la cadena de llamadas se ve así:

  • Transformación del complemento de llamadas acumuladas
  • el complemento llama a LanguageService.getEmitOutput mecanografiado
  • el servicio de idioma llama a la implementación del complemento de LanguageHost.resolveModuleNames y espera que las rutas resueltas se devuelvan en esa función
  • PluginContext.resolveId del paquete acumulativo de llamadas del anfitrión
  • rollup devuelve una promesa
  • si entiendo correctamente, todo lo que puedo hacer con una promesa es hacer otra promesa

LanguageService parece ser estrictamente sincrónico: https://github.com/Microsoft/TypeScript/issues/1857

Plugin.transform sí mismo puede devolver una Promesa, pero la mecánica de encadenar múltiples promesas hechas en el interior de las devoluciones de llamada en un objeto observador me elude en este momento.

Hola ezolenko.

Hoy en día, los métodos asincrónicos en Javascript significan principalmente métodos que devuelven promesas. La nueva sintaxis async / await es esencialmente azúcar sintáctica para métodos asincrónicos que permite al desarrollador escribir su código similar al código síncrono, los métodos async aún devuelven promesas. await embargo, async . Como notó, el método LanguageHost.resolveModuleNames no es asíncrono y, por lo tanto, no es posible regresar de ese método solo después de esperar una promesa en Javascript simple.

Sin embargo, en NodeJs, cosas como esta son realmente posibles al generar el método síncrono en el hilo actual, luego saltar al método asíncrono y volver al método síncrono cuando se resuelve el método asíncrono. Consulte Fibras o envoltorios a su alrededor, como sincronizar.js .

Por lo tanto, lo que pasa con la invocación del método asincrónico no es un gran problema en realidad. Sin embargo, podría haber otro problema. Si bien el contexto del complemento ofrece un método resolveId , eso no será suficiente. Necesitamos llamar al transform de rollup-plugin-vue para extraer el código mecanografiado de los componentes del archivo único vue. Desafortunadamente, el contexto del complemento no parece ofrecer esa funcionalidad.

Un enfoque para resolver esto podría ser agregar rollup-plugin-vue como dependencia a su proyecto y activar el transform en el complemento vue directamente. Eso seguramente no es hermoso en absoluto y no es la forma prevista de trabajar con complementos acumulativos.

Otro enfoque podría ser ejecutar solo transpileModule en transform por archivo en una primera ejecución para permitir que el resumen recopile todas las importaciones, deje que el complemento vue transform el único componentes del archivo y almacenar en caché el código mecanografiado extraído. Luego, antes de que finalice el resumen, descarte el código transpilado y haga una compilación de mecanografiado adecuada en el código que almacenamos en caché en un gancho de complemento renderChunk o generateBundle . Sin embargo, esto podría interferir con otros complementos que aplican transformaciones adicionales al código que descartaríamos.

Por ahora, todavía no veo una solución más hermosa.

Editar: Pensándolo bien, el segundo enfoque tal vez no sea _ tan_ feo. En lugar de renderChunk o generateBundle ganchos, el complemento podría detectar cuándo se está importando la última importación y, en ese momento, iniciar la compilación desde cero y agregar el archivo compilado a la cola de acumulación de manera que en realidad, también puede ser procesado por todos los demás complementos. Sin embargo, los archivos generados anteriormente aún deben descartarse para evitar que terminen en el paquete final.
Aún así, este enfoque desperdicia algo de tiempo de procesamiento, ya que permite que los otros complementos también estén en archivos que descartaríamos de todos modos.

@danimoh @eddow La solución alternativa para ambos // @ts-ignore justo encima de las importaciones ofensivas.

El error es básicamente mecanografiado quejándose de que no sabe qué tipo de cosas * .vue es ( Cannot find module significa tipo de módulo). Una vez que se silencia, todo parece compilarse correctamente. La desventaja es que las cosas importadas de archivos vue tienen el tipo any y no ayudan con la verificación de errores.

(en el repositorio mínimo, el primer componente necesita una referencia al segundo, de lo contrario, el rollup trees lo sacude del paquete)

@danimoh sí, no hay forma de obtener la fuente del módulo del resumen a través del contexto. La mayor parte se puede hacer en el lado del complemento de vue (abrí un caso allí), pero todavía hay problemas potenciales, como que rpt2 necesitará haber transformado el script extraído antes de transformar un script que lo importa.

Creo que el enfoque que describe en el hilo de problemas de vue requiere mecanografiado para procesar los archivos de uno en uno, ya que esencialmente ignora las importaciones de archivos vue y espera a que el resumen los devuelva al mecanografiado. Por lo tanto, perdería la verificación de tipos en los archivos.

Como alternativa a dejar que el complemento vue maneje ts, lo siguiente podría ser un enfoque válido y una especie de mejor iteración de los horribles trucos que propuse anteriormente:

  • ¿La instancia del complemento vue está expuesta a través del gancho options ?
    De esa forma podríamos llamar al método transform en el complemento vue.
  • De https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API me parece que los ts CompilerHost y LanguageServiceHost se pueden alimentar de forma personalizada fileExists , readFile , getScriptSnapshot y similares.
  • Si ambos funcionan, podríamos dejar que el mecanografiado analice el código que obtenemos del complemento vue en un AST y recopile las importaciones de ese AST y las solicite del complemento vue si son archivos .vue . Para todos los archivos vue, almacenamos en caché el código mecanografiado extraído y sobrescribimos métodos como readFile para devolver ese código ts almacenado en caché para una importación vue .

Editar: En realidad, si podemos sobrescribir fileExists y readFile , no tendríamos que recopilar las importaciones nosotros mismos atravesando el AST, ya que el mecanografiado solo llamará a estos métodos para todas las importaciones que desee importar. de todos modos. Entonces solo necesitamos llamar al complemento vue a pedido.

La instancia del complemento Vue probablemente esté expuesta, no sé si el paquete acumulativo espera que los complementos se llamen entre sí y si algo se romperá (inmediatamente o en el futuro) en ese caso.

Su segundo punto funcionará, eso es exactamente para lo que es LanguageServiceHost .

Este enfoque podría funcionar, el principal inconveniente es el acoplamiento potencialmente frágil con el complemento vue y ciclos adicionales para el trabajo desechable.

Desearía que el resumen tuviera una forma de que los complementos abortaran la transformación y declararan que una dependencia se transformará antes de que se vuelva a intentar el archivo actual, entonces esto podría implementarse limpiamente ...

Creo que en realidad no hay trabajo de usar y tirar. TypeScript solo compilará el código una vez y también el complemento vue necesitará procesar cada archivo solo una vez si almacenamos en caché el código ts extraído. Este enfoque no descarta ninguno de sus propios resultados o resultados de otros complementos que no sean mi sugerencia anterior.

Sí, se requeriría algún cambio arquitectónico en el resumen. Tal vez uno podría abrir un problema allí para implementar algo como esto, pero probablemente tomaría años.
Además, no estoy seguro de si mejora mucho las cosas. Todavía tenemos que asegurarnos de que mecanografiado compile todo a la vez para realizar la verificación de tipos en todos los archivos. De lo contrario, también podríamos encontrarnos con esto .

Me funciona con esta configuración, para compilar un solo componente 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' },
  ],
}

No estoy seguro de si esta es la mejor manera de crear un módulo a partir de un Vue SFC con lang = "ts".

Si alguien tiene algún consejo por favor dejenme saber.

Me funciona con esta configuración, para compilar un solo componente vue:

Correcto, pero ese no es un caso de uso real. Eso es hola mundo. Para cualquiera que tenga problemas para comprender el problema, esto es lo que he obtenido.

rollup literalmente no puede hacer esto

¿Por qué? aquí hay un ejemplo:

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

1) el complemento vue pasa el script al complemento mecanografiado
2) el complemento mecanografiado encuentra un archivo .vue , pero no tiene forma de saber qué hacer con él porque el resumen no proporciona un mecanismo para que los complementos difieran a otros complementos en importaciones como el paquete web. JS normal puede ceder a los complementos, pero el código que ya está siendo procesado por un complemento no puede.
3) En realidad, no entiendo por qué esto es diferente a lang=scss o lang=ts , pero supongo que lo es.

Bueno, que puedo hacer?

No mucho.

¡Pero vuetifica! buefy!

Vuetify es mecanografiado, pero no usa SFC. Son funciones de renderizado puro.

Buefy usa SFC y rollup, pero no mecanografiado.

Sin embargo, ¿no hay nada que pueda hacer?

No te va a gustar. Para cada archivo Vue que necesite importar desde un archivo mecanografiado, deberá crear un intermediario de archivos javascript normal.

import Bar from './Bar.vue';

export default Bar;

Entonces, y solo entonces, podrá construir su biblioteca de componentes SFC de mecanografiado con rollup.

Dios, eso apesta

Si ha encontrado una solución mejor, me encantaría escucharla.

¿Fue útil esta página
0 / 5 - 0 calificaciones