Запретить компилятору закрытия дублировать строку

#javascript #google-closure-compiler

#javascript #google-closure-compiler

Вопрос:

Я использую компилятор закрытия Google для сокращения моего JS. В моем коде есть несколько мест, где у меня есть повторяющаяся строка, например

 (function($){


$('.bat').append('<p>the red car has a fantastically wonderfully awe inspiringly world class engine</p><p>the blue car has a fantastically wonderfully awe inspiringly world class stereo</p><p>the green car has a fantastically wonderfully awe inspiringly world class horn</p>')

})(jQuery);
  

Компилятор не минимизировал эту избыточность (как и следовало ожидать), поэтому я сделал это сам в «предварительно скомпилированном» коде:

 (function($){

   var ch = ' car has a fantastically wonderfully awe inspiringly world class ';
   $('.bat').append('<p>the red' ch 'engine</p><p>the blue' ch 'stereo</p><p>the green' ch 'horn</p>')

})(jQuery);
  

Но когда я запускаю это через компилятор, он отменяет мое сжатие, что приводит к увеличению количества символов. Он выводит:

 (function(a){a(".bat").append("<p>the red car has a fantastically wonderfully awe inspiringly world class engine</p><p>the blue car has a fantastically wonderfully awe inspiringly world class stereo</p><p>the green car has a fantastically wonderfully awe inspiringly world class horn</p>")})(jQuery);
  

Есть ли способ предотвратить это? Есть идеи, почему это делается? Является ли это улучшением производительности во время выполнения?

Спасибо

Комментарии:

1. AFAIK, Закрытие — это правильное решение. Переменная ch не используется снаружи, и это экономит байты (и повышает производительность) за счет ее встраивания. Ваш способ сделать это, похоже, не является каким-либо решением для избежания «повторяющихся строк». Кроме того, имейте в виду, что, хотя повторяющиеся строки выглядят неэффективными в хранилище, они не влияют на сжатый размер.

Ответ №1:

Это поведение задокументировано здесь:

https://github.com/google/closure-compiler/wiki/FAQ#closure-compiler-inlined-all-my-strings-which-made-my-code-size-bigger-why-did-it-do-that

Однако один из подходов, который я использовал, чтобы избежать добавления очень большой строки, которую стоит дедуплицировать, — это обернуть значение в функцию:

const getCssStyleSheetText = () => "...";

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

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