Определите, какие JavaScript функции НЕ вызывались - PullRequest
2 голосов
/ 16 июня 2020

Представьте, что у вас есть веб-сайт, на котором используются JavaScript библиотеки, будь то ваши собственные или сторонние. Помимо минимизации и запутывания, мне было интересно, можно ли еще больше уменьшить размер полезной нагрузки скрипта, удалив неиспользуемые функции. Как только вы достигнете определенного уровня сложности, становится трудно / невозможно узнать, какие функции в конечном итоге вызываются при всех возможных путях выполнения. И это привело меня к следующему вопросу: есть ли какие-либо инструменты или способы определить после определенного периода использования веб-страницы, какие пользовательские функции (не встроенные) не были вызваны?

Одна очевидная возможность - заключить все определения функций в вызов функции регистрации, которая 1) добавляет функцию регистратору и 2) вводит некоторый код, чтобы пометить функцию как вызванную. Тогда можно будет запросить у регистратора функций те, которые не были вызваны. Однако этот подход чрезвычайно сложен. Лучше всего написать парсер кода JavaScript на веб-сервере, который включается флагом времени выполнения («находится в режиме JS Diagnosti c»), который собирает все ответы JavaScript и изменяет код. соответственно. Но не требуется большого воображения, чтобы понять, насколько это может быть ошибочно и сложно.

ОБНОВЛЕНИЕ : просто чтобы уточнить, я не ищу решение, которое автоматически удаляет неиспользуемые функции, мне было бы неудобно с этим, из-за боязни внести нестабильность. Скорее, анализ использования функций во время разработки позволил бы мне выбрать, какие включают / функции для удаления, чтобы окончательное решение можно было должным образом протестировать перед выпуском.

1 Ответ

2 голосов
/ 16 июня 2020

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

Нет необходимости в sla sh в «сложно / невозможно». Устранение мертвого кода эквивалентно решению проблемы остановки и, таким образом, невозможно сразу, точка.

есть ли какие-либо инструменты или способы определения после периода использования веб-страницы, какие пользовательские функции (не встроенные) не были вызваны?

Это находится где-то между профилированием (определение того, какие части кода как часто выполнялись) и анализ покрытия (определение того, какие части кода были выполнены вообще). Точнее, похоже, что вы ищете покрытие функции .

Обратите внимание, что покрытие кода часто упоминается в контексте тестирования, так что для некоторых людей термин «код» покрытие »и« покрытие тестами »являются синонимами, но покрытие кода не имеет ничего общего с тестированием. Это просто относится к вопросу «когда я запускаю определенную c рабочую нагрузку, какие части кода выполняются?»

Существуют разные способы интерпретации термина «часть» в вопросе выше, и они порождают различные виды покрытия:

  • покрытие строки : какие строки выполняются?
  • покрытие функции : какие функции получают казнен? (Это тот, который вас интересует.)
  • покрытие операторов : какие операторы выполняются?
  • покрытие выражений : какие выражения выполняются ?
  • покрытие ветвей : какие ветви условного условия выполняются?
  • покрытие пути : какие пути через блок выполняются?

Покрытие строк обычно бесполезно, потому что вы можете изменить номер, просто переформатировав код. Фактически, в ECMAScript я всегда легко могу сделать так, чтобы все строки выполнялись, просто записывая все в одну строку.

Разницу между покрытием ветвей и покрытием пути можно проиллюстрировать следующим фрагментом кода:

function foo(bar, baz) {
  if (bar) {
    console.log("bar");
  } else {
    console.log("no bar");
  }

  if (baz) {
    console.log("baz");
  } else {
    console.log("no baz");
  }
}

Чтобы охватить все филиалы , мне нужно два звонков:

foo(true,  false);
foo(false, true);

Чтобы охватить все возможные пути через функцию, мне нужно четыре вызовов:

foo(true,  true);
foo(true,  false);
foo(false, true);
foo(false, false);

Если вы выполните heuristi c удаление мертвого кода на основе покрытия функции, вы сможете удалить неиспользуемые функции. Если вы сделаете это на основе покрытия веток, вы сможете даже удалить неиспользуемые ветки из операторов if или switch.

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

Насколько я понимаю. знаете, для этого нет существующих инструментов, хотя я могу ошибаться.

...