Недавно на моей последней работе я взялся за проект, связанный с техническим долгом, который требовал удаления повторяющегося кода из 7 (😲) репозиториев, который можно было бы реализовать как многоразовый пакет NPM для импорта и внедрения. Я решил писать код на Typescript. Когда пришло время публиковать, у меня возник вопрос: «Как я собираюсь связать этот код?»

Как и все, что связано с JavaScript и программированием, есть несколько способов снять шкуру с этой кошки. Варианты, которые я рассматривал:

  • Посылка
  • Свернуть
  • TSC
  • Вавилон

Я использовал Parcel для разработки своего Provider компонента, поэтому теоретически я мог бы просто использовать их вывод, но я быстро исключил эту опцию, поскольку он выводил один файл, который я не считал идеальным. Я хотел убедиться, что есть возможность встряхивать дерево, и понял, что вывод Parcel отлично подходит для компиляции кода для вывода окончательного пакета. Не обязательно идеален для написания компонентов.

В этой статье будут рассмотрены некоторые преимущества и недостатки Rollup, TSC и Babel.

Некоторые распространенные установочные файлы: tsconfig.json:

И упрощенная версия package.json, включающая несколько скриптов для запуска:

Первый - это Rollup:

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

Что ж, это описание, похоже, попало в самую точку! Что хорошо в Rollup, так это то, что он даже включает логику для встроенного встряхивания деревьев моего кода разработки.

Настроить Rollup очень просто с помощью простого файла rollup.config.js.

В идеале этот файл конфигурации имеет то, что плагин typescript имеет «параметры» для дальнейшей настройки того, что входит в комплект. Например, в моем реальном коде myComponent.test.tsx тестовых файла. Я не хочу игнорировать эти файлы в tsconfig.json, но я также не хочу включать мои тестовые файлы в качестве выходных данных сборки для NPM. Так что у tsconfigOverride есть полезная exclude опция для достижения этой цели.

Также обратите внимание на массив output: Rollup может экспортировать как ESModules, так и CommonJS (и AMD для тех, кому это нужно). Вы видели в своем package.json поля для module и main и задавались вопросом, что и когда они вам понадобятся? Это время! Когда ваш пакет NPM создан, эти 2 поля можно использовать, чтобы ваш исполнитель сборки / разработчика знал, где найти содержимое этого пакета.

Нам нужно будет отредактировать строку 12 файла package.json следующим образом:

Давайте запустим Rollup CLI и посмотрим, что произойдет. У меня есть npm script для вызова накопительного пакета: build: “npm run rollup -c". Вот результат:

Вы можете увидеть важный index.d.ts файл, который создает файл декларации, так что когда вы import { Button } from ‘reusable-thing’ модуль будет правильно разрешен, и (Бонус) вы избежите ошибки линтинга: error TS2307: Cannot find module 'moduleA'.

Это было довольно просто. Если вам интересно, почему я добавил тип экспорта cjs, это потому, что проект не смог разрешить мой модуль как тип es. К сожалению, я так и не разобрался в «почему». Чтобы использовать cjs типы экспорта, мне пришлось настроить несколько вещей при использовании commonjs плагина.

Накопительный пакет хорош тем, что доступен плагин. Аналогично среде webpack. Нужно скопировать какой-нибудь файл, отличный от js? Наверное, есть плагин.

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

Давайте запустим команду и посмотрим, что произойдет. Сначала нам нужно обновить скрипт npm в строке 12 пакета до npm run tsc.

Потом запускаем. 🤔 Это интересно. Терминал выглядит нормально. Но build вывод пуст !? О верно. Нам нужно изменить флаг tsconfig noEmit на false, чтобы компилятор выдавал выходные данные.

Снова запустите build. Теперь выходной каталог немного отличается от сводной версии:

Наиболее очевидным изменением является то, что исключенные stories.js файлы теперь находятся здесь. Это нормально? Может быть ... может быть, перед упаковкой вашего модуля npm вы можете обновить файл npmignore, чтобы исключить их 🤷‍♂.

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

Обратите внимание, что в исходном tsconfig declaration установлено значение true. Поэтому у нас есть свои d.ts файла без каких-либо дополнительных изменений.

А как насчет файлов, отличных от JS, таких как svg, json, jpg? Ну, они не копируются TSC автоматически. Вам нужно будет добавить еще один npm script к вашей команде, которая будет выполняться после.

Наконец, давайте посмотрим на Babel. С самого начала Babel имеет аналогичное ограничение компиляции, о котором следует помнить, подобное TSC выше, в том смысле, что он выглядит только как файлы «js». Для любых файлов, отличных от js, потребуется тот же сценарий «копирования», что и выше.

Можно создать новый babel.config.js файл. Вам может потребоваться загрузить дополнительные плагины для @babel, чтобы это работало правильно.

Кроме того, давайте обновим наш скрипт package.json в строке 12, чтобы:

И мы можем снова запустить npm run build. Вот результат build:

Сразу обратите внимание, что нет файла *.d.ts или чего-либо, связанного с «типами», для использования после того, как он упакован NPM. Это сделано специально от компании Babel. В конце концов, это всего лишь транспилятор:

Обратной стороной использования babel является отсутствие проверки типов при переходе с TS на JS.

Чтобы решить эту проблему, добавьте команду tsc с измененным tsconfig, которая генерирует только файлы объявлений. В этом случае необходимо установить флаг emitDeclarationTrue.

Надеюсь, это сравнение поможет. Каждый из этих вариантов жизнеспособен. Это действительно зависит от ваших настроек и требований.

Как бы то ни было, я использовал Rollup в своей Provide библиотеке.

Однако в другом проекте TS в рамках устаревшего приложения «блокировка шага микрофронта» я реализовал такую ​​команду сборки:

"build": "NODE_ENV=production npm run clean && npm run tsc && babel --extensions \".ts,.tsx\" src --out-dir build",

Мы запускаем tsc, чтобы выполнить проверку типа перед переносом в чистый пакет JS. В других приложениях нам нужно включить скрипт копирования, чтобы включить эти ресурсы, не относящиеся к js.