Запускаем jQuery на движке Node.js вместо браузера

  • Tutorial
Библиотека jQuery — это общепризнанное средство манипуляции сразу несколькими форматами данных (XML, HTML, объекты DOM, обыкновенные объекты), да притом работающее посредством удобного (цепного) вызова методов с удобными (краткими) названиями. Поэтому ничуть не удивляют попытки приспособить jQuery не только к одному клиентскому, но также ещё и к серверному джаваскрипту — в частности, к Node.js.

Признаюсь честно, что когда разработчики jQuery превозмогли проблему №7102, то её название («Register jQuery as a CommonJS async module») на какое-то время даже заставило меня обмануться: я сперва подумал было, что и в Node.js (так как модули Node.js и СommonJS имеют немало общего) отныне jQuery станет работать невозбранно. Ан нет, не тут-то было. Пристальное вглядывание в коммит и в запрос на слияние позволяет осознать, что jQuery, в сущности, обрёл возможность регистрироваться только как AMD-модуль и даже проверяет свойства define.amd и define.amd.jQuery перед саморегистрацией.

Собственно говоря, архитектура jQuery «затóчена» под употребление в условиях браузерной DOM: код jQuery полагается на существование объекта window, который служит аргументом главного замыкания, окаймляющего весь код jQuery. Прежде же таких неявных предположений было ещё больше, и только с устранением проблемы №6690 библиотека jQuery перестала полагаться на существование глобальных объектов navigator и location, начав вместо того получать их как свойства объекта window. (Понятно, что такое предположение никак не подходило для Node.js, где глобальные объекты служат свойствами объекта global, а вовсе не window; а равно не подходило и ко многим прочим реализациям CommonJS.)

Потому для запуска jQuery в Node.js применяются готовые реализации браузерной DOM — такие, как пакет jsdom, на основе которого невозбранно работает, например, вот какой код, предлагаемый в качестве примера:

// Print all of the news items on hackernews
var jsdom  = require('jsdom');
var fs     = require('fs');
var jquery = fs.readFileSync("./jquery-1.6.2.min.js").toString();

jsdom.env({
   html: 'http://news.ycombinator.com/',
   src: [
      jquery
   ],
   done: function(errors, window) {
      var $ = window.$;
      console.log('HN Links');
      $('td.title:not(:last) a').each(function() {
         console.log(' -', $(this).text());
      });
   }
});

А на jsdom, в свою очередь, основан пакет node-jQuery, отличающийся дополнительными обёртками из синтаксического сахара.

Другого метода, другого подхода к этой задаче нет, да пока что и быть не может.

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

    –7
    слово «невозбранно» глаз сразу цепляет. Вы его в жизни используете, или это переводчик? (Это не издевка, просто интересно)
      +25
      Я его в жизни использую.
        +3
        причем наверняка невозбранно.
        +2
        Вы просто недавно на хабре :) Почитайте топики этого автора и глаз у вас будет дергаться еще пару дней.

        пы.сы. Мицгол, не осуждаю, просто человек чувствительный.
        +2
        У меня дежавю: сначала был Java — язык, применявшийся в Вебе для серверной логики (сервлеты и прочее), а потом его допилили, чтобы иметь возможность применять на клиентской стороне и получился Google Web Toolkit. С Javascript все наоборот: изначально позиционировался как чисто клиентский язык, но потом Райан Дал и разработчики V8 сделали возможным выполнение Javascript на сервере. GWT объективно не нашел большого распространения. Интересно посмотреть получится ли у Javascript.
          +3
          В настоящее время будущее Node.js ещё не достаточно лучезарно, поскольку ещё только ≈1½ месяца этот движок существует не только под Linux, под Mac и под Соляркою, но также и под Windows.

          Следует ожидать мощного синергического толчка в тот момент, когда код модулей для Node.js начнут сочинять также и те разработчики на JavaScript, у которых на рабочем компьютере стоит Windows. По моим оценкам, для этого не достаточно портировать на Windows один только сам движок Node.js; потребуется также, по меньшей мере, вот что:
          • Плавная работа пакетного менеджера npm. В частности, будет необыкновенном полезным появление у разработчиков модулей возможности поставлять заранее скомпилированные модули для win32 и win64: нельзя же полагаться на то, что у каждого конечного пользователя стоят средства разработки (например, Visual Studio 2010 Express). Понятно, что и разработчики модулей должны взяться за ум, а не то даже команду npm install zip нельзя под Windows подать без того, чтобы наткнуться на симлинк внутри тарболла. (Или автор скрипта npm/lib/utils/tar.js мог бы получше предусмотреть это.)
             
          • Появление возможности оскриптовывания произвольной системной библиотеки. (Появится, вероятно, после портирования node-ffi на Windows.) Только отсюда протянется тропка к сотворению GUI.
             
          • Появление возможности работать с БД файлового (а не клиент-серверного) типа. (Появится, вероятно, после портирования node-sqlite3 на Windows.)
            0
            Впрочем, быть может, Node.js и не нуждается в GUI, если вебоинтерфейса будет достаточно.
              –2
              Святые котята. Как это вы не заменили GUI на, что-то родное?
          +2
          Я ковырял jsdom какое-то время назад, пытался заставить работать кое-какие готовые скрипты на стороне сервера, и уперся в некоторые отличия в реализации jsdom и браузерного DOM. В итоге код не заработал, от идеи я отказался.
            0
            А какие задачи нужно было решать на сервере чтобы там потребовались DOM дерево?
              0
              Не вдаваясь в подробности, мне нужен был контент парсер типа Readability — www.readability.com/
            +4
            А скажите мне, зачем нужен jQuery внутри Node.js?
              –1
              Ответом на этот вопрос, собственно говоря, начинается моя блогозапись.
                +4
                Меня именно это и удивило: XML, HTML, объекты DOM, обыкновенные объекты — 3 пункта из 4 требуют DOM-движка, а для последнего есть undescore.js, у которого и вызовы «удобные», и к node.js подключается легко и без дополнительных телодвижений, и функций по-боле, чем у jQuery.
                  +1
                  Ну, разве я стану оспаривать достоинства underscore? Библиотека underscore в рейтинге npm не зря занимает первое место в номинации «пакет, на котором основано больше всего других пакетов»: это удобное, а иногда и незаменимое средство. Использовать jQuery вместе (а подчас и вместо) underscore понадобится только тогда, когда прежде всего нужно поработать с XML и (или) HTML.
              +1
              Просто шикарно, спасибо. Для парсинга это просто незаменимая связка получается. Красота кода от jQuery + скорость от node.
                0
                Использую данный метод, наблюдаются утечки памяти.

                Баг на jsodom. В частности при вызове window.close() который должен освобождать память — происходит весьма таки fatal error.

                Есть идеи?
                  0
                  Хотя нет, приведенный способ работает как часы. Глючил jquery.create(window);
                    0
                    При должном тестировании все-таки утечка возникает. Даже если window.close() работает без ошибки. А для веб сервера это недопустимо.

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

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