Pull to refresh

Небольшая заметка о feature detection

Reading time3 min
Views10K
В современном вебе используются две основные технологии определения возможностей браузера:
(а) распарсить юзер-агент, определить версию браузера и писать в коде свитчи по версии браузера;
(б) пытаться определять поддержку фич путём проверки нужных полей / вызовов нужных методов.

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

И, вроде бы, аргументация-то правильная: (а) не нужно хранить базу регулярок, (б) если в каком-то браузере появляется новая фича, она начинает работать автоматически без изменения кода, (в) неизвестные (экзотические, новые) браузеры будут работать без дополнительных телодвижений, (г) если у пользователя подменён юзер-агент, то код всё равно будет работать.

Это всё хорошо и правильно, но только для небольших проектов.



У этого подхода возникают неразрешимые сложности, когда та или иная фича детектится, но не работает.
В идеальном мире если в браузере реализована какая-то фича, то она работает. В реальном — может, работает, а может, и нет. И вообще, новая версия браузера может внезапно её сломать.

Вот работал у вас transform3d в Хроме, а потом в 15-ой версии взял и сломался:
code.google.com/p/chromium/issues/detail?id=119076&can=1&q=transform%203d&sort=-pri&colspec=ID%20Pri%20Mstone%20ReleaseBlock%20OS%20Area%20Feature%20Status%20Owner%20Summary
А починили его только в 21-ой.

Как вам поможет feature detection выяснить, что при каких-то условиях блок с transform3d делает близлежащие инпуты некликабельными?
Можно, конечно, извернуться и написать автотест на то, что transform3d не делает близлежащие инпуты некликабельными. Только со временем ваш код превратится в гигантский автотест на баги браузеров.

Или вот в Opera 10-11 для корректной работы transition нужно было руками вызвать reflow, дёрнув какой-нибудь элемент на странице, а иначе появлялись артефакты анимации. Как это сдетектить автоматически?

Кроме браузеров, есть ещё гигантская армия скриптописателей. Например, в дефолтной теме Joomla! 1.5 до сих пор используется mootools 1.12, в котором написано следующее:

Array.extend({
    forEach: function (fn,bind) {
        for (var i=0, j=this.length; i<j; i++)
             fn.call(bind,this[i],i,this);
    }
});


А в браузерной реализации написано следующее:

Array.prototype.forEach = function(fn, scope) {
    for(var i = 0, len = this.length; i < len; ++i) {
      fn.call(scope || this, this[i], i, this);
    }
  }


Т.е. браузерная реализация при незаданном втором параметре подставляет в качестве контекста сам массив, а мутулзовская — нет. И ваша прекрасная библиотечка, использующий feature detection, работает как баг в IE в Жумле — потому что forEach в прототипе массива есть, но работает неправильно. Что здесь делать? Добавить к feature detection-у ещё feature validation или перестать использовать контексты в forEach?

А вот старый добрый парсинг юзер-агента от всего этого спасает. Да, он добавляет дополительной работы в определении работающих фич — но он же и избавляет от головной боли при определении НЕработающих фич.

Итого, если в вашем проекте вы интенсивно используете новые фичи браузеров либо встраиваетесь на страницы с агрессивным пользовательским кодом — feature detection рано или поздно выйдет вам боком. Да, парсинг юзер-агента лишает вас части аудитории с нестандартными браузерами и переопределёнными юзер-агентами — но это измеримые риски. Для каждого нестандартного браузера вы можете посмотреть на его долю и решить, окупится ли его поддержка. Использование же feature detection добавляет вам неизмеримых рисков — черт его знает, у какой доли пользователей та или иная фича работает криво.
Tags:
Hubs:
+13
Comments15

Articles

Change theme settings