Хватит использовать jQuery, вы способны сделать лучше без него

    Введение


    Наверное вам уже приходилось слышать замечания такого рода и скорее всего вы чувствуете себя вполне вольготно используя jQuery. Тогда вы спрашиваете себя почему на свете есть такие лунатики которые так ненавидят такую прекрасную и пушистую библиотеку и какого нафиг черта я должен прекратит ей пользоваться. Вы наверное будете удивлены узнать что делу тут вовсе не в ненависти. Давайте разберемся в ситуации.



    Как и множество других разработчиков, я начал использовать jQuery во времена поздней бронзовой эры (2007), когда различия между браузерами были просто занозой в пятке и нехватка общих стандартов была так ненавистна. jQuery был, своего рода, источником вдохновения и лучиком света в эти темные времена, он был революционным. Я влюбился в jQuery как только я начал им пользоваться. Я написал несколько ярких и пушистых расширений для jQuery а так же я хотел поделиться со всеми благой вестью и выступил пару раз с докладом о нем и даже организовал небольшой тренинг для ознакомления команд с этим продуктом. Но затем, несколько лет назад я изменил мое мнение.

    Давайте детально рассмотрим что не так с использованием jQuery в современной web-разработке и как мы можем это исправить.

    Униформизатор


    Одна из потрясающих киллер-фич JQuery была способность сглаживать а иногда и восполнять различия в работе с DOM в различных браузерах и их версиях. Но давайте посмотрим правде в глаза, с тех самых пор много чего поменялось, появилось множество современных стандартов. В большинстве своем jQuery в лучшем случае перенаправляет вызов стандартных API DOM, а в худшем случае использует свою собственную реализацию той или иной фичи. В современном мире можно лего обойтись без использования селекторов и утилит jQuery. Можно легко заменить селектор типа:

    $('div, span, article');
    $('#formId :invalid');
    

    на:
    document.querySelectorAll('div, span, article');
    document.querySelectorAll('#formId :invalid');
    

    Ну или на пример утилиты типа:
    $.isArray(array1);
    $.each(array, function(i, v) {
      // do something here
    });
    

    легко заменяются на:
    Array.isArray(array1);
    array1.forEach(function(v, i) {
      // do something here
    }
    


    Лично я предпочитаю всегда держатся стандартов, jQuery не стандарт это просто библиотека.

    Объект обертка


    Как вы наверное знаете, jQuery после почти всех своих манипуляций возвращает вам специальный объект в который заворачивается или нет определенный результат или его отсутствие. Например *$('span')* вернет вам такой объект. Мало того что объект обертка имеет свои собственные доморощенные методы, отличные от общепринятых стандартов, но это еще вам не гарантирует что внутри методов jQuery будет использовать только обертки. Это далеко не так, чем будет *this* в функции обработчика события или чем будет первый аргумент такой функции или значение его специального поля *target*? Небольшой пример:

    $('button').bind('click', function(e){
      var el = this; // Is it jQuery "object" or not ? Let's see the doc
      var event = e; // Is it jQuery "object" ? No, it's a special event-wrapper object
      var target = event.target; // Is it jQuery "object" ? Sure not, it's a simple DOM element
    });
    

    И так, иногда обертка, иногда нет, а иногда специальная обертка, что это вообще такое, зачем нам нужно так усложнять себе жизнь? Но есть же костыль, скажете вы, как насчет конвенции когда все «спец объекты» jQuery начинаются на знак $. Что-то вроде:

    $('button').bind('click', function(e){
      var $el = $(this);
      var _event = e; // Let's use an another special convention for jQuery's events wrapper, prefix _
      var $event = e; // No, we should be coherent
      var target = $(event.target); // I'm sorry I forgot the dollar, because I'm just a human
      var target2 = $(target); // Oups, but I have to be sure that it's wrapped
      var var1 = someFunc(); // I forgot, this function should return $ or simple NodeList
      $(var1); // Nevermind ...
    });
    


    JQuery как эталон web-разработки


    Я много раз слышал такое мнение что jQuery это своего рода эталон веб-разработки, если вы занимаетесь этим значит вы просто обязаны использовать jQuery что бы добиться успеха, потому что он хорош, у него есть яйца и у него куча таких пушистых и ламповых плагинов. По мне так это все фигня, это было от части верно лет 5 назад но не сейчас. Это все равно что говорить что для того что бы разрабатывать современные приложения Windows 8/10 вам нужно обязательно использовать Win32 API в чистом виде.

    Как я уже сказал выше, jQuery это всего навсего библиотека, и по сегодняшним меркам библиотека низкого уровня. А вещи такого рода не подходят для написание современных веб приложений. Ничего не мешает вам использовать jQuery или чистый стандарт DOM/API для реализации той или иной низкоуровневой задачи, но писать все приложение а потом еще и поддерживать его очень тяжело. Я видел кучу больших проектов которые превращались в одно большое блюдо спагетти на клиентской стороне, где jQuery не был корнем зла, просто люди не смогли справиться с наплывом кода.

    Как можно этого избежать? Используйте более подходящие для этого решения там где они действительно нужны, будь то MV* или что-то другое.

    Тестирование


    Эта часть неразрывна связанна с предыдущей. Как мы все знаем — человек ленив по своей природе а хорошие программисты-автоматизаторы часто бывают ленивы. Вы когда-нибудь тестировали код использующий jQuery, из-за цепочек вызовов это нетривиальная задача. А если брать во внимание тот факт что часто проекты с использованием jQuery набирают вес так стремительно что разработчики не успевают, не хотят или не могут реорганизовать свой код. Результат получается неутешительный, как можно говорить о тестировании когда даже автор кода не в силах понять что этот код делает.

    В MV* подходе это решается намного легче.

    Итог


    Если вас убедила данная статья и вы хотите попробовать жить и трудиться без jQuery вы можете воспользоваться следующими ссылками:
    • You don't need jQuery — Блог о том как избавиться от jQuery
    • Beyond jQuery — Книга о том как избавиться от jQuery
    • The cost of frameworks — Мысли об экономии времени для разработчиков
    • Zepto.js — Небольшая jQuery-совместимая библиотека, своего рода переход от кокаина jQuery на травку Zepto.


    Кому интересно имеется английская версия данной статьи.
    Поделиться публикацией

    Похожие публикации

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

      +7
      Не понимаю смысла таких статей. Каждой задаче — свой инструмент.
      jQuery — очень хорошая библиотека, ускоряющая процесс разработки, имеющая кучу плагинов.
        0
        Согласен, всему свой инструмент. Эта статья направлена на разъяснение что не нужно использовать jQuery как the ultimate фреймворк для управления самолетом, и приготовления кофе. Эта классная низкоуровневая библиотека с кучей расширений и не более.
          +4
          Не надо использовать библиотеку как фремворк, а надо использовать библиотеку как библиотеку… Вам всё ещё кажется что статья нужна? :)
            0
            Да конечно, я же описал выше почему. Если вам кажется что статья вам лично ничего не дает или сводится к тому что вы говорите, просто не читайте ее как вы не читаете статьи которые вас не интересуют.
              –2
              Одно дело когда просто не интересно, другое дело когда статья разжигает очередной никому ненужный холивар на пустом месте. Не нравится как работает jQuery? Не вижу ссылок https://github.com/jquery/jquery
                0
                Холивал пытаетесь разжечь вы. В статье не говорится что jquery гумно и что все кто его использует ослы. В статье есть два ключевых аспекта, первый в том что время jquery прошло и он попросту изжил себя так что хватит его притягивать за все что можно и второй аспект в том что jquery не всеобъемлющий, а всего навсего библиотека. Эта статья выражение моей точки зрения, если кто-то ей ущемлен или оскорблен, ваше дело, это не было сутью статьи.
                  +1
                  В статье есть два ключевых аспекта, первый в том что время jquery прошло и он попросту изжил себя так что хватит его притягивать за все что можно

                  Покажите, где указано, что она себя изжила.
                  Есть что jquery пытается угодить всем, есть призыв за использование «стандартов», против привычного функционала.
          +1
          Каждой задаче — свой инструмент.
          А то мы не знали.

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

          jQuery — очень хорошая библиотека, ускоряющая процесс разработки, имеющая кучу плагинов.
          Спасибо, кэп! :)
          +5
          ИМХО в данный момент основной проблемой jQuery является обилие плагинов, которые без допиливания напильником сложно использовать с webpack/common.js, покуда они цепляются на неймспейс jQuery, что портит всю идею. Но эта проблема появилась не так давно, да и не такая уж и большая проблема (многие плагины сейчас обзаводятся совместимостью, что не может не радовать). Второй проблемой я вижу то, что очень часто тянут эту библиотеку ради того, чтобы повесить одно событие или один раз спрятать элемент, что является пустой тратой ресурсов. Однако если у вас достаточно большой проект — jQuery очень полезен, порой — не заменим, даже если вы используете крупные фреймворки (что уж тут говорить, jQuery тянет за собой angular (правда jQuery light, но не суть), backbone и многие другие).
          jQuery — большой, превосходный, но все же один из многочисленных инструментов, и его, как и все другие, нужно использовать с умом.

          P.S. Конкретно по статье: тема интересная, но в статье совсем не раскрыта — не показано, когда его нужно использовать, когда он избыточен. Поэтому статья и выглядит бесполезной.

          P.P.S. «Наверное, вам уже приходилось слышать замечания такого рода, и, скорее всего, вы чувствуете себя вполне вольготно, используя jQuery.» — о грамматике принято писать в личку, но у вас во всей статье одни и те же ошибки, ужасно режущие глаз прямо с первого предложения с 5-ю ошибками. Посему вспоминается отличное правило: «не используйте сложносочиненные предложения, вводные слова и прочие обороты, потому что все равно не знаете правил расстановки знаков препинания». Ну или вставляйте текст перед публикацией в Word хотя бы.
            0
            Angular не тянет с собой jQuery, а jQuery Light вообще не совместим с настоящим jQuery и сделан ради «чтобы было» (на самом деле несложной работы через Директивы, там даже поиска по классам нет). Мало того — у Angular сам принцип работы с DOM в корне отличается от работы с DOM через jQuery и поэтому если вам нужно работать с DOM через Angular в стиле jQuery — значит большая вероятность, что вы делаете что-то не так.
            Работая с Angular я очень часто сталкиваюсь с тем, что очень мало готовых плагинов не завязанных под jQuery.
            Сейчас у меня большой проект на Angular и там нет jQuery совсем.
              0
              Backbone, справедливости ради, тоже не сказать, что тянет с собой jQuery. Если не использовать Backbone.View, то остальное работает без нее.
              0
              С jQuery есть две проблемы. Первая — это легаси-методы, типа prependTo и unwrap. Сначала шаблонизаторы, потом байндинги сделали прямые манипуляции с DOM ненужными, слава богу. Вторая — мелкие, но многочисленные архитектурные недочеты, типа God Object, кривые вещи в некоторых API и т.д. Zepto, являясь полным клоном, эти проблемы никак не решает, а с разделением jQuery на 1.x и 2.x имеет смысл использовать ее только разве ради поддержки тач-событий.

              С другой стороны, в jQuery есть масса удобных вещей, для которых пока нет и не предвидится нативных аналогов — навскидку .closest и .index. С третьей стороны — наверняка stand-alone аналоги всему или почти всему есть в npm.
                +1
                Очередная статья на тему «не используйте JQ», если не путаю, их уже на хабре больше 3х и каждая практически не отличается содержанием. Только по-моему не имеет смысла, т.к. ситуация несколько иная:

                Проблема не в том, что ей пользуются, т.к. не видят аналогичных возможностей ванилы, а статья показывает, мол, смотрите, уже можно и без Jq вот так писать. Проблема в том, что те, кто используют — просто не умеют иначе. На подсознании уже у ребят подключение jq идёт первым делом, а дальше уже гугл, плагины и прочее. А то, что 30% jq реализовано в css, 60% в нативе, а остальная часть в ES15+ — это же надо учить, надо заморачиваться.
                  0
                  Как люди начинают использовать jQuery? У меня это произошло после поиска «JS post request», где мне выдало jquery + как менять элементы на странице через тот же jquery.
                  • динамически менять контент (работая на get/post c rest api)
                  • анимация и няшки
                  • плагины, которые требуют jquery


                  Мои фломастеры мне говорят, что из всей статьи единственный полезный момент (для меня, опять же), это http://blog.garstasio.com/you-dont-need-jquery/, где показаны простейшие реализации отдельных элементов на JS, что избавит от надобности отдавать юзеру jquery, если надо сделать пару-тройку функций.

                  Теперь замена на zepto:
                  94K Apr 28  2015 jquery-1.11.3.min.js
                  33K Dec 17 12:51 jquery-1.11.3.min.js.gz
                  83K Apr 28  2015 jquery-2.1.4.min.js
                  29K Dec 17 12:51 jquery-2.1.4.min.js.gz
                  25K Jun 16  2015 zepto.min.js
                  10K Dec 17 12:51 zepto.min.js.gz
                  

                  19кб больше… как-нибудь переживем. Что еще?
                  Zepto stays lean by not attempting to fix ancient 'browsers'
                  image


                  Итого: 19 кб экономии и без поддержки «чего-то там» в старых браузерах?
                  Вердикт: может даже и быть. Но пока множество галерей, чатов и прочих свистоперделок использует jquery, и причем работает на старых системах, переезд на новую фреймворк библиотеку будет не скоро.
                    0
                    Ну вообще все эти свистоперделки, по задумке, как раз должны работать на zepto без проблем. Зато получаете меньший вес и поддержку тач-событий — обе плюшки важны для мобилок.
                      0
                      Так тач-события есть и в jquery https://api.jquerymobile.com/category/events/ (tap, swipe, taphold, swipeleft, swiperight).
                      В zepto, судя по оффсайту добавили «doubleTap», «swipeUp», «swipeDown». А «longTap» это аналог "taphold".
                        +1
                        Это jquery mobile. Отдельная беда, то есть. Которую надо отдельно ставить и подключать. И которая представляет собой довольно жесткий фреймворк, подходящий не всем.
                    0
                    У любого человека который тесно связан с фрондэндом есть несколько этапов развития.

                    — Когда человек пишет на jquery все
                    — Когда человек начинает задумываться над jquery
                    — Когда человек пытается переписать jquery
                    — Когда осознает что можно жить и без него
                    — Опционально написать об этом статью
                    — И когда наконец-то осознает, что jquery это отличная либа, которая хоть и прилично весит, и довольно медленная, но решает целую кучу проблем, особенно в типовых задачах
                      +3
                      И какие же проблемы решает JQ? Вот представьте, что я обычный фронт-эндер, но ничего не знаю о JQ, максимум использую либу вроде кнокаута для разделения логики и представления. Убедите меня использовать JQuery для какой-либо задачи, где оно будет проще с Jquery, чем без него?

                      P.S. Если по теме — у меня немного другая стадия — я просто не использую его, т.к. не знаю задач, где он облегчит жизнь.
                        +2
                        P.P.S:
                        — Ajax? Мне проще написать «await fetch('...')», вместо "$.ajax(...)".
                        — Анимации? Мне проще написать «trasition: opacity .3s ease», вместо "$(...).fadeIn".
                        — Управление данными DOM элемента? Мне проще написать «value = 42» (указав в шаблоне куда вставлять переменную value), вместо "$(...).text(42);"

                        Больше я не представляю зачем оно нужно, увы.
                          –1
                          Сильно облегчает жизнь если требуется поддержка большинства браузеров. Конечно многие сайты этого не требуют, но когда серьезный проект это очень важно.
                            +1
                            Кейворд «await» должен был вам сказать, что в пример я привожу ES'16, а использование ES'16 подразумевает использование babel прослойки для отката, которая реализует все стандартные объекты, кроме проксей. Единственное «но» — это экспериментальные фичи, вроде Fetch API (крайне рекомендую хотя бы полистать его доки, в своё время я впал в экстаз смотря на это чудо), но это так же исправляется строкой «npm install whatwg-fetch» (К слову, оно уже работает на современных браузерах). В сумме оно (рантайм) весит примерно столько же, но значительное преимущество в том, что через 2-3 года эти прослойки можно просто отключить, не трогая и строчки кода.
                              0
                              Как это решает проблему поддержки ie7-8-9, и прочих проблемных вещей?
                                +1
                                Поддержку IE9 решает, а остальные даже гугл, вк и прочие, боюсь что больше половины сайтов в интернете не поддерживают (Например http://habrahabr.ru/post/201174/ прошу обратить внимание, что новость двухлетней давности).

                                Боюсь спросить, а на кой вам поддержка ИЕ8?
                                  0
                                  Гугл поддерживает, но не официально. Когда делаешь проект не для себя, или не корпоративного уровня, где можно всех пересадить на любой браузер, тогда это не актуально.

                                  Но даже в этом случае, спорить с тем, что jquery упрощает работу с DOM, ajax, для кого-то анимациями, эвентами и добавляет сахара.

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

                                  С мобильных приложениях и сайтах стараюсь не использовать jQuery, раньше заменял на zepto, но последние год-два и от него отказался. Но это только потому что у мобильных браузеров нет IE<9
                                    0
                                    Я до сих пор не понимаю зачем при наличии декларативного подхода (ангулар) требуется ярая императивщина (jquery)? Можно пример пожалуйста? Может я просто не сталкивался с такими ситуациями, хотя и писал довольно серьёзные проекты.
                                      +1
                                      Вы хотите сказать что пишите серьезные веб проекты довольствуясь только jQuery? Я не троллоло, просто пытаюсь понять вашу точку зрения.
                                        0
                                        Не понимаю как вы читаете. Я все хорошо и понятно написал. Повторю еще раз — в случае работы с ангуляром jQuery бывает не лишним.
                                          0
                                          Из вышеописанного не понятно или вы так считаете в глобально-космическом плане или же вы в реальных проектах, день за днем мешаете(я не в негативной стезе) оба подхода. Но не суть важно. Если это так, я вас не понимаю. Из опыта могу сказать что мне уже приходилось быть в схожих ситуациях, когда в проекте на knockout просто позарез нужен какойнить плюшко-плагин jquery и PO просто на гумно исходится лишь бы плюшка была в продакшене. Но я всегда выходил сухим из воды, аккуратно оборачивая всю сантехнику jQ в расширения knockout. Насколько мне известно вы можете сделать тоже самое при помощи директив angular, хотя я могу и ошибаться.
                                            0
                                            Чаще всего так и происходит. Всякие календарики, кастомные селекты, кастомные инпуты с автодоплнением и т.д. И проблема в общем-то не в том, что аналогов чисто на ангуляре нет. Они есть, только не всегда подходят, особенно если у тебя не SPA, а страницы которые генерируются на сервере. Тогда можно сделать плагин и как декларативную директиву так и просто как плагин. Так же приятно использовать $.ajax просто потому что привык. Ну и немного сахара.
                              0
                              Неправильно вы смотрите на ситуацию, спрос рождает предложение и популярные вещи априори не могут быть бесполезными. Это как раз результат рожениц кода. Значит у вас нет таких задач.
                              0
                              Спасибо, я вот к этой стадии только стремлюсь. Если бы был один, то давно бы уже улетел на планету где jquery нет и не нужно. Я не понимаю как человек видевший все достоинства MV* для разработки крупных и средних веб-приложений может откатиться назад и нежно укладывать jquery-based код в модуль паттерны. Я почему-то в последнее время только с такими и имею дело.
                                0
                                Не стоит забывать, что даже используя современные MV фрейворки, это не гарантирует того, что тебе не потребуется какой-нибудь плагин, который завязан на jQuery.
                                  0
                                  Ну это уже экстремальные ситуации, так не должно быть.
                            0
                            В статье имеется уклон в сторону «используйте нативный javascript». Выскажу мнение со своей колокольни. Я ни в коем случае не против знания чистого javascipt, просто как-то так получается, что в основном занимаюсь проектами, где уже используется jquery.

                            Можно легко заменить селектор типа $('div, span, article'); на document.querySelectorAll('div, span, article');

                            И заменить 1 символ на 25. На главной Хабра обращение к $ встречается 44 раза. А сколько будет в подключаемых скриптах?
                            Сделать функцию-обертку? Идем дальше.

                            $('button').bind('click', function(e){});

                            $('button').bind('click', function(e){});
                            // 41 байт
                            
                            console.log(document.querySelectorAll('button').forEach)
                            // undefined
                            // хм
                            
                            // можно сделать так (83 байт)
                            for(var v of document.querySelectorAll('button')) {
                              v.onclick = function() {}
                            }
                            
                            // или так (144 байт)
                            nodes = Array.prototype.slice.call(document.querySelectorAll('button'), 0);
                            nodes.forEach(function(v, i) {
                              v.onclick = function() {}
                            });
                            
                            // или с оберткой в виде функции $ (73 байта)
                            $('button').forEach(function(v, i) {
                              v.onclick = function() {}
                            });
                            

                            «Зачем нам нужно так усложнять себе жизнь?»

                            И так, иногда обертка, иногда нет, а иногда специальная обертка

                            document.getElementById('some_id') возвращает Element
                            document.getElementsByClassName('some_class') возвращает HTMLCollection[...]
                            document.querySelectorAll('#some_id') возвращает NodeList[...]
                            document.getElementById('unknown_id') возвращает null
                            

                            Последнее особенно весело, если кто-то так назначил обработчик где-нибудь в main.js и не проверил на null, при этом unknown_id является known на 99% страниц, а unknown он только на некоторых и при определенных условиях.

                            Да, еще при изменении селектора с «id» на «class» мне надо не забыть поменять нативную функцию.

                            Я видел кучу больших проектов которые превращались в одно большое блюдо спагетти на клиентской стороне

                            Здесь полностью согласен, такое бывает. Но для проектов среднего уровня, где не требуется серьезная работа с фронтендом, jQuery неплохой выбор.
                              –1
                              И заменить 1 символ на 25.

                              Минификаторы.
                                0
                                Минификаторы переименовывают системные функции (document.querySelectorAll)?
                                Эм. Дайте два ссылку плиз. Видимо я динозавр совсем дремучий…
                                  0
                                  А зачем им их переименовывать? Делаются алиасы. Вы никогда минифицированного кода не видели?:)
                                    0
                                    Я пока не встречал минификаторов делающих алиасы для системных функций. Видимо вот
                                    поэтому
                                    И, я не говорю, что это невозможно — я вообще-то попросил ссылку на такой умный минификатор.

                                    И, насчет «видел» — чтобы далеко-то не ходить… С текущей страницы скрипт, минифицированный:
                                    http://habracdn.net/habr/javascripts/1450359574/assets/global_main.js
                                      0
                                      Минификаторам можно и помочь, например, вот так: github.com/remy/min.js/blob/master/src/%24.js#L33. Если честно, я был уверен, что с обилием современных средств разбора AST минификаторы давно бороздят просторы вселенной и так далее.

                                      В любом случае я бы не тревожился насчет 25 байт вместо одного. А в случае с повторами они эффективно сожмутся gzip.
                              +1
                              Селекторы сейчас уже не являются тем локомотивом, который тащит jQuery. Их действительно можно и использовать нативные.

                              Чуть более сложный случай — это крайне нужные функции addClass, removeClass и так далее. Их нативная реализация пока еще не повсеместно поддерживается, увы. А полноценные фолбеки там довольно громоздки. Впрочем, прекрасно можно использовать Zepto, который легче в несколько раз.

                              Но и это неглавное. Главное — это огромный пул плагинов, которые привязаны к jQuery. И сначала библиотека дала взлететь им, теперь они не дают тонуть библиотеке. Иногда плагин заводится в связке с Зепто, иногда удается заставить их работать небольшим допиливанием кода. Но не всегда. Примеры из практики — галереи Fotorama, Slick привязаны именно к Джейквери. Я пытался модифицировать их внутри так, чтобы подружить с Зепто, но быстро это не получилось. Нужно либо тратить много времени, либо забить, либо выбрать другие галереи.
                                +1
                                Давно выпилили jQuery. В Ангуляровских проектах он точно не нужен

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

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