Введение
Наверное вам уже приходилось слышать замечания такого рода и скорее всего вы чувствуете себя вполне вольготно используя 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)
kahi4
17.12.2015 15:04+5ИМХО в данный момент основной проблемой jQuery является обилие плагинов, которые без допиливания напильником сложно использовать с webpack/common.js, покуда они цепляются на неймспейс jQuery, что портит всю идею. Но эта проблема появилась не так давно, да и не такая уж и большая проблема (многие плагины сейчас обзаводятся совместимостью, что не может не радовать). Второй проблемой я вижу то, что очень часто тянут эту библиотеку ради того, чтобы повесить одно событие или один раз спрятать элемент, что является пустой тратой ресурсов. Однако если у вас достаточно большой проект — jQuery очень полезен, порой — не заменим, даже если вы используете крупные фреймворки (что уж тут говорить, jQuery тянет за собой angular (правда jQuery light, но не суть), backbone и многие другие).
jQuery — большой, превосходный, но все же один из многочисленных инструментов, и его, как и все другие, нужно использовать с умом.
P.S. Конкретно по статье: тема интересная, но в статье совсем не раскрыта — не показано, когда его нужно использовать, когда он избыточен. Поэтому статья и выглядит бесполезной.
P.P.S. «Наверное, вам уже приходилось слышать замечания такого рода, и, скорее всего, вы чувствуете себя вполне вольготно, используя jQuery.» — о грамматике принято писать в личку, но у вас во всей статье одни и те же ошибки, ужасно режущие глаз прямо с первого предложения с 5-ю ошибками. Посему вспоминается отличное правило: «не используйте сложносочиненные предложения, вводные слова и прочие обороты, потому что все равно не знаете правил расстановки знаков препинания». Ну или вставляйте текст перед публикацией в Word хотя бы.dshster
18.12.2015 15:58Angular не тянет с собой jQuery, а jQuery Light вообще не совместим с настоящим jQuery и сделан ради «чтобы было» (на самом деле несложной работы через Директивы, там даже поиска по классам нет). Мало того — у Angular сам принцип работы с DOM в корне отличается от работы с DOM через jQuery и поэтому если вам нужно работать с DOM через Angular в стиле jQuery — значит большая вероятность, что вы делаете что-то не так.
Работая с Angular я очень часто сталкиваюсь с тем, что очень мало готовых плагинов не завязанных под jQuery.
Сейчас у меня большой проект на Angular и там нет jQuery совсем.
k12th
18.12.2015 16:28Backbone, справедливости ради, тоже не сказать, что тянет с собой jQuery. Если не использовать Backbone.View, то остальное работает без нее.
k12th
17.12.2015 15:34С jQuery есть две проблемы. Первая — это легаси-методы, типа prependTo и unwrap. Сначала шаблонизаторы, потом байндинги сделали прямые манипуляции с DOM ненужными, слава богу. Вторая — мелкие, но многочисленные архитектурные недочеты, типа God Object, кривые вещи в некоторых API и т.д. Zepto, являясь полным клоном, эти проблемы никак не решает, а с разделением jQuery на 1.x и 2.x имеет смысл использовать ее только разве ради поддержки тач-событий.
С другой стороны, в jQuery есть масса удобных вещей, для которых пока нет и не предвидится нативных аналогов — навскидку .closest и .index. С третьей стороны — наверняка stand-alone аналоги всему или почти всему есть в npm.
SerafimArts
17.12.2015 15:55+1Очередная статья на тему «не используйте JQ», если не путаю, их уже на хабре больше 3х и каждая практически не отличается содержанием. Только по-моему не имеет смысла, т.к. ситуация несколько иная:
Проблема не в том, что ей пользуются, т.к. не видят аналогичных возможностей ванилы, а статья показывает, мол, смотрите, уже можно и без Jq вот так писать. Проблема в том, что те, кто используют — просто не умеют иначе. На подсознании уже у ребят подключение jq идёт первым делом, а дальше уже гугл, плагины и прочее. А то, что 30% jq реализовано в css, 60% в нативе, а остальная часть в ES15+ — это же надо учить, надо заморачиваться.
nikitasius
17.12.2015 16:01Как люди начинают использовать 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'k12th
17.12.2015 16:12Ну вообще все эти свистоперделки, по задумке, как раз должны работать на zepto без проблем. Зато получаете меньший вес и поддержку тач-событий — обе плюшки важны для мобилок.
nikitasius
17.12.2015 17:03Так тач-события есть и в jquery https://api.jquerymobile.com/category/events/ (tap, swipe, taphold, swipeleft, swiperight).
В zepto, судя по оффсайту добавили «doubleTap», «swipeUp», «swipeDown». А «longTap» это аналог "taphold".k12th
17.12.2015 17:08+1Это jquery mobile. Отдельная беда, то есть. Которую надо отдельно ставить и подключать. И которая представляет собой довольно жесткий фреймворк, подходящий не всем.
Evgeny42
17.12.2015 16:29У любого человека который тесно связан с фрондэндом есть несколько этапов развития.
— Когда человек пишет на jquery все
— Когда человек начинает задумываться над jquery
— Когда человек пытается переписать jquery
— Когда осознает что можно жить и без него
— Опционально написать об этом статью
— И когда наконец-то осознает, что jquery это отличная либа, которая хоть и прилично весит, и довольно медленная, но решает целую кучу проблем, особенно в типовых задачахSerafimArts
17.12.2015 17:11+3И какие же проблемы решает JQ? Вот представьте, что я обычный фронт-эндер, но ничего не знаю о JQ, максимум использую либу вроде кнокаута для разделения логики и представления. Убедите меня использовать JQuery для какой-либо задачи, где оно будет проще с Jquery, чем без него?
P.S. Если по теме — у меня немного другая стадия — я просто не использую его, т.к. не знаю задач, где он облегчит жизнь.SerafimArts
17.12.2015 17:18+2P.P.S:
— Ajax? Мне проще написать «await fetch('...')», вместо "$.ajax(...)".
— Анимации? Мне проще написать «trasition: opacity .3s ease», вместо "$(...).fadeIn".
— Управление данными DOM элемента? Мне проще написать «value = 42» (указав в шаблоне куда вставлять переменную value), вместо "$(...).text(42);"
Больше я не представляю зачем оно нужно, увы.Evgeny42
17.12.2015 18:21-1Сильно облегчает жизнь если требуется поддержка большинства браузеров. Конечно многие сайты этого не требуют, но когда серьезный проект это очень важно.
SerafimArts
17.12.2015 19:30+1Кейворд «await» должен был вам сказать, что в пример я привожу ES'16, а использование ES'16 подразумевает использование babel прослойки для отката, которая реализует все стандартные объекты, кроме проксей. Единственное «но» — это экспериментальные фичи, вроде Fetch API (крайне рекомендую хотя бы полистать его доки, в своё время я впал в экстаз смотря на это чудо), но это так же исправляется строкой «npm install whatwg-fetch» (К слову, оно уже работает на современных браузерах). В сумме оно (рантайм) весит примерно столько же, но значительное преимущество в том, что через 2-3 года эти прослойки можно просто отключить, не трогая и строчки кода.
Evgeny42
17.12.2015 19:37Как это решает проблему поддержки ie7-8-9, и прочих проблемных вещей?
SerafimArts
17.12.2015 19:59+1Поддержку IE9 решает, а остальные даже гугл, вк и прочие, боюсь что больше половины сайтов в интернете не поддерживают (Например http://habrahabr.ru/post/201174/ прошу обратить внимание, что новость двухлетней давности).
Боюсь спросить, а на кой вам поддержка ИЕ8?Evgeny42
17.12.2015 20:52Гугл поддерживает, но не официально. Когда делаешь проект не для себя, или не корпоративного уровня, где можно всех пересадить на любой браузер, тогда это не актуально.
Но даже в этом случае, спорить с тем, что jquery упрощает работу с DOM, ajax, для кого-то анимациями, эвентами и добавляет сахара.
В конечном итоге jQuery это либа, а не фреймворк и не указывает тебе что делать. И я могу сказать что написал много приложений с ангуляром, и даже в этом случае jQuery мне очень помогал. И дело совсем не в неправильности архитектуры.
С мобильных приложениях и сайтах стараюсь не использовать jQuery, раньше заменял на zepto, но последние год-два и от него отказался. Но это только потому что у мобильных браузеров нет IE<9SerafimArts
17.12.2015 21:12Я до сих пор не понимаю зачем при наличии декларативного подхода (ангулар) требуется ярая императивщина (jquery)? Можно пример пожалуйста? Может я просто не сталкивался с такими ситуациями, хотя и писал довольно серьёзные проекты.
vba
17.12.2015 23:44+1Вы хотите сказать что пишите серьезные веб проекты довольствуясь только jQuery? Я не троллоло, просто пытаюсь понять вашу точку зрения.
Evgeny42
17.12.2015 23:57Не понимаю как вы читаете. Я все хорошо и понятно написал. Повторю еще раз — в случае работы с ангуляром jQuery бывает не лишним.
vba
18.12.2015 11:20Из вышеописанного не понятно или вы так считаете в глобально-космическом плане или же вы в реальных проектах, день за днем мешаете(я не в негативной стезе) оба подхода. Но не суть важно. Если это так, я вас не понимаю. Из опыта могу сказать что мне уже приходилось быть в схожих ситуациях, когда в проекте на knockout просто позарез нужен какойнить плюшко-плагин jquery и PO просто на гумно исходится лишь бы плюшка была в продакшене. Но я всегда выходил сухим из воды, аккуратно оборачивая всю сантехнику jQ в расширения knockout. Насколько мне известно вы можете сделать тоже самое при помощи директив angular, хотя я могу и ошибаться.
Evgeny42
18.12.2015 17:13Чаще всего так и происходит. Всякие календарики, кастомные селекты, кастомные инпуты с автодоплнением и т.д. И проблема в общем-то не в том, что аналогов чисто на ангуляре нет. Они есть, только не всегда подходят, особенно если у тебя не SPA, а страницы которые генерируются на сервере. Тогда можно сделать плагин и как декларативную директиву так и просто как плагин. Так же приятно использовать $.ajax просто потому что привык. Ну и немного сахара.
Alexufo
17.12.2015 23:11Неправильно вы смотрите на ситуацию, спрос рождает предложение и популярные вещи априори не могут быть бесполезными. Это как раз результат рожениц кода. Значит у вас нет таких задач.
vba
17.12.2015 17:44Спасибо, я вот к этой стадии только стремлюсь. Если бы был один, то давно бы уже улетел на планету где jquery нет и не нужно. Я не понимаю как человек видевший все достоинства MV* для разработки крупных и средних веб-приложений может откатиться назад и нежно укладывать jquery-based код в модуль паттерны. Я почему-то в последнее время только с такими и имею дело.
michael_vostrikov
17.12.2015 18:49В статье имеется уклон в сторону «используйте нативный 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 неплохой выбор.k12th
17.12.2015 19:43-1И заменить 1 символ на 25.
Минификаторы.foxkeys
18.12.2015 00:40Минификаторы переименовывают системные функции (document.querySelectorAll)?
Эм. Дайтедвассылку плиз. Видимо я динозавр совсем дремучий…k12th
18.12.2015 00:42А зачем им их переименовывать? Делаются алиасы. Вы никогда минифицированного кода не видели?:)
foxkeys
18.12.2015 00:50Я пока не встречал минификаторов делающих алиасы для системных функций. Видимо вот
поэтому
И, я не говорю, что это невозможно — я вообще-то попросил ссылку на такой умный минификатор.
И, насчет «видел» — чтобы далеко-то не ходить… С текущей страницы скрипт, минифицированный:
http://habracdn.net/habr/javascripts/1450359574/assets/global_main.jsk12th
18.12.2015 01:21Минификаторам можно и помочь, например, вот так: github.com/remy/min.js/blob/master/src/%24.js#L33. Если честно, я был уверен, что с обилием современных средств разбора AST минификаторы давно бороздят просторы вселенной и так далее.
В любом случае я бы не тревожился насчет 25 байт вместо одного. А в случае с повторами они эффективно сожмутся gzip.
dom1n1k
18.12.2015 00:31+1Селекторы сейчас уже не являются тем локомотивом, который тащит jQuery. Их действительно можно и использовать нативные.
Чуть более сложный случай — это крайне нужные функции addClass, removeClass и так далее. Их нативная реализация пока еще не повсеместно поддерживается, увы. А полноценные фолбеки там довольно громоздки. Впрочем, прекрасно можно использовать Zepto, который легче в несколько раз.
Но и это неглавное. Главное — это огромный пул плагинов, которые привязаны к jQuery. И сначала библиотека дала взлететь им, теперь они не дают тонуть библиотеке. Иногда плагин заводится в связке с Зепто, иногда удается заставить их работать небольшим допиливанием кода. Но не всегда. Примеры из практики — галереи Fotorama, Slick привязаны именно к Джейквери. Я пытался модифицировать их внутри так, чтобы подружить с Зепто, но быстро это не получилось. Нужно либо тратить много времени, либо забить, либо выбрать другие галереи.
yjurfdw
Не понимаю смысла таких статей. Каждой задаче — свой инструмент.
jQuery — очень хорошая библиотека, ускоряющая процесс разработки, имеющая кучу плагинов.
vba
Согласен, всему свой инструмент. Эта статья направлена на разъяснение что не нужно использовать jQuery как the ultimate фреймворк для управления самолетом, и приготовления кофе. Эта классная низкоуровневая библиотека с кучей расширений и не более.
Caravus
Не надо использовать библиотеку как фремворк, а надо использовать библиотеку как библиотеку… Вам всё ещё кажется что статья нужна? :)
vba
Да конечно, я же описал выше почему. Если вам кажется что статья вам лично ничего не дает или сводится к тому что вы говорите, просто не читайте ее как вы не читаете статьи которые вас не интересуют.
Caravus
Одно дело когда просто не интересно, другое дело когда статья разжигает очередной никому ненужный холивар на пустом месте. Не нравится как работает jQuery? Не вижу ссылок https://github.com/jquery/jquery
vba
Холивал пытаетесь разжечь вы. В статье не говорится что jquery гумно и что все кто его использует ослы. В статье есть два ключевых аспекта, первый в том что время jquery прошло и он попросту изжил себя так что хватит его притягивать за все что можно и второй аспект в том что jquery не всеобъемлющий, а всего навсего библиотека. Эта статья выражение моей точки зрения, если кто-то ей ущемлен или оскорблен, ваше дело, это не было сутью статьи.
nikitasius
Покажите, где указано, что она себя изжила.
Есть что jquery пытается угодить всем, есть призыв за использование «стандартов», против привычного функционала.
poxu
В статье обрисован круг задач, для решения которых jquery не нужен.
Спасибо, кэп! :)