Начав удалять ненужный код, сложно остановиться. В прошлой части были удалены неиспользуемые импорты, в этот раз я найду лишние файлы: пустые readme и дефолтные таблицы стилей. Такие файлы выглядят полезными, но это оптическая иллюзия, которая проходит, если присмотреться.
Рефакторинг подходит для больших проектов: в текущем около 300 файлов историй, и примерно столько же компонентов. PR с лишним кодом унёс с собой 1.4к строк и улучшил время сборки почти на минуту (!).
Для малых проектов лучше сберечь усилия для каких-то более существенных улучшений.
Мёртвый код: код, который не используется.
Лишний код: балласт, который не несёт логики, не улучшает производительность и DX, не улучшает читаемость и не добавляет настоящей документации.
Подобные файлы часто создаются при старой доброй копипасте или при скаффолдинге кода, что сокращает время на рутинные операции, однако, так же часто они отправляются в мастер без разбора.
В моём случае, в проекте было множество README.md файлов с одной строчкой: заглавие с названием компонента. По факту, строк две: заголовок плюс пустая линия (линтер). Эти доки бесполезны, но создают какую-то толику нагрузки при сборке и использовании StoryBook (React Cosmos, Atellier etc.): операции File I/O, парсинг и компилирование пары импортов в каждой истории (дополнительный декоратор и сам Markdown файл).
Другая мишень для рефакторинга это дефолтные файлы стилей, которые добавляются к каждому новому компоненту. В каких-то случаях, такие файлы так и остаются пустышкой с ненужными импортами (S)CSS фреймворка. Если их удалить, внешний вид компонента не изменится: а если нет разницы, то зачем плодить сущности? Проблемы здесь такие же: лишний импорт, парсинг и время на компилирование и tree-shaking при сборке проекта.
Процесс
Доки-пустышки можно найти по количеству строк в файле: их всего две. Также было полезным просмотреть файлы с тремя строчками, среди них тоже нашлись ненужные.
Стили-пустышки было просто опознать по паре обязательных импортов (настройки и утилиты SCSS-фреймворка).
Для очистки файлов я написал шелл-скрипт:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | #!/bin/bash function remove-readmes() { empties=$( # More than 2: mixed results, processed by hand find app -type f -name README.md | xargs wc -l | grep '^\s*[012]\b' | sed -e 's@^\s*[0-9]\s*@@' ) for readme in $empties; do # rm "$readme" stories=$(echo $readme | sed -e 's@/README.md$@\/*.stories.*@') for story in $stories; do # [[ $(grep -q 'withReadme' "$story") ]] && echo $story perl -pi -e 's/^import.*README\.md.*$//g' "$story" [[ ! $? -eq 0 ]] && echo "Problems with $story" perl -pi -e 's/\.addDecorator\(withReadme.*$//g' "$story" [[ ! $? -eq 0 ]] && echo "Problems with $story" perl -pi -e 's/import.*withReadme.*$//g' "$story" [[ ! $? -eq 0 ]] && echo "Problems with $story" done done } function remove-stylesheets () { stylesheets=$( # Exact 2 lines mean redundant imports find app -type f -name *.scss | xargs wc -l | grep '^\s*2\b' | sed -e 's@^\s*[0-9]\s*@@' ) for file in $stylesheets; do fbasename=$(basename "$file") fdir=$(dirname "$file") # rm "$file" for js in $(find $fdir -type f -regextype posix-egrep -regex ".*\.(jsx?|tsx?)$"); do perl -pi -e "s/^import.*$fbasename.*$//g" "$js" done [[ ! $? -eq 0 ]] && echo "Problems with $fbasename" done } |
Код настолько же уродлив, насколько быстро написан, и требует доводки под каждый отдельный случай.
Кроме удаления самих файлов, также удаляются их импорты в историях и компонентах, заодно импорты функций, которые использовались для работы с ними (декоратор withReadme).
После запуска скриптов, все файлы я прогнал через eslint --fix
и починил, что сломалось.
Всего удалил пустышек: под две сотни markdown-доков и около сотни таблиц стилей.
На эти две большие статьи меня вдохновила книга Фаулера про рефакторинг, которую рекомендую.