Скрипты и стили плагинов в HEAD. Оптимизация

6

Товарищи разработчики!

Пожалуйста помещайте все любые куски кода javascript и css в отдельные файлы. Вместо использования <style> и <script>

И для вывода прописывайте ссылки для скриптов и css:

<link href="/wa-apps/shop/plugins/MYPLUGIN/css/FILENAME.css?{$wa->version()}" rel="stylesheet">

<script src="/wa-apps/shop/plugins/MYPLUGIN/js/FILENAME.js?{$wa->version()}"></script>

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

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

22 комментария

  • +4
    Евгений Леман Евгений Леман 8 декабря 2016 10:34 #

    Дитя google pagespeed

  • +1
    Алексей Алексей Webasyst 8 декабря 2016 10:29 #
    все любые куски кода javascript и css в отдельные файлы.

    Это сильно категорично. Иногда удобнее и правильнее все же использовать inline вставку, чем делать лишние запросы.
    Тем более это влечёт с собой дополнительные ограничение в виде того, что во внешних файлах не используются smarty.

    • +1
      Genasyst Genasyst 14 декабря 2016 13:52 #

      Да с любыми кусками я погорячился)

    • +1
      Syrnik.com Syrnik.com 15 марта 2017 15:55 #

      И это опять не 100%. При использовании HTTP/2 выгоднее разбить на много мелких файлов %)

    • +1
      Евгений Леман Евгений Леман 13 декабря 2016 17:09 #

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

      А вообще странный подход. Винить продажные темы/плагины широкого потребления в том, что они в вашем персональном случае имеют лишний код. Не подходит - пишите своё.

      • +1
        info@ravencode.ru info@ravencode.ru 13 декабря 2016 18:25 #

        он уже написал как - генерировать js\css файлы

      • +1
        Genasyst Genasyst 13 декабря 2016 18:48 #

        Что же касается js/сss генерируемых, то можно компилировать файлы, сохранять и отдавать как файл! Это конечно не подходит для тем, но для плагинов самое оптимальное решение!

        • +1
          Евгений Леман Евгений Леман 14 декабря 2016 10:03 #

          И в этом способе я тоже могу найти ряд проблем. Но начнем с другого. А хочется ли разработчикам плагинов, которые стоят копейки, так заморачиваться?

          Автору стоит понять, что товары широкого потребления предназначены для других целей. А еще вам, Гена, стоит получше изучить тему оптимизации. Расскажите чем плох JS в шаблоне? Только лишь тем, что зрительно картина не соответствует тому, чему учат в школе. Только клиенты туда не смотрят. А вот лишний файлик = лишний http-запрос. Об этом не написано в "оптимизация для чайников". Но во многих случаях вынос js в саму страницу является более профитным, чем подключение десятка файлов.

          • +1
            Genasyst Genasyst 14 декабря 2016 12:54 #

            Так! Вот явный пример: Плагин Обратный звонок

            Вот строки которые подключают файл js :

            <script type="text/javascript">
            		{include file="../js/callb.frontend.js"}
            	</script>

            Вот код самого файла js/callb.frontend.js


            /**
             * callb.frontend.js
             * Module callbFrontend
             */
            
            /*global $, callbFrontend */
            
            var callbFrontend = (function () { "use strict";
            	//---------------- BEGIN MODULE SCOPE VARIABLES ---------------
            	var
            		onIdinhtmlClick, removeCallbForm, onFormSubmit, initModule;
            	//----------------- END MODULE SCOPE VARIABLES ----------------
            
            	//--------------------- BEGIN DOM METHODS ---------------------
            	removeCallbForm = function () {
            		$('.call-b-bg, .call-b-form').remove();
            	};
            	//--------------------- END DOM METHODS -----------------------
            
            	//------------------- BEGIN EVENT HANDLERS --------------------
            	onIdinhtmlClick = function (event) {
            		event.preventDefault();
            
            		removeCallbForm();
            
            		var bg = $('<div/>');
            		var form = $('<form />');
            		var formTop = $(document).scrollTop() + $(window).height()/2 - '{$callb_settings.style_form_height}'/2;
            		var callbCommentStatus = "{if isset($callb_settings.comment_status)}{$callb_settings.comment_status}{/if}";
            
            		bg.addClass('call-b-bg').css('height', ($(document).height())+'px');
            		form.addClass('call-b-form').css({
            			'background': '#{$callb_settings.style_form_background}',
            			'height': '{$callb_settings.style_form_height}px',
            			'width': '{$callb_settings.style_form_width}px',
            			'top' : formTop+'px'
            		}).prepend(
            			'<div class="call-b-header" style="background: #{$callb_settings.style_header_background}; color: #{$callb_settings.style_header_text_color};">{$callb_settings.text_header_title}<span id="call-b-close-x">x</span></div>' +
            			'<div class="call-b-input"><input type="text" name="callb-name" placeholder="{$callb_settings.text_name_placeholder}" value="" /></div>' +
            			'<div class="call-b-input"><input type="text" name="callb-phone" placeholder="{$callb_settings.text_phone_placeholder}" value="" /></div>' +
                        '<div class="call-b-input"><textarea name="comment" placeholder="{$callb_settings.text_comment_placeholder}"></textarea></div>' +
            			'<div class="call-b-input"><input id="call-b-submit" type="submit" value="{$callb_settings.text_submit_button}" style="background: #{$callb_settings.style_submit_background}; color: #{$callb_settings.style_submit_text_color}; height: {$callb_settings.style_submit_height}px; width: {$callb_settings.style_submit_width}px" /></div>'
            		);
            
            		$('body').prepend(form).prepend(bg);
            
            		$('.call-b-form input[name="callb-name"]').focus();
            
            		{if isset($callb_settings.phone_masked_input) && strlen($callb_settings.phone_masked_input) > 0}
            		$('.call-b-form input[name="callb-phone"]').mask('{$callb_settings.phone_masked_input}');
            		{/if}
            
                    if (callbCommentStatus !== 'on') {
                        $('textarea[name="comment"]').parent('.call-b-input').hide();
                    }
            	};
            
            	onFormSubmit = function (event) {
            		event.preventDefault();
            
            		var n = $('.call-b-input').find('input[name="callb-name"]').val();
            		var p = $('.call-b-input').find('input[name="callb-phone"]').val();
            		var c = $('.call-b-input').find('textarea[name="comment"]').val();
            		var err = $('<div/>');
            		var currentUrl = window.location.href;
            
            		$('.call-b-error').remove();
            		$('.call-b-input').find('input[name="callb-name"], input[name="callb-phone"]').removeClass('call-b-inp-err');
            
            		if ( n.length > 0 && p.length > 0 ) {
            			$.post("{$callback_url}", { "name": n, "phone": p, "comment": c, "url": currentUrl }, function (response) {
            				if (response.data.status === true) {
            					$('.call-b-input').remove();
            					$('.call-b-form').append(
            						'<p class="call-b-ok" style="color: #{$callb_settings.style_thanks_text_color};">{$callb_settings.text_thanks_message} ' + response.data.name + ',</p>' +
            						'<p class="call-b-ok" style="color: #{$callb_settings.style_thanks_text_color};">{$callb_settings.text_more_thanks_message}</p>' +
            						'<div class="call-b-input"><input id="call-b-close" type="button" value=\"{_wp("Close")}\" style="background: #{$callb_settings.style_close_ok_background}; height: {$callb_settings.style_submit_height}px; width: {$callb_settings.style_submit_width}px;" /></div>'
            					);
            				} else {
            					$('.call-b-input').remove();
            					$('.call-b-form').append(
            						'<p class="call-b-ok margins">{_wp("Error occurred when sending message")}</p>' +
            						'<div class="call-b-input"><input class="call-b-close-error" id="call-b-close" type="button" value=\"{_wp("Close")}\" style="background: #{$callb_settings.style_close_error_background}; height: {$callb_settings.style_submit_height}px; width: {$callb_settings.style_submit_width}px;" /></div>'
            					);
            				}
            			}, "json");
            		} else {
            			if ( !(n.length > 0) ) {
            				$('.call-b-input').find('input[name="callb-name"]').focus();
            			} else if ( !(p.length > 0) ) {
            				$('.call-b-input').find('input[name="callb-phone"]').focus();
            			}
            			if ( !(n.length > 0) ) {
            				$('.call-b-input').find('input[name="callb-name"]').addClass('call-b-inp-err');
            			}
            			if ( !(p.length > 0) ) {
            				$('.call-b-input').find('input[name="callb-phone"]').addClass('call-b-inp-err');
            			}
            			err.addClass('call-b-error').text("{_wp('Complete «Name» and «Phone»')}");
            			$('.call-b-form').append( err );
            		}
            	};
            	//------------------- END EVENT HANDLERS ----------------------
            
            	//------------------- BEGIN PUBLIC METHODS --------------------
            	initModule = function () {		
            		$(document).on('click', '{$callb_settings.id_in_html}', onIdinhtmlClick);
            
            		$(document).on('click', '.call-b-bg, #call-b-close-x, #call-b-close', removeCallbForm);
            
            		$(document).keyup(function(event) {
            			if (event.keyCode == 27) { // close callb form when esc key is pressed
            				removeCallbForm();
            			}
            		});
            
            		$(document).on('submit', '.call-b-form', onFormSubmit);
            	};
            
            	return {
            		initModule: initModule
            	};
            	//------------------- END PUBLIC METHODS ----------------------
            }());

            Это идет в head страницы и каждый раз компилируется через смарти!!!!!


            Посмотрев переменные которые передаются и используются для компиляции данного js, понятно что туда передаются только массив настроек $callb_settings.

            Так почему бы не сделать объект


            $.callb = {
            
            settings:{},
            
            init:function(settings) {
            
            this.settings = settings;
            
            }
            
            ///тут методы
            
            };

            А в шаблон передавать только массив json

            <script type="text/javascript" src="{$wa_url}wa-apps/shop/plugins/callb/js/callb_frontend.js"></script>
            <script type="text/javascript">
            	$.callb.init({json_encode($callb_settings)})
            </script>

            Что вы скажете про данный случай?

            1. В моей реализации передается только Json массив

            2. код скрипта будет зfпрошен один раз (далее будет из кеша браться)

            3. никакой лишней компиляции через PHP

            4. вполне удобно читаемый код Js


            • +1
              Syrnik.com Syrnik.com 15 марта 2017 15:59 #

              Про этот конкретный случай скажу, что автор погорячился.

              И что ему вправду стоит попробовать почитать документацию по написанию jQ-плагинов

              Потом подумать и переписать это без jQ совсем. %)

            • +1
              Genasyst Genasyst 14 декабря 2016 13:22 #

              Кстати именно из-за этого плагина я и создал тему((((

              Когда один такой плагин вроде бы ничего страшного, а когда таких будет установлено 30?!!!

              Давайте посчитаем


              <script type="text/javascript">
              		{$start = microtime(true)}
              		{for $i = 0 to 30}
              		{include file="../js/callb.frontend.js"}
              		{/for}
              		{$all_time = microtime(true) - $start}
              
              	</script>
              	<!-- {$all_time} -->

              компиляция занимает 0.012 сек

              компилированный код таких 30 скриптов весит 164kb

              + это все надо отдать браузеру вывод



            • 0
              Genasyst Genasyst 8 декабря 2016 10:57 #

              я не дитя гугл спид. Просто столкнулся с проблемой на одном сайте, там во первых сама тема генерит css цвета через смарти , а еще там стоит четверть всех плагинов. Код head превращается в индусский код! Хотя половина кода могла бы находится в файлах. Да действительно бывают случаи когда надо передать переменную смарти в javascript, я для этого использую json обьект. Что же касается сss, то можно компилировать файлы, сохранять и отдавать как файл

              • +1
                info@ravencode.ru info@ravencode.ru 12 декабря 2016 17:28 #

                50% виденных мной плагинов представляют собой лапшу из серии "х..як, х..як и в продакшн")) да и если говорить о частной разработке, то всем подавай подешевле, вот в итоге и получается подобный говнокод (хотя им и сама WA постоянно грешит - т.ч. понятно откуда сторонние разработчики черпают "вдохновение"). Также согласен с замечанием Евгения.

                • +2
                  Genasyst Genasyst 12 декабря 2016 19:09 #

                  Да! поддерживаю!!!!

                  Проблема в общем-то не особо из-за javascript, а из-за дополнительных запросов в бд плагинами по каждому пуку! многие плагины делают свои выводы через методы хелперов да еще и без хранения дополнительной информации в статических переменных(например массив данных самой категории) и при каждом запросе метода хелпера для получения информации о товаре, которых для показа 50, заново запрашивается инфа текущей категории ( это как пример), а особенно это сказывается на производительности при показе товаров категории!

                  Также создание объектов моделей можно также заносить в пул!

                  Вот простой код хранения моделей плагина:

                  <?php
                  
                  class shopMyPluginModels  {
                  
                      protected static $models = array();
                  
                      public static function get($name) {
                          if(isset(self::$models[strtolower($name)])) {
                              return self::$models[strtolower($name)];
                          } else {
                              $class_name = 'shopMyPlugin'.ucfirst($name).'Model';
                              if(class_exists($class_name)) {
                                  self::$models[strtolower($name)] = new $class_name();
                                  return self::$models[strtolower($name)];
                              }
                              return null;
                          }
                      }
                  }
                  • +1
                    info@ravencode.ru info@ravencode.ru 12 декабря 2016 22:05 #

                    Проще тогда уж singleton использовать.

                    • +1
                      Genasyst Genasyst 13 декабря 2016 00:36 #

                      Мне не проще) Проще пул одиночек! Мне не надо знать является ли объект одиночкой или нет, мне без разницы, я получу все равно копию нужного мне объекта не зависимо от его реализации) Можно еще проверять является ли класс одиночкой и его тогда загружать через метод

                    • +1
                      Syrnik.com Syrnik.com 15 марта 2017 16:00 #

                      Это и есть синглтон. Если присмотреться %)

                      Ну, фабричный метод с кэшем и синглтонами :D

                      • +1
                        Genasyst Genasyst 15 марта 2017 16:08 #

                        Отличие синглтона от статики для использования в WA в том что в смарти нельзя инициализировать классы через new, поэтому синглтон это как защита от использования класса в шаблоне.

                        Добавить комментарий

                        Чтобы добавить комментарий, зарегистрируйтесь или войдите