Index.ts – зло и польза
Привет всем! Меня зовут Михаил, я старший Frontend-разработчик в НЛМК, занимаюсь разработкой одной из внутренних информационных систем на React + Typescript.
Расскажу про самый короткий и наименее трудоемкий способ экспорта и импорта модулей, что частенько требуется для построения современных приложений. А именно опишу свой эксперимент с импортом и экспортом без использования файла Index.ts, затем — с его использованием. Для наглядности я создал небольшой проект с Webpack и Typescript в редакторе исходного кода Visual Studio Code (далее по тексту VS Code).
Файл webpack.config.js содержит дефолтные настройки, никаких плагинов я не использую. В статье посмотрим на результаты сборки проекта с помощью Webpack в режиме “mode=development”, в режиме “mode=production” и затем подведем итоги.
Структура проекта выглядит следующим образом:
В app.ts происходит подключение модулей mod1, mod2, mod3. А модули mod1, mod2, mod3 внутри себя импортируют типы из папки types.ts.
Само приложение очень простое.
Объявляем две числовые константы. Вызываем функцию суммирования чисел из mod1, затем вызываем функцию из mod2, получаем строку с текстовым описанием проделанной операции и для вывода описания в консоль вызываем функцию из mod3.
Начнем рассмотрение без файлов Index.ts.
Содержимое файлов представлено ниже:
app.ts
mod1:
mod2:
mod3:
Типы простейшие используются для демонстрации:
caption_types:
resultMessage_types:
sumElement_types:
Видим в app.ts три строки импорта до каждого файла, т.е.
необходимо прописывать путь до файла;
проникновение во внутреннюю реализацию, в структуру и именование файлов внутри общей папки parts;
необходимость писать 3 отдельных импорта.
В файлах модулей mod1, mod2, mod3 импорт типов обладает всеми вышеописанными недостатками. Если бы происходил импорт более одного типа, то каждый тип импортировался бы отдельной строкой и напрямую зависел бы от расположения файла с типом внутри папки types. Т.е., если внутри папки types возникнет необходимость перенести файл с экспортируемым типом в другую папку или перенести экспортируемый тип в другой файл, во всех модулях, импортирующих этот тип, придется внести изменения.
Проведем сборку с помощью Webpack в режиме “mode=development”, в режиме “mode=production”.
mode=development:
Сборка прошла за 3380 миллисекунд, результирующий файл main.js весит 6.16 килобайт.
mode=production:
Сборка прошла за 3622 миллисекунды, результирующий файл main.js весит 50 байт.
Запомним эти результаты и теперь добавим в проект файлы Index.ts.
Первым делом видим структуру проекта, которая явно увеличилась.
Посмотрим, что содержат файлы Index.ts в папках parts и types:
parts/Index.ts:
types/Index.ts:
Благодаря файлам Index.ts в папках с модулями mod1, mod2, mod3 и в папках с типами caption, resultMessage, sumElement не нужно писать что-то типа export * from './mod1/mod1' - видим задвоение /mod1/mod1.
Посмотрим, как изменился наш файл app.ts:
В app.ts:
нет необходимости прописывать путь вплоть до файла;
мы ничего не знаем про внутреннюю реализацию и структуру файлов внутри общей папки parts;
одна строка импорта для функций через именованный деструктурированный импорт.
Теперь импорты типов в mod1, mod2, mod3 напрямую не зависят от расположения файла с типом внутри папки types и имени самого файла, экспортирующего данный тип.
Для примера переименуем файл с типом CaptionItem из “caption_types” в “renamed_caption_types”. Единственной точкой внесения изменений будет файл Index.ts внутри самой папки caption, содержащей переименованный файл.
Таким образом, файлы индекса служат «шлюзом» для всего импорта, связанного с папкой, в которой они находятся. Это своего рода “оглавление” экспортов папки.
Экспорт через файл Index.ts защищает от экспорта типов или переменных с одинаковыми названиями, но возможно с разным содержимым.
Например, в папке types/caption_types находится тип CaptionItem, который равен number.
Добавим в файл resultMessage_types тип с аналогичным названием CaptionItem, но приравняем его string.
После это VS Code выдаст подсказку, что экспортируемый ранее модуль уже экспортирует значение с аналогичным названием.
Импорт типа CaptionItem происходит в модуле mod2, удалим импорт и посмотрим какие варианты для импорта предложит VS Code.
VS Code выдает подсказку для импорта, и разработчик может принять неверное решение - импортировать тип из файла resultMessage_types, а потом гадать, что же происходит. Особенно актуально это на больших проектах. Файл Index.ts позволит избежать этих проблем.
Проведем сборку с помощью Webpack в режиме “mode=development” и в режиме “mode=production” с файлами Index.ts.
mode=development:
Сборка прошла за 3519 миллисекунд, результирующий файл main.js весит 9.02 килобайта.
Без Index.ts файлов сборка в режиме “development” прошла за 3380 миллисекунд и сформировала результирующий файл main.js размером 6.16 килобайт, значит в режиме разработки файлы индекса увеличивают время сборки и попадают в результирующий бандл main.js. Это плохие новости.
Попробуем собрать в режиме “production”.
mode=production:
Сборка прошла за 3915 миллисекунд, результирующий файл main.js весит 50 байт.
Без Index.ts файлов сборка в режиме “production” заняла 3622 миллисекунды, а результирующий бандл весил 50 байт, значит добавление файлов индекса увеличивает время сборки, но в результате обработки файлы индекса не попадают в результирующий бандл main.js., а значит не происходит увеличение бандла, который в итоге будет использоваться в “production”.
Подведем итоги. Выделим + и - использования файлов Index.ts.
Минусы:
Приходится создавать лишние файлы;
Файл проходит через все стадии компиляции;
Увеличивается время сборки;
При сборке в режиме “mode=development” включаются в бандл, увеличивая его размер.
Плюсы:
Пропадает необходимости прописывать путь вплоть до файла;
При импорте из Index.ts мы не завязаны на внутреннюю реализацию и структуру файлов внутри общей папки, из которой происходит экспорт. Это дает нам больше свободы, гибкости в случаях, когда необходимо переименовать, перенести папку или файл, содержащий экспортируемое значение;
При экспорте через файл Index.ts мы защищены от экспорта типов или переменных с одинаковыми названиями. И это может быть банальным задвоением, копированием, а ведь содержимое может быть разным…;
Значительно уменьшается количество строк импорта;
Облегчаем поиск файлов для импорта и делаем их более однозначными.
При сборке в режиме “mode=production” файлы Index.ts не включаются в бандл, не увеличивают размер бандла.
Итого:
На мой взгляд, умеренное использование файла Index.ts в разработке несомненно дает исключительно положительный эффект, если его использовать как “оглавление” для большой директории, содержащей типы, компоненты, модули приложения.
Самое главное, что при сборке для “production” наличие данных файлов не влияет на размер бандла.
В режиме “development” увеличение размера бандла и времени пересборки не столь критично, сколько польза от использования данного файла.
Спасибо за внимание! Пишите комментарии, буду рад узнать Ваше мнение по данному вопросу!