Rollup-plugin-typescript2: Файл типизации сгенерирован в неправильной папке внутри объекта в качестве свертки `input`

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

Что происходит и почему это не так

Возможно, это неправильная конфигурация с моей стороны, но это похоже на ошибку. Когда вы используете object качестве свойства input для конфигурации объединения, файл типизации для входных файлов создается в корневой папке репозитория (в той же папке, что и файл конфигурации объединения) и а не целевой выходной каталог (здесь ./dist ) вместе со связанным файлом JS.

Версии

  • машинопись: 3.2.4
  • накопительный пакет: 1.1.2
  • скопированный плагин typescript2: 0.19.2

rollup.config.js

{
    ...
    input: {
        Lib1: './src/Lib1.tsx',
        Lib2: './src/Lib2.tsx'
    },
    output: {
        dir: './dist',
        format: 'cjs',
        sourcemap: true,
        entryFileNames: '[name].js'
    }
}

tsconfig.json

{
  ...
  "compilerOptions": {
    "outDir": "./dist"
  },
}

Результат:

// These files are created
./Lib1.d.ts
./Lib2.d.ts

// instead of (expected):
./dist/Lib1.d.ts
./dist/Lib2.d.ts

Любопытно, что если вы введете entryFileNames: 'dist/[name].js' он создаст лишнюю подпапку с именем dist в папке dist и создаст их там.

bug more info needed

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

Ага. кажется, это единственный способ, если вы не позволите tsc выполнять комплексную сборку.
Похоже, что эти накопительные плагины эффективно просят tsc выполнить две разные задачи:

  1. «Проверьте тип и преобразуйте все эти отдельные модули в JavaScript», и позвольте мне (например, Rollup) выполнить сборку и запись на диск.
  2. «Сделайте все объявления для этой папки проекта TS и выкиньте их туда».

Результаты 1 и 2 не совпадают и не могут совпадать, когда вы используете «карту ввода», разделение кода и т. Д. - AFAICT.

... если только вы не сделаете плагин накопления более вовлеченным в процесс генерации объявления типа.

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

Вариант плагина useTsconfigDeclarationDir является временным решением.

Это может быть исправлено с помощью # 142, выпущенного в 0.20.0.

Привет, @ezolenkom и @jakearchibald , ни с одним из них не повезло.

При добавлении параметра useTsconfigDeclarationDir в мой подключаемый модуль накопления файлы объявлений больше не создаются. И обновление до 0.20.1, к сожалению, не повлияло.

@benkeen при использовании опции плагина useTsconfigDeclarationDir: true вам также необходимо иметь значение declarationDir в tsconfig.json

у меня похожая проблема, мой макет проекта такой:

export default [ 
  {
    input: 'src/subFolder1/one.ts,
    output: [
                    {
                      file: 'dist/one.js'
                      .....                      
                     }
    ],
    plugins: [
           typescript({
                typescript: require('typescript'),
            }),
    ]
  },
      input: 'src/subFolder2/two.ts,
      output: [
                    {
                      file: 'dist/two.js'
                      .....                      
                     }
    ],
     ...
  },
]

На выходе у меня есть:

  |---subFolder1
  |          |--------one.d.ts
  |
  |---subFolder2
  |          |---------two.d.ts
  |-----one.js
  |-----two.js

У меня работает на 0.20.1 с useTsconfigDeclarationDir: false - файлы d.ts попадают в папки, указанные в output.[].dir . @benkeen не могли бы вы попробовать еще раз?

@AntonPilyak , это по замыслу - если d.ts входили в одну папку без дополнительных путей, то если бы у вас были subFolder1/one.ts и subFolder2/one.ts , один из них перезаписывал бы другой.

@ezolenko : эта функция, я думаю, скорее создает больше неудобств, чем решает реальную проблему (из-за того, что сложно поддерживать всю эту структуру каталогов). Мне нужно создать сценарий, который копирует все эти объявления типов в корень пакета и добавляет каталоги в .npmignore, чтобы создать пакет, который легко включить. Я бы посоветовал вам создавать эти дополнительные каталоги ТОЛЬКО для файлов типов с такими же именами. А для всего остального используйте каталог, определенный в разделе «output» файла rollup.config.json.

@AntonPilyak, вы могли бы использовать параметр useTsconfigDeclarationDir: true , настроить declarationDir в tsconfig, это должно позволить самому машинописному тексту обрабатывать пути вывода ввода.

Решение о том, следует ли использовать подкаталоги на основе уникальности путей, было бы кошмаром в развивающемся проекте, внезапно ваш набор текста переместится в подпапку только потому, что вы добавили новый файл с тем же именем в другую папку.

Обычно, если вам нужен красивый текст, вы все равно захотите объединить их в один файл (был модуль npm, имя которого я все время забываю)

Я использую версию 0.22.0 и у меня почти та же проблема, что и у @AntonPilyak

{
    ...
    input: {
        foo: 'src/lorem/foo.ts',
        bar: 'src/ipsum/bar.ts'
    },
    output: {
        dir: 'dist',
        format: 'cjs',
        sourcemap: true,
    }
}

И я получаю это:

dist/
    lorem/
        foo.d.ts
    ipsum/
        bar.d.ts
    foo.js
    foo.js.map
    bar.js
    bar.js.map

Очевидно, мне бы хотелось, чтобы файлы *.d.ts располагались рядом с файлами *.js и *.js.map .

Я пробовал возиться с useTsconfigDeclarationDir и declarationDir но безрезультатно.

Файлы определений всегда оказываются внутри подпапок lorem и ipsum соответственно и никогда не попадают в плоский список.

Более того, похоже, что он создает файлы объявлений для каждого найденного файла .ts, а не только для точек входа.

dist/
    lorem/
        foo.d.ts
    ipsum/
        utils/
            bar-helper.d.ts
        bar.d.ts
     some_other_ts_file/
         not_imported_by/
             neither_foo_nor_bar/
                  wat.d.ts
    foo.js
    foo.js.map
    bar.js
    bar.js.map

Я пробовал ограничивать options.tsconfigOverride.input только точками входа, но, похоже, это не имеет никакого эффекта. На самом деле я даже не уверен, что tsconfigOverride.input вообще работает.

Все это немного сбивает с толку.

...

Я имею в виду, достаточно справедливо, если ему нужно создать файл декларации для utils/bar-helper.ts но как минимум wat.ts следует исключить из всего этого.

Да, он генерирует объявления для всех файлов, найденных tsconfig, если вы не хотите, чтобы конкретный файл касался, убедитесь, что он исключен или не включен в tsconfig. Чтобы увидеть список файлов, найденных машинописным текстом, запустите плагин с уровнем детализации 3 и найдите запись "parsed tsconfig".

Для пути определений, где в вашем примере вы хотите разместить определение для 'src/ipsum/foo.ts' ?

Поскольку это определение для dist/foo.js я предполагал, что оно окажется рядом с ним - точно так же, как файл исходной карты - то есть в dist/foo.d.ts .

Сможет ли TypeScript объединить dist/foo.js и dist/lorem/foo.d.ts ?

Полный сценарий, в котором это не удается:
src / dir1 / foo.ts
src / dir2 / foo.ts

dir1 / foo.ts используется в качестве входных данных для объединения и импортирует dir2 / foo.ts. Rollup создаст пакет dist / foo.js, который будет содержать соответствующие части обоих исходных файлов, но машинописный текст должен где-то создать 2 файла определения типов с одинаковыми именами.

Простое решение - использовать подпапки, зеркально копируя исходный макет. Я думаю, что это то же самое, что и tsc , если вы не укажете ему объединить определения типов (rpt2 не поддерживает объединение определений).

И да, машинописный текст знает, где найти определения типов. Так что кроме того, что это немного беспорядочно, это не должно быть проблемой. Если вы хотите развернуть пакет с типами в npm, установите "types" в package.json в файл d.ts для вашей точки входа. Машинопись найдет что-нибудь оттуда.

Ах, значит, этот плагин на самом деле не управляет какой-либо частью процесса объявления-сборки. Он просто запускает tsc чтобы сделать свое дело, независимо от процесса Rollup?

Тем не менее, если я раскрываю / публикую только несколько модулей, зачем мне нужно, чтобы TypeScript генерировал файлы *.d.ts для каждого отдельного файла ts, с которым он сталкивается? Нет возможности ограничить его только точками входа?

Дело в том, что я экспортирую набор автономных модулей ( import tool1 from 'myTools/tool1'; т. Д.), Поэтому в pkg.types нет единой точки входа. Каждый файл определения должен находиться рядом с его эквивалентом *.js чтобы VSCode мог его подобрать.

Еще хуже, если у меня

{
    ...
    input: {
        fooscript: 'src/foo/index.ts',
        barscript: 'src/bar/index.ts'
    },
    output: {
        dir: 'dist',
        format: 'cjs',
        sourcemap: true,
    }
}

Я получил:

dist/
    foo/
        index.d.ts
    bar/
        index.d.ts
    fooscript.js
    fooscript.js.map
    barscript.js
    barscript.js.map

И теперь у TypeScript нет возможности объединить dist/fooscript.js и dist/foo/index.d.ts .

...

Нет ли способа, которым ваш плагин мог передать TypeScript путь назначения / вывода для каждого файла пакета JavaScript? Кажется, что tsc получает исходное имя файла записи и крепко держится за него при создании объявлений.
... или для каждого из входных файлов найдите соответствующий файл *.d.ts и переместите + переименуйте его в место назначения карты входного файла. (Вы можете заметить, что я говорю здесь не из своей задницы, так что ... ;-)

Это то, что я обязательно попробую вручную после того, как Rollup завершит работу, но было бы намного лучше, если бы плагин обрабатывал это автоматически.

Нет, плагин использует LanguageServices (обычно используются те же IDE API машинописного текста), поэтому я могу контролировать, что и где писать.

Чтобы написать одно определение типа для каждого сводного ввода, нам нужно объединить определения для всех импортов для этого ввода. Rollup может видеть один входной ts-файл, но он может импортировать и объединять любое количество исходных файлов при его сборке, и эти типы также должны быть сгенерированы.

В настоящее время я ошибаюсь при создании определений для всего, что машинописный текст находит при просмотре файла tsconfig. Если я генерирую типы только для транспилированных модулей, файлы только типа будут проигнорированы.

Возможно, мне придется вернуться к этой части, API значительно изменился с тех пор, как эта часть была сделана ...

Мне нужно посмотреть, как заставить ваш пример работать. Может потребоваться лучшая поддержка нескольких пакетов в одной конфигурации накопительного пакета.

Но как вы потребляете этот пакет после его сборки? Это не то, что вы можете опубликовать в npm и импортировать по имени пакета ...

Составляю сборник автономных утилит. Корневая папка опубликованного / установленного пакета содержит все файлы встроенных модулей в виде плоского списка.

(Я пишу их в TS / ES6 во вложенной структуре папок со смешанными тестовыми файлами и полагаюсь на Rollup, чтобы преобразовать их в плоский список файлов CJS с эффективным сочетанием разделения кода и встраивания для любых общий код.)

Затем я использую эти инструменты, импортируя их по имени файла, например:

import tool1 from 'myTools/tool1';
import tool2 from 'myTools/tool2';

Идея состоит в том, что, не имея единой точки входа для всего набора инструментов (без записей pkg.main или pkg.module ), я могу без опаски добавлять редко используемые и даже экспериментальные инструменты. без увеличения веса / раздувания для последующих потребителей (у которых может не быть эффективного встряхивания деревьев).

... Я немного поигрался с tsc в командной строке, и теперь я думаю, что вижу ограничения, с которыми вы имеете дело.

Однако я заметил, что если вы запустите tsc и установите для формата модуля / вывода значение "amd" или "system" , он сгенерирует один файл *.d.ts с аккуратным списком всех необходимые блоки declare module "..." встроены.

Интересно, можно ли каким-то образом использовать это поведение - путем переименования / перемещения файла и разворачивания / перезаписи последнего (основного) объявления модуля?


Боковое примечание: я также заметил, что tsc , похоже, не прилагает особых усилий для того, чтобы встряхнуть этот файл декларации. В одном случае я вижу основной модуль (точка входа), который экспортирует единственную, очень простую сигнатуру функции, и, тем не менее, файл объявления предоставляет блоки объявлений для всех частных модулей, используемых «за кулисами». Смешной. :-)

Привет еще раз.
На данный момент я устанавливаю пользовательский declarationDir для tsc чтобы выгружать все *.d.ts , а затем запускаю автономный скрипт, который импортирует тот же входной файл в- объект output-file, когда я передаю его в Rollup, и он генерирует файлы объявлений уровня назначения пакета, которые просто export * from фактический файл объявления.

По сути, я генерирую dist/fooscript.d.ts который содержит только:

export *  from './__types/foo/index';

Это уродливый автономный способ взлома, но он дает предсказуемо правильные результаты.

Интересно, может ли rollup-plugin-typescript2 сделать что-то подобное?

Это сработает, да.

У меня есть пара идей (когда я к ним прихожу), например, создание <bundlename>.d.ts , у которого есть куча /// <reference types=""/> для каждого задействованного d.ts.

Сначала мне, возможно, придется исправить связанную ошибку, связанную с генерацией слишком большого количества объявлений типов, и ограничить это только корневым файлом и всем, что он фактически импортирует.

Несколько мыслей:

ИМО, единственная действительно уродливая часть моего хака - это то, что он стоит отдельно от процесса накопления пакетов. Посредник *.d.ts на самом деле является довольно изящным и идиоматическим способом связи между пакетами, сгенерированными Rollup, и определениями tsc .

Поскольку файлы объявлений, сгенерированные tsc , ссылаются друг на друга через относительные пути, эту структуру файлов / папок, вероятно, лучше оставить в покое - иначе вам придется повторно реализовать части функциональности Rollup для синтаксиса настраиваемого языка.

И если rollup-plugin-typescript2 устанавливает что-то вроде output.dir + '__types' как declarationDir по умолчанию, то любой беспорядок, вызванный чрезмерным рвением tsc будет аккуратно устранен. загляните в папку с четким названием. Таким образом, посторонние файлы определений становятся очень незначительной проблемой IMO.


FWIW, вот суть моего сценария:

const { makeInputMap, getEntrypoints, distFolder, srcFolder } = require('./buildHelpers');
const { writeFileSync } = require('fs');
const { relative } = require('path');

const srcPrefixRe = new RegExp('^' + srcFolder + '/');
const tsExtRe = /\.tsx?$/;

const declDirRelative = './' + relative(
  distFolder,
  require('../tsconfig.json').compilerOptions.declarationDir
);

const tsEntrypoints = getEntrypoints()
  .filter((fileName) => tsExtRe.test(fileName));

Object.entries(makeInputMap(tsEntrypoints))
  .forEach(([moduleName, sourcePath]) => {
    const tscDeclFile = sourcePath
      .replace(srcPrefixRe, declDirRelative + '/')
      .replace(tsExtRe, '');
    const outFile = distFolder + '/' + moduleName + '.d.ts';
    writeFileSync(
      outFile,
      [
        'export * from "' + tscDeclFile + '";',
        'import x from "' + tscDeclFile + '";',
        'export default x;',
        '',
      ].join('\n')
    );
  });

console.info('Created local declaration files for TypeScripted entrypoints.');

Я обновил приведенный выше пример, так как кажется, что экспорт по умолчанию нужно явно реэкспортировать.

Предварительное тестирование показывает, что слепой реэкспорт default из файла декларации, в котором нет экспорта default безвреден и незаметно игнорируется. (По крайней мере, по VSCode.)

Привет, должна ли эта проблема быть решена в версии 0.23.0?

(... интересно, стоит ли мне попробовать обновить свой проект, чтобы отказаться от всех настраиваемых ошибок)

0.23 не будет генерировать декларации для всего, что находится в поле зрения, но она все равно будет генерировать декларации, которые вы фактически импортируете в соответствующие подпапки. Вы, вероятно, можете обновить и иметь более легкие типы, но пока нечего генерировать объявления корневого типа.

Мой собственный сценарий сборки обходного пути (см. Выше) постепенно проникает во все больше и больше моих проектов. о_О

К вашему сведению: разработка официального пакета @ rollup / plugin-typescript с тех пор возобновилась, и теперь в нем есть функция проверки типов и вывода файлов объявлений, поэтому я лично перехожу на его использование.
Однако ограничения во многом те же.

@maranomynet Вы по-прежнему полагаетесь на свой сценарий для перемещения файлов декларации после того, как свертка сделает свое дело? Мне не очень повезло с переключением.

Ага. кажется, это единственный способ, если вы не позволите tsc выполнять комплексную сборку.
Похоже, что эти накопительные плагины эффективно просят tsc выполнить две разные задачи:

  1. «Проверьте тип и преобразуйте все эти отдельные модули в JavaScript», и позвольте мне (например, Rollup) выполнить сборку и запись на диск.
  2. «Сделайте все объявления для этой папки проекта TS и выкиньте их туда».

Результаты 1 и 2 не совпадают и не могут совпадать, когда вы используете «карту ввода», разделение кода и т. Д. - AFAICT.

... если только вы не сделаете плагин накопления более вовлеченным в процесс генерации объявления типа.

Ах да, вот что я понял, спасибо! Дала вам за полезный ответ, а за то, что я к этому отношусь.

Удачи с этим?

Для любой борющейся души, имеющей ту же структуру папок src, что и у @maranomynet и у меня.

Я нашел быстрое решение для этого, может быть, еще один уродливый способ, но работает для меня.

Я использую rollup-plugin / typescript2, поэтому в этом ответе я воспользуюсь его конфигурацией:
Определите свой собственный каталог декларации в вашем tsconfig.json, чтобы ваш проект мог сбрасывать все файлы * .d.ts по своему собственному пути в связанном dist. И не забудьте установить для useTsConfigDeclarationDir значение true в вашем подключаемом модуле машинописного текста в файле конфигурации накопительного пакета.
Кроме того, если вы определяете выходные пути для своих индивидуальных пакетов компонентов в своем rollup.config.js (и package.json), измените эти пути, чтобы они были такими же, как ваш «каталог декларации» + «как ваш маршрут компонента src». Итак, если ваш компонент в src похож на:

src / домашняя страница / foo.tsx

И ваше объявлениеDir:

dist / MyDeclarationDir

Итак, ваш выходной путь должен быть таким:

dist / MyDeclarationDir / домашняя страница / foo.js

Таким образом, свертка будет включать ваши типы в тот же каталог, что и ваш компонент main.js, и ваш проект TS-потребителя получит эти типы.

Таким образом, пакет будет выглядеть примерно так:

dist /

    declarationDirPath/
                  component1/
                        foo.js/
                              foo.js
                              foo.map.js
                        foo.d.ts
                   component2/
                        bar.js/
                               bar.js
                               bar.map.js
                        bar.d.ts
Была ли эта страница полезной?
0 / 5 - 0 рейтинги