Rollup-plugin-typescript2: Просмотр импорта файла

Созданный на 9 янв. 2019  ·  14Комментарии  ·  Источник: ezolenko/rollup-plugin-typescript2

При переключении с 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 без проблем.

Это может быть связано с этой проблемой, хотя у меня есть последняя версия (действительно, сегодня для каждого плагина).

bug help wanted

Самый полезный комментарий

У меня работает эта настройка, чтобы скомпилировать один компонент vue:

Верно, но это не настоящий вариант использования. Привет, мир. Для тех, у кого возникли проблемы с пониманием проблемы, вот что я почерпнул.

rollup буквально не может этого сделать

Зачем? вот пример:

<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 машинописного текста с помощью накопительного пакета.

Боже, это отстой

Если вы придумали лучшее решение, я бы хотел его услышать.

Все 14 Комментарий

Не могли бы вы опубликовать свою конфигурацию 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
  • rollup возвращает обещание
  • Если я правильно понимаю, все, что я могу сделать с обещанием, - это дать еще одно обещание

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, следующий подход может быть допустимым и своего рода лучшей итерацией уродливых хаков, которые я предложил ранее:

  • Доступен ли экземпляр плагина vue через хук options ?
    Таким образом мы могли бы вызвать метод transform в плагине vue.
  • Из https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API мне кажется, что ts CompilerHost и LanguageServiceHost могут быть загружены на заказ fileExists , readFile , getScriptSnapshot и т.п.
  • Если оба работают, мы могли бы позволить машинописному тексту анализировать код, который мы получаем из плагина vue, в AST, собирать импорт из этого AST и запрашивать их из плагина vue, если это файлы .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:

Верно, но это не настоящий вариант использования. Привет, мир. Для тех, у кого возникли проблемы с пониманием проблемы, вот что я почерпнул.

rollup буквально не может этого сделать

Зачем? вот пример:

<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 машинописного текста с помощью накопительного пакета.

Боже, это отстой

Если вы придумали лучшее решение, я бы хотел его услышать.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги