Оптимизация JavaScript для ускорения загрузки веб-страниц

    Инженер из компании Google, автор трёх книг по веб-производительности и оптимизации, Стив Содерс (Steve Souders) опубликовал презентацию "JavaScript Perfomance" о том, какие методы нужно применять, чтобы скрипты меньше тормозили загрузку страниц.

    По статистике WebPagetest, блокировка загрузки файлов .js на сайтах из Alexa Top 100 снижает среднее по медиане время загрузки страницы c 3,65 с до 2,487 с, то есть на 31%. Если вы видите медленную загрузку веб-страниц и хотите улучшить этот показатель, то, по мнению Стива Содерса, первым делом нужно посмотреть на JavaScript.

    В качестве примера оптимизации Стив Содерс приводит сниппет Google Analytics.

    var ga = document.createElement(‘script’);
    ga.type = ‘text/javascript’;
    ga.async = true;
    ga.src = (‘https:’ == document.location.protocol ? ‘https://ssl’ : ‘http://www’) + ‘.google-analytics.com/ga.js’;
    var s = document.getElementsByTagName(‘script’)[0];
    s.parentNode.insertBefore(ga, s);

    Особое внимание он обращает на строчку

    ga.async = true;

    Этот параметр означает, что скрипт ga.js не будет блокировать исполнение других асинхронных скриптов.

    Ещё один момент — инструкция insertBefore. Оказывается, некоторые браузеры блокируют выполнение скриптов, если ещё не загружен скрипт с инструкцией insertBefore. Естественно, это замедляет загрузку страницы. Другими словами, такие браузеры будут ждать, пока на странице не загрузится модуль Google Analytics, и до этого момента все остальные скрипты блокируются. Параметр ga.async = true исправляет ситуацию во многих современных браузерах. Но не во всех.

    Стив Содерс сделал специальную страничку, чтобы выявить те версии браузеров, которые игнорируют инструкцию ga.async = true при наличии insertBefore. Он собрал статистику с 60+ различных браузеров — как видно в таблице по ссылке, главным «нарушителем» является браузер Opera. Запустить тест и провериться можно здесь.

    В презентации "JavaScript Perfomance" Стив Содерс говорит о модуле для ускорения загрузки скриптов ControlJS, а также об использовании localStorage в качестве кэша.

    Поддержать автора
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

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

      0
      А я вот пользую code.google.com/p/extsrcjs/
      Жаль разавитие проекта остановилось.
        +4
        Еще один вариант — это yepnope.js, асинхроная загрузка вообще любого контента, в том числе css и скриптов. Кстати входит в состав Modernizr.
          –1
          Opera — удобный с точки зрения пользовательского интерфейса и очень быстрый браузер. Когда-то даже команда разработки Opera позиционировала его как самый продвинутый с точки зрения поддержки новых веб-стандартов (возможно, и сейчас так позиционируют). Но, к сожалению, куча таких вот мелочей, когда не поддерживаются маленькие фишки, которые уже поддерживаются и хромом и фаерфоксом, очень расстраивает!
          • НЛО прилетело и опубликовало эту надпись здесь
              +4
              Пятый слайд презентации очень хорош.
                +6
                > Инженер из компании Google
                Как бы его познакомить с разработчиками Google Sites из той же компании… :)
                  –1
                  Спасибо, о нагрузке на сервер задумывался, а вот про клиент частенько забывал. Пошёл апдейтить скрипты.
                    +12
                    Даже если вы сделаете один монолитный файл или он надежно закэшируется, то у вас останется еще одна весомая проблема, которая становится более актуальна сегодня(вес скриптов увеличивается, скорость сети увеличивается) — инициализация скрипта aka Startup Latency. Данная проблема такая же актуальная как и тормоза при старте Java-приложений.

                    Сравним: 1Мб JavaScript на локалхосте загружается за 32мс и меньше. В iOS Safari 4 он инициализируется за 3500мс!!!, а в Firefox 9 — около 600мс. Даже если мы эти 32мс превратим в 0, то как избавится от 600-3500мс?! Сейчас не существует нативных средств (JavaScript/DOM) устранить эту проблему и это физически невозможно для JavaScript (его классы функции не декларативны — требуют инициализации) дамп памяти(Image) тоже, в принципе, невозможен.

                    Есть способ уменьшить Startup Latency(да, как всегда, костыли):
                    1. Загружать и инициализировать модули по необходимости(так работает gmail) — асинхронные модули+кэш
                    2. Загружать все, а потом инициализировать модули по необходимости(так работает lmd) — синхронный способ как в Node.js
                    Еще раз повторю — это костыль. Например в Dart такой проблемы нет.

                    Почитать:
                    www.nczonline.net/blog/2011/02/14/separating-javascript-download-and-execution/
                    googlecode.blogspot.com/2009/09/gmail-for-mobile-html5-series-reducing.html
                    calendar.perfplanet.com/2011/lazy-evaluation-of-commonjs-modules/
                    github.com/azproduction/lmd
                      0
                      Еще вариант — это как сделанно в GWT с их code splitting: при разработке отдельные приложение разбивается на «куски», которые подгружаются (включая парсинг) уже по мере необходимости (т.е при необходимости показатьк какой-то виджет) автоматически.

                      Довольно неплохое решение для быстрого startup приложения, хотя из-за того что анализ зависимостей автоматический, иногда не так хорошо сплитится как хотелось.
                      • НЛО прилетело и опубликовало эту надпись здесь
                          0
                          LMD и AMD — одно лицо, только в LMD нет define, все модули локальны и инициализируются по требованию.

                          Немного о истории LMD.
                          Сначала я решил пропатчить require.js, добавив отложенную инициализацию, но покопавшись в кода и поняв, что там много чего лишнего и понял, что лучше начать с нуля (так, собственно, и делаются все велосипеды).
                          require.js — огромный кусок кода, который чинит косяки многих браузеров по асинхронной загрузке различных ресурсов и предоставляет перегруженный интерфейс — зачем все это, если можно собрать скриптовый пакет и работать с модулями как в Node.js, используя только require()? LMD около 300 байт клиентского скрипта.

                          Собирать все модули в одну кучу с первого взгляда кажется плохо — зачем мне загружать скрипты для блока «ололо» если пользователь этот блок не увидит — уж лучше я сэкономлю 10кб трафика пользователя, сделаю 50 запросов вместо одного и помучаюсь с асинхронными модулями и неработающими блоками в оффлайн режиме! (тут я не говорю о сборке в пакет сторонних библиотек)

                          Зачем все это, если все модули можно так или иначе закэшировать, пользователь рано ли и поздно воспользуется блоком «ололо», мы сокращаем количество запросов до минимума и работаем с модулями в привычном и удобном для нас синхронном виде(node.js).

                          Это плюсы LMD по сравнению с require.js
                          • НЛО прилетело и опубликовало эту надпись здесь

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

                      Самое читаемое