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).
¿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í:
LanguageService.getEmitOutput
mecanografiadoLanguageHost.resolveModuleNames
y espera que las rutas resueltas se devuelvan en esa funciónPluginContext.resolveId
del paquete acumulativo de llamadas del anfitriónLanguageService
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.
Algo relacionado: https://github.com/rollup/rollup/issues/2631
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:
options
?transform
en el complemento vue.CompilerHost
y LanguageServiceHost
se pueden alimentar de forma personalizada fileExists
, readFile
, getScriptSnapshot
y similares..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".
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.
¿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.
Comentario más útil
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:
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
olang=ts
, pero supongo que lo es.No mucho.
Vuetify es mecanografiado, pero no usa SFC. Son funciones de renderizado puro.
Buefy usa SFC y rollup, pero no mecanografiado.
No te va a gustar. Para cada archivo Vue que necesite importar desde un archivo mecanografiado, deberá crear un intermediario de archivos javascript normal.
Entonces, y solo entonces, podrá construir su biblioteca de componentes SFC de mecanografiado con rollup.
Si ha encontrado una solución mejor, me encantaría escucharla.