При переключении с rollup-plugin-typescript
на rollup-plugin-typescript2
для создания файлов декларации файлы *.vue
больше не распознаются.
[!] (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'.
Попытка просто импортировать rollup-plugin-typescript
вместо пакетов rollup-plugin-typescript2
без проблем.
Это может быть связано с этой проблемой, хотя у меня есть последняя версия (действительно, сегодня для каждого плагина).
Не могли бы вы опубликовать свою конфигурацию tsconfig и rollup?
Или небольшое репо с воспроизведением :)
У меня, к сожалению, нет "маленького" репо. Я работаю здесь , пытаюсь перейти с webpack
на rollup
.
Импорт в rollup.config.js
можно изменить на rollup-plugin-typescript2
чтобы увидеть разницу.
Привет.
Прежде всего, большое спасибо за работу над этим плагином. Это действительно имеет гораздо больше смысла, чем rollup-plugin-typescript
.
Я могу подтвердить, что эта проблема существует, и настроить небольшой демонстрационный репозиторий:
https://github.com/danimoh/rollup-plugin-typescript2-vue-demo
Если вы закомментируете строку import AnotherComponent from './AnotherComponent.vue';
она будет компилироваться, но, к сожалению, не с включенной этой строкой.
Забавно, что мы столкнулись с этой проблемой примерно в то же время. Может это было вызвано недавним изменением?
Предположение с моей стороны с очень ограниченными знаниями о накоплении, подключаемых модулях и машинописном тексте будет:
Возможно ли, что сам машинописный текст пытается импортировать AnotherComponent
вместо объединения или rollup-plugin-vue
обрабатывающего этот импорт первым?
Это объясняет, почему rollup-plugin-typescript
не имеет этой проблемы, поскольку он компилируется для каждого файла с помощью transpileModule
.
В этом случае может быть интересно следующее: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#customizing -module-resolution
Мы очень ценим любую работу по этому вопросу.
Воспроизводится в обоих репозиториях, не уверен, что это та же проблема, но вполне вероятно.
Чтобы исправить второй случай, нам действительно нужно отправить разрешение модуля обратно в накопительный пакет, чтобы плагин vue мог это сделать.
Проблема с подключением разрешения модуля свертки и машинописного текста заключается в том, что свертка в более поздних версиях возвращает обещание от context.resolveId(...)
. Итак, цепочка вызовов выглядит так:
LanguageService.getEmitOutput
машинописного текстаLanguageHost.resolveModuleNames
и ожидает, что в этой функции будут возвращены разрешенные путиPluginContext.resolveId
LanguageService
кажется строго синхронным: https://github.com/Microsoft/TypeScript/issues/1857
Plugin.transform
может сам возвращать Promise, но механика объединения нескольких обещаний, сделанных глубоко внутри обратных вызовов для объекта-наблюдателя, в данный момент ускользает от меня.
В некоторой степени связано: https://github.com/rollup/rollup/issues/2631
Привет, езоленко.
В настоящее время асинхронные методы в Javascript в основном означают методы, возвращающие обещания. Новый синтаксис async
/ await
по сути является просто синтаксическим сахаром для асинхронных методов, который позволяет разработчику писать свой код, аналогичный синхронному коду, методы async
прежнему возвращают обещания. await
можно использовать только в методах async
. Как вы заметили, метод LanguageHost.resolveModuleNames
не является асинхронным, и поэтому невозможно вернуться из этого метода только после ожидания обещания в простом Javascript.
Однако в NodeJs подобные вещи на самом деле возможны, если предоставить синхронный метод в текущем потоке, затем перейти к асинхронному методу и вернуться к синхронному методу, когда метод asynchronoues разрешится. См. Волокна или оболочки вокруг него, например synchronize.js .
Таким образом, вызов метода async на самом деле не представляет большой проблемы. Однако может возникнуть другая проблема. Хотя контекст плагина предлагает метод resolveId
, этого недостаточно. Нам нужно вызвать transform
из rollup-plugin-vue
чтобы извлечь код машинописного текста из компонентов одного файла vue. К сожалению, контекст плагина не предлагает такой функции.
Одним из подходов к решению этой проблемы может быть добавление rollup-plugin-vue
в качестве зависимости к вашему проекту и запуск transform
непосредственно в плагине vue. Это, конечно, совсем не красиво, и это не тот способ работы с подключаемыми модулями, который предполагается использовать.
Другой подход может заключаться в запуске только transpileModule
в transform
для каждого файла при первом запуске, чтобы позволить объединению собирать весь импорт, а плагин vue transform
- единственный компоненты файла и кэшировать извлеченный код машинописного текста. Затем, до завершения накопления, отбросьте перенесенный код и выполните правильную компиляцию машинописного текста для кода, который мы кэшировали в хуке плагина renderChunk
или generateBundle
. Это может мешать работе других плагинов, которые применяют к коду дополнительные преобразования, которые мы бы отбросили.
Более красивого решения пока не вижу.
Изменить: если подумать, второй подход, возможно, не уродлив. Вместо перехватов renderChunk
или generateBundle
плагин мог обнаружить себя, когда импортируется последний импорт, и в этот момент начать компиляцию с нуля и добавить скомпилированный файл в очередь накопления таким образом, чтобы он фактически может обрабатываться и всеми другими плагинами. Однако от ранее созданных файлов все равно нужно отказаться, чтобы они не попали в окончательный пакет.
Тем не менее, этот подход тратит некоторое время на обработку, поскольку он позволяет другим плагинам также работать с файлами, которые мы все равно отбрасываем.
@danimoh @eddow Обходной путь для обоих примеров репозиториев - отключение проверки ошибок с помощью // @ts-ignore
чуть выше ошибочного импорта.
Ошибка в основном заключается в том, что машинописный текст жалуется, что он не знает, что это за тип * .vue ( Cannot find module
означает тип модуля). Как только это будет отключено, все будет скомпилировано правильно. Обратной стороной является то, что вещи, импортированные из файлов vue, имеют тип any
и не помогают при проверке ошибок.
(в минимальном репо первому компоненту нужна ссылка на второй, иначе свертка дерева вытряхнет его из пакета)
@danimoh да, нет возможности получить исходный код модуля из свертки через контекст. Большая часть этого может быть выполнена на стороне плагина vue (я открыл там кейс), но все еще есть потенциальные подводные камни, например, rpt2 необходимо преобразовать извлеченный скрипт перед преобразованием скрипта, который его импортирует.
Я думаю, что подход, который вы описываете в ветке выпуска vue, требует, чтобы машинописный текст обрабатывал файлы по одному, поскольку он по существу игнорирует импорт файлов vue и ждет, пока свертка вернет их обратно в машинописный текст. Следовательно, вы потеряете проверку типов в файлах.
В качестве альтернативы разрешению плагину vue обрабатывать ts, следующий подход может быть допустимым и своего рода лучшей итерацией уродливых хаков, которые я предложил ранее:
options
?transform
в плагине vue.CompilerHost
и LanguageServiceHost
могут быть загружены на заказ fileExists
, readFile
, getScriptSnapshot
и т.п..vue
. Для всех файлов vue мы кэшируем извлеченный код машинописного текста и перезаписываем такие методы, как readFile
чтобы вернуть этот кешированный ts-код для импорта vue
.Изменить: на самом деле, если мы можем перезаписать fileExists
и readFile
, нам не нужно будет собирать импорт самостоятельно, просматривая AST, поскольку машинописный текст просто вызовет эти методы для всех импортов, которые он хочет импортировать. в любом случае. Затем нам просто нужно вызвать плагин vue по запросу.
Экземпляр плагина Vue, вероятно, открыт, я не знаю, ожидает ли накопительный пакет плагинов, чтобы они вызывали друг друга, и если что-то сломается (немедленно или в будущем) в этом случае.
Ваш второй пункт будет работать, это именно то, для чего нужен LanguageServiceHost
.
Этот подход может сработать, основным недостатком является потенциально хрупкая связь с плагином vue и дополнительные циклы для одноразовой работы.
Я бы хотел, чтобы у накопительного пакета был способ для плагинов прервать преобразование и объявить зависимость, которая должна быть преобразована перед повторной попыткой текущего файла, тогда это можно было бы реализовать чисто ...
Я думаю, что на самом деле нет одноразовой работы. Typescript скомпилирует код только один раз, а также плагину vue потребуется обработать каждый файл только один раз, если мы кэшируем извлеченный код ts. Этот подход не отменяет никаких собственных результатов или результатов других плагинов, кроме моего предыдущего предложения.
Да, в свертке потребуются некоторые архитектурные изменения. Возможно, там можно было бы открыть проблему, чтобы реализовать что-то вроде этого, но это, вероятно, займет много времени.
Также я не уверен, действительно ли это делает вещи намного лучше. Мы по-прежнему должны убедиться, что typescript компилирует все сразу, чтобы выполнять проверку типов во всех файлах. В противном случае мы тоже можем столкнуться с этим .
У меня работает эта настройка, чтобы скомпилировать один компонент 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' },
],
}
Я не уверен, что это лучший способ создать модуль из Vue SFC с lang = "ts".
У меня работает эта настройка, чтобы скомпилировать один компонент vue:
Верно, но это не настоящий вариант использования. Привет, мир. Для тех, у кого возникли проблемы с пониманием проблемы, вот что я почерпнул.
Зачем? вот пример:
<script lang="ts">
import Bar from './Bar.vue';
...
</script>
1) плагин vue передает скрипт в плагин машинописного текста
2) плагин typescript обнаруживает файл .vue
, но не знает, что с ним делать, потому что накопительный пакет не предоставляет механизм, позволяющий плагинам передавать другим плагинам импорт, такой как webpack. Обычный JS может относиться к плагинам, но код, уже обрабатываемый плагином, не может.
3) На самом деле я не понимаю, почему это отличается от lang=scss
или lang=ts
, но я предполагаю, что это так.
Ну что мне делать?
Немного.
Но vuetify! буэфи!
Vuetify - это машинописный текст, но не использует SFC. Это чистые функции рендеринга.
Buefy использует SFC и свертку, но не машинописный текст.
Правда, я ничего не могу поделать?
Тебе это не понравится. Для каждого файла Vue, который вам нужно импортировать из файла машинописного текста, вам нужно будет создать обычный посредник для файлов javascript.
import Bar from './Bar.vue';
export default Bar;
Тогда и только тогда вы сможете создать свою библиотеку компонентов SFC машинописного текста с помощью накопительного пакета.
Боже, это отстой
Если вы придумали лучшее решение, я бы хотел его услышать.
Самый полезный комментарий
Верно, но это не настоящий вариант использования. Привет, мир. Для тех, у кого возникли проблемы с пониманием проблемы, вот что я почерпнул.
rollup буквально не может этого сделать
Зачем? вот пример:
1) плагин vue передает скрипт в плагин машинописного текста
2) плагин typescript обнаруживает файл
.vue
, но не знает, что с ним делать, потому что накопительный пакет не предоставляет механизм, позволяющий плагинам передавать другим плагинам импорт, такой как webpack. Обычный JS может относиться к плагинам, но код, уже обрабатываемый плагином, не может.3) На самом деле я не понимаю, почему это отличается от
lang=scss
илиlang=ts
, но я предполагаю, что это так.Немного.
Vuetify - это машинописный текст, но не использует SFC. Это чистые функции рендеринга.
Buefy использует SFC и свертку, но не машинописный текст.
Тебе это не понравится. Для каждого файла Vue, который вам нужно импортировать из файла машинописного текста, вам нужно будет создать обычный посредник для файлов javascript.
Тогда и только тогда вы сможете создать свою библиотеку компонентов SFC машинописного текста с помощью накопительного пакета.
Если вы придумали лучшее решение, я бы хотел его услышать.