Яндекс.Метрика

    Песочница

    JavaScript: обработка include_once

    Как включить один JavaScript файл в другой? Как обозначить зависимости между кодом расположенным в разных JavaScript файлах? Решения для этих проблем давно известны. А почему бы не попробовать разобраться с этим на сервере?

    Проблема


    Из топика уже должно быть понятно, что речь пойдёт о JavaScript'е на Web-страницах. Вообще, как мне кажется, многие очень давно озабочены проблемой include'ов в JavaScript'е (например, тут и тут), хотя, может быть, я несколько преувеличиваю проблему.
    На моём счёту на данный момент всего одно приложение на PHP + (JavaScript + HTML), и где-то под конец его разработки меня совсем уже достали постоянное прописывание тегов <script> в заголовки страниц, запихивание кучи кода в один JavaScript файл и тому подобные вещи. Но чем мне больше всего не нравился такой подход, так это невозможностью обозначить зависимости между кодом, который находится в разных файлах.

    В идеале хочется иметь возможность написать в заголовке файла что-то вроде:

    import 'folder/file.js';

    Известные решения


    Из известных мне решений существуют, как минимум, возможность использовать ленивую загрузку или SSI и mod_include в Apache.

    Я не претендую на оригинальность, тем более аналогичный модуль я, кажется, встречал в составе какой-то библиотеки. Однако легко отыскать требуемую функциональность в виде отдельной библиотеки мне не удалось, хотя идея довольно простая и уже точно в голову пришла не мне одному. Поэтому, буду рад если в комментариях расскажут, почему так делать не надо.

    Альтернативный подход


    В общем, перейдём к сути. Все знают и активно используют CSS препроцессоры, часть из них разбирает исходный файл на сервере и клиент получает один готовый CSS файл. В таких препроцессорах, несомненно, существует возможность делать include других файлов. Я предлагаю использовать аналогичный подход и для JavaScript.

    Потратив немного времени, я получил модуль под название JsPPP (исходники и тесты можно найти на googlecode). Рассмотрим конечный вариант использования данного модуля.
    • Для начала необходимо скачать последнюю версию библиотеки.
    • Поместите содержимое архива в какой-нибудь каталог на сервере. Пусть для определённости это будет каталог jsppp в корневом каталоге.
    • Теперь осталось набрать в строке адреса вашего браузера что-то типа yourdomain.com/jsppp/js.php?test.js. Если вы увидели содержимое двух файлов – значит всё работает.

    Обратимся к файлу test.js:
    //#>import 'subdir/test2.js'
    
    function test1()
    {
        alert('test1');
    }
    

    Как вы уже догадались, код //#>import 'subdir/test2.js' подключает файл subdir/test2.js к файлу test.js при пропускании его через js.php. Последнее, что нужно знать чтобы воспользоваться этой функциональностью: в файле js.php легко обнаружить имя каталога, в котором находятся все JavaScript файлы проекта (т.е. тот, относительно которого будут искаться подключаемые файлы). Этот путь передаётся параметром в конструктор объекту JsPreprocessor. Его нужно исправить на тот, который вам нужен.

    Подключить JavaScript по старинке


    И так, файл js.php обрабатывает JavaScript файл и выдаёт один скомпонованный JavaScript со всем зависимостями. На всякий случай имеется дополнительная функциональность, которая позволяет по файлу с директивами в указанном выше формате получить набор <script src="..."></script>, для подключения всех файлов, от которых он зависит.
    Делается это вызовом функции GetScriptLinks:
    echo $preprocessor->GetScriptLinks("filename.js", "www_path_to_js_dir");
    


    Напоследок


    Разумеется, библиотека отмечена версией 0.1. Это означает, что если вдруг окажется, что всё это не полный бред, то можно сделать следующее:
    • Отработать кэш на сервере.
    • Отработать кэш для клиента (ETag, If-Modified) и редирект 301.
    • Подключить минимизатор.
    • Сделать вариант обработки директив через ленивую загрузку.