Еще один загрузчик скриптов для JavaScript

    При разработке одного сайта мне понадобился загрузчик скриптов, так как хотелось что бы загрузка вызывалась из js кода. Из готовых решений нашел requirejs и yepnope. Requirejs — модульный, что к моим требованиям не подходило. Yepnope — асинхронный, это означает, что код в каждом файле мне пришлось бы обертывать в callback функции. Ничего не оставалось, кроме как написать что-нибудь самому. И вот что у меня получилось: wakeloader — безмодульный синхронный загрузчик скриптов для JavaScript. В этой статье я расскажу про него.

    Инициализация


    В html код нужно добавить следующее:
    <script wake-loader src="/loader.min.js"></script> 
    

    Параметры


    В wakeloader несколько параметров загрузки, вот их перечень:
    string    main-file    путь к файлу с главным кодом (main.js) 
    string    main         имя функции, вызываемой после загрузки страницы
    string    update       при изменении, кеш очереди скриптов будет обновлен
    bool      quick        если true, то функция main будет вызвана по событию DOMContentLoaded, false - onload
    bool      cached       кешировать ли очередь скриптов
    object    alias        алиасы путей
    array     queue        очередь скриптов для загрузки   
    

    Параметры можно задавать двумя способами:

    1. С помощью создания объекта с параметрами


    <script>
        wakeloader = {
            mainFile :  "/app/main",
            main     :  "main",
            update   :  "04.04.2013",
            quick    :  true,
            cached   :  true,
            alias    :  { "http://code.jquery.com/" : "jquery/" },
            queue    :  ["/app/widget","jquery/jquery-2.0.2.min",{ "http://some.serv.er/lib/" : ["sugar","backbone"] }]
        };
    </script>
    <script wake-loader src="/loader.min.js"></script>
    

    2. Через атрибуты тега script


    <script wake-loader data-main-file="/app/main" data-main data-update="04.04.2013" 
            data-cached data-quick data-alias='{ "http://code.jquery.com/" : "jquery/" }' src="/loader.min.js">
        ["/app/widget","jquery/jquery-2.0.2.min",{ "http://some.serv.er/lib/" : ["sugar","backbone"] }]            
    </script>
    

    Очередь можно задать и через атрибут data-queue.

    Функции


    Wakeloader имеет всего две функции: это require и updateQueue.

    require загружает указанные вами скрипты, доступна в глобальном пространстве имен.
    require('jquery/jquery-1.10.1.min','/app/lastfm-api');
    

    После вызова функции updateQueue, при первом обновлении страницы, кеш очереди будет обновлен. Функция доступна только из объекта wakeloader.

    Как это работает


    Работает это все достаточно просто: достигнуть синхронность функции require можно было только одним способом — загрузка скриптов через XMLHttpRequest и помещение кода внутрь тегов . Если скрипт лежит на другом сервере, то указывайте его в очереди тега загрузчика.

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



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



    Дело в том что при включенном кешировании функция require еще и записывает очередь скриптов в localStorage, благодаря этому все последующие загрузки будут проходить очень быстро.


    Мне было интересно сравнить мой загрузчик с requirejs, для этого я обернул код скриптов в модули.



    На всех скриншотах видно колличтесво файлов и их размеры(они не минимизированы). В среднем получилось, что при данном наборе файлов скорость загрузки wakeloader c включенным кешированием - 700ms, скорость requirejs - 800ms.

    UPD: так же проверил на скорость requirejs, когда все скрипты прописаны в shim:



    Еще медленней чем модульная загрузка.

    Исходники на GitHub. Демо.
    P.S.: Скоро напишу php-cli скрипт для склеивания файлов, ссылка на него будет в описании wakeloader'a на github'e.

    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 16

      0
      еще есть github.com/ded/script.js, асинхронная загрузка, очередь и всякое такое
        0
        Очень вовремя. Завтра же применю его в рабочем проекте: )
        И предусмотрено всё, что бывает нужно в практических случаях.
          +3
          безмодульный синхронный загрузчик
          вы серьезно? И если да, то зачем?
            0
            Я серьезно.
            Yepnope — асинхронный, это означает, что код в каждом файле мне пришлось бы обертывать в callback функции.
              0
              Но ведь синхронная загрузка означает совершенно ненужные задержки и подвисание браузера на время этой операции.
                0
                Вы видимо пост невнимательно прочли.
                  0
                  Возможно. Я просто так и не понял, почему проще написать свой велосипед, чем взять проверенное решение и обернуть пару десятков файлов в модули.
                    0
                    Ну я могу привести один аргумент: скорость. Конечно тут идет счет на миллисекунды, но все же.
                    wakeloader сам по себе легче чем requirejs, грузится быстрее, и сама работа requirejs оказалась медленней чем моего загрузчика (смотрите скриншоты).
                      0
                      На девелоперской машине эти миллисекунды ничего не решают. А на продакшене пользователь все равно должен получать склеенные и сжатые скрипты.
                        0
                        Ну тогда уже это дело вкуса, кому что больше понравится.
                  0
                  Мой загрузчик никак не тормозит рендеринг браузера: после того как браузер загрузил и выполнил код загрузчика он идет дальше обрабатывать документ, загрузка остальных скриптов идет асинхронно(не тормозя рендеринг). Если тегу script добавить атрибут async то и загрузка и выполнение кода загрузчика не будет томрозить рендеринг.

                  Синхронность про которую я говорю — это синхронность в работе скрипта: пока функция require не загрузит скрипты(если скрипт загружен кешем то повторно скрипт не загружается), дальше выполнение кода не пойдет.
                    0
                    Простите, ваша терминология меня сбила с толку.
              0
              Вы бы хоть дали ссылку на демо.
              Интересно же посмотреть, как браузер встанет раком при синхронной загрузке кучки скриптов, например jQuery и пары десятков плагинов к нему.
              Вы достаточно элегантно решили проблему очередности загрузки скриптов — загружаете скрипты в цикле синхронно.
                0
                Ну давайте я чейчас демку сделаю а вы протестируете, договорились?
                  0
                  0
                  Для себя сделал свой велосипед: gist.github.com/Rulexec/5719946

                  Правда это совсем не загрузчик, всё равно просто пихаю кучу script-тегов в head. Ну и лишние две строки в каждом файле в начале и конце. Впрочем, если взглянуть на node.js, оно там реализовано так же (например, если попытаться запустить что-нибудь инвалидное на первой строке можно получить:

                  <code>ruliov@ruliov-laptop:/tmp$ echo glitch > test.js
                  ruliov@ruliov-laptop:/tmp$ node test.js
                  
                  /tmp/test.js:1
                  (function (exports, require, module, __filename, __dirname) { glitch</code>

                  В теории в среде node.js, а не браузера смогу определить глобальный Module и подпихивать туда настоящие module, exports, require и получить код, который и там и там работает. Да, я знаю, что уже есть такие решения, но не вижу проблем в своём. Потом можно будет просто склеить все подключенные скрипты в один и всё так же будет работать.

                  Only users with full accounts can post comments. Log in, please.