У меня очень странная проблема с браузером. Скрипты на некоторых страницах просто не работают, пока не пройдёт около 20 секунд.

Что бы вы ни собирались предложить — да, я уже думала об этом, и нет, не помогло. Я рассказываю об этом не в надежде, что кто-то подскажет с отладкой, а потому что этот случай заставил меня остро осознать некоторые, как бы сказать… причуды… разработки на фронте.

(В самом деле, даже не пытайтесь диагностировать проблему по одному предложению, не надо, я слышала и перепробовала почти всё, что вы можете себе представить).

Статья написана в марте 2016 года, некоторые примеры устарели — прим. пер.

Бесполезные страницы


Смотрите, вот скриншот твита. В нём красным цветом выделены те части, которые не работают без JavaScript. Я это знаю, потому что по-прежнему 20 секунд гляжу на страницу, на которой ещё не сработала большая часть кода.



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

С другой стороны…

Эта кнопка ? в правом верхнем углу и все пустое окружающее пространство? Их единственная функция — отправить вас в мой профиль, который виден за твитом. С таким же успехом они могли быть обычными ссылками, как стрелки влево и вправо для навигации. Но это сделано иначе, поэтому не работает без JavaScript.

Или маленькая кнопка с графиками, для аналитики? Её единственная функция — загрузить другую страницу в искусственном всплывающем окне со встроенным фреймом. Здесь могла быть обычная ссылка, которая превращается во всплывающее окно с помощью скрипта. Но это сделано иначе, поэтому не работает без JavaScript.

Текстовое поле? Конечно, это просто текстовое поле. Но если нажать на него до запуска JavaScript, в поле останется неуклюжая надпись Reply to @eevee. А когда скрипт всё-таки запускается, он стирает всё, что вы набрали, и снова вставляет Reply to @eevee, только теперь @eevee написано синенькими буквами, а не серенькими.

То же самое происходит на странице поиска Twitter, что очень странно, потому что в поле поиска нет текста! Если вы начнёте печатать до окончания работы скриптов, они просто сотрут всё, что вы набрали. Даже не для того, чтобы вставить свой текст-заполнитель или применить пользовательский стиль. Без всякой видимой причины, просто так.

Поскольку у меня работает NoScript, я частенько замечаю странные дизайнерские решения на сайтах, которые посещаю впервые. Конечно, пустые белые страницы — обычное дело. Довольно долго статьи на сайте Time отлично загружались без скрипта, но только не прокручивались — для страницы применялось свойство overflow: hidden; по причинам, которые я не могу понять. Статьи Vox также загружаются нормально, за исключением того, что перед каждым изображением выводится пустое пространство на всю высоту экрана. Некоторые особенно плохие корпоративные сайты представляют собой месиво перекрывающихся блоков текста. Думаю, что они отказались от CSS и написали макет на JavaScript.

Для этого нет никаких веских причин. Это не передовые интерактивные приложения, это просто страницы с текстом. Мы раньше их печатали на бумаге, но как только перешли на информационные технологии, стало невозможно поместить слова на экран, не запустив на исполнение несколько мегабайт мусора?

Я прямо слышу, как меня называют луддиткой, потому что я не согласна окружать пять абзацев статического текста тысячами строк скриптов. Ну, позвольте заранее ответить: идите в баню. Я думаю, что веб и интерактивные страницы — это здорово, я вижу отличный прогресс в последнее десятилетие. Просто супер, что веб изначально поддерживал пользовательские настройки, а я могу заранее настроить для каждого сайта разрешения, что он может запускать на моём компьютере, а что нет.

А вот что не очень здорово, так это группа высокооплачиваемых и высококвалифицированных специалистов, у каждого из которых установлен Chrome на последней модели Mac Pro, которые работают в офисе на расстоянии не больше километра от каждого сервера, на который они заходят. И вот эти ребята работают, а потом поворачиваются и хихикают над всеми остальными, у кого нет такой конфигурации. Учтите, что любое из следующих условий помешает работе вашего JavaScript:

  • Кто-то на медленном компьютере.
  • Кто-то на медленном соединении.
  • Кто-то на телефоне, то есть на медленном компьютере с медленным соединением.
  • Кто-то застрял со старым браузером на компьютере, который он не контролирует — на работе, в школе, в библиотеке и т. д.
  • Кто-то пытается написать небольшую программу, которая взаимодействует с вашим сайтом, у которого нет API.
  • Кто-то пытается загрузить копию вашего сайта, чтобы почитать в офлайне.
  • Кто-то — это кэш Google или Архив Интернета.
  • Кто-то сломал графическое окружение в Linux и пытается выяснить, как его починить, загружая статьи с вашего сайта через браузер командной строки Elinks.
  • Кто-то внёс изменения в ваш сайт с помощью пользовательского скрипта, и это мешает вашему собственному коду.
  • Кто-то использует NoScript и видит на вашем сайте только пустой экран. Он настолько раздражён, что просто уходит, а не вносит ваш сайт в белый список.
  • Кто-то использует NoScript и вносит в белый список вас, но ни один из десятков трекеров, которые вы используете. Позже вы случайно ставите скрипт в зависимость от трекера, и он таинственным образом больше не работает для таких пользователей.
  • Вы даёте критически важному скрипту название, связанное с рекламой, и он не загружается у десятков миллионов пользователей с блокировщиками рекламы.
  • Ваш CDN упал.
  • У вашего CDN есть адрес IPv6, но на самом деле он не работает (да, я видела такое и у компаний стоимостью в миллиард долларов, и у федерального правительства). Заходит кто-то по IPv6, страница загружается, но JS вылетает по таймауту.
  • Ваш деплой идёт немного неудачно, и JavaScript повреждается.
  • Вы случайно использовали новую функцию, которая не работает в предыдущей версии самого популярного браузера. Выводится синтаксическая ошибка, и ни один из ваших сценариев не запускается.
  • Вы прямо вводите синтаксическую ошибку, и никто не замечает, пока она не попадает в продакшн.

Я не говорю, что следует стереть с лица Земли интерактивные веб-приложения, такие как Google Maps, хотя даже для Google Maps много лет был запасной вариант без скриптов, до текущей версии WebGL! Я говорю, что мы свернули куда-то не туда, когда базовые функции обычного HTML вдруг перестали работать без JavaScript. А именно, без 40 мегабайт JavaScript, согласно about:memory — это данные в памяти, а не размер загрузки. Это может показаться не очень много (для страницы, которая выводит на экран 140 символов?), но в моём браузере часто накапливается десяток открытых вкладок Twitter, то есть полгигабайта памяти, выделенных максимум на 6 КБ текста.

Изобретение квадратного колеса


Вам действительно нужно постараться, чтобы добиться такого плачевного результата. Я имею в виду, если вам нужна ссылка, вы просто пишете <a href="somewhere">label</a>, и готово. Но если вы начнёте изобретать это с помощью JavaScript, то нужен обработчик кликов, и он должен работать в нужное время, чтобы вы знали, что ссылка действительно существует, и, возможно, вам придётся сделать некоторую работу, чтобы добавить обработчики кликов к фальшивым ссылкам, которые добавляет Ajax. Так ведь?

Нет! Вы получите лишь бледную, дрянную имитацию ссылки. Рассмотрим все функции нативных ссылок:

  • Я могу перейти по ссылке.
  • Я могу открыть ссылку в новой вкладке или окне с помощью комбинации клавиш ctrl, shift и колёсика (средней кнопки) мыши.
  • Я могу скопировать адрес ссылки и вставить его куда-нибудь или открыть в другом браузере, или ещё что-нибудь.
  • Я могу использовать ' в Firefox для поиска только ссылок.
  • В некоторых браузерах — Opera, Konqueror, uzbl, Firefox с vimperator? — есть горячая клавиша, которая показывает цифру или букву рядом с каждой ссылкой на странице, так что вы можете очень быстро «щёлкнуть» ссылку визуально, даже не касаясь мыши.
  • Я считаю, что скринридеры обрабатывают ссылки специальным образом.
  • Простые краулеры составляют по ссылкам карту сайта.
  • Браузеры начинают экспериментировать с предварительной загрузкой видных ссылок, так что если пользователь действительно нажимает на неё, то страница открывается мгновенно.

Общая нить здесь заключается в том, что тег <a href=...> нечто значит. Он говорит: «Это путь, по которому можно пройти». Тонны инструментов полагаются на эту информацию. Если заменить его на <div onclick>, то да, нажатие на div что-то сделает, но весь смысл полностью потерян. И наоборот, если использовать <a href="javascript:void(0);">, то вы фактически лжёте этим инструментам; вы вызываете смысл, но отдаёте бессмысленную информацию.

Вот что люди имеют в виду, когда говорят о «семантике» — что есть полезная информация, которую нужно собрать. Если вы начинаете изобретать подобие ссылок, то анализ этого синтетического конструкта потребует либо спекулятивного выполнения большого количества произвольного кода, либо написания чрезвычайно умного статического анализатора, либо просто обучения программиста-человека. Декларирование намерений — гораздо более мощный и гибкий метод, чем просто выполнение работы, потому что в первом случае универсальные инструменты делают полезные вещи почти тривиально.

Еще один хороший пример — выпадающие формы <select>. Некоторые разработчики иногда полностью с нуля создают свою замену из неродных виджетов. Наверное, чтобы сделать их красивее? Благородная цель. Но знаете ли вы, что в нативных выпадающих формах при начале набора текста автоматически выбирается первая подходящая позиция? Очевидно, в большинстве альтернативных реализаций это не поддерживается. Визуально они выглядят лучше (или просто иначе), но функционально намного хуже для длинных списков.

Самодельное текстовое поле Twitter — это вовсе не текстовое поле, а contenteditable <div>. Здесь contenteditable означает, что большинство нативных элементов управления работают довольно хорошо, но всё равно этот объект время от времени демонстрирует некое странное поведение, например, перемещает курсор в начало текста, когда я переключаюсь между вкладками. Или иногда у скрипта возникают какие-то проблемы с моей скоростью набора и он начинает з а м е т н о     о т с т а в а т ь. Единственная причина, зачем вообще ставить его вместо обычного <textarea>, кажется, это чтобы подкрасить @handles и ссылки синим цветом? Самодельное текстовое поле не сокращает ссылки и не заменяет твиттеровские эмодзи, поэтому на самом деле это не предварительный просмотр того, как будет выглядеть ваш твит.

Вы знаете, что на некоторых сайтах работают горячие клавиши? Мило, правда? Но на самом деле / — это встроенная в Firefox горячая клавиша, которая открывает панель быстрого поиска. Очевидно, никто в Twitter или GitHub, или BitBucket, или Tumblr, или в десятке других мест не знает об этом, потому что все они назначили этой клавише перемещение фокуса на собственную панель поиска по сайту. Что полностью отличается от поиска на текущей странице (к чести GitHub, они это исправили, когда я пожаловалась в твиттере). В течение длительного времени Google+ отключал пробел для прокрутки вниз. Почему никто в этих огромных компаниях не остановился и не сказал: «Эй, подождите, это ведь рабочая функция в браузере, а мы её ломаем»? Веб-разработчики сами вообще пользуются браузерами?

Тут вспомнилось, что каждая страница Twitter молча поглощает любые события клавиатуры и нажатия мыши, пока не отработают все скрипты. Это означает, что я не могу даже сменить вкладку, пока не подожду эти 20 секунд загрузки страницы: ctrl-t, ctrl-w, ctrl-tab, ctrl-pgup и ctrl-pgdn — все события клавиатуры полностью поглощаются. Так работает механизм под названием «очередь быстрых действий» (swift action queue). Звучит так, будто эта очередь должна воспроизводить события по окончании загрузки страницы, но (а) вы не можете воспользоваться горячими клавишами в браузере; (б) похоже, она всё равно не работает. Чтобы это исправить, мне пришлось написать пользовательский скрипт, чтобы заблокировать тег скрипта с определённым идентификатором.

Я не думаю, что очень привередничаю. Это базовые функции браузера, и вы их нарушаете, часто без уважительной причины. Я не ожидаю, что вы заставите Google Docs работать без JavaScript. Я просто надеюсь, что вы не сломаете мою чёртову клавиатуру.

Позвольте дать совет


Примите тот факт, что иногда для некоторых людей ваш JavaScript не будет работать. Подумайте, что это значит. Когда есть выбор, всегда выбирайте существующие HTML-механизмы. Может, раз в год ваша команда разработчиков отключит JavaScript и попытается использовать сайт. Начинай плакать.

Если вы собираетесь переопределить или переосмыслить то, что уже существует, сначала изучите это. Вы не можете создать хорошую замену без понимания оригинала. Поспрашивайте вокруг. Чёрт, просто попробуйте нажать / в браузере, прежде чем делать это горячей клавишей на своём сайте.

Помните, что при всей власти, которую даёт вам интернет, в конечном счёте контроль всё равно находится в руках пользователя. Интернет — это не игровая приставка, действуйте соответственно. Создавайте модули. Заранее учитывайте вероятные или распространённые настройки. Может, что-нибудь немного уменьшить, когда достигнете 40 мегабайт скриптов на странице.

Спасибо.