[Перевод] Конец эпохи Trident

tl; dr Я бы сказал, что Microsoft на несколько световых лет опередила всех в разработке инструментов для проектирования сложных веб-сайтов. Сейчас эти технологии изобретают заново на руинах погибшей цивилизации.

a877780d8c626b34fffc4a85714ec037.jpg

Когда я был ребёнком, меня всегда завораживали истории о древних цивилизациях. Я зачитывался книгами об Атлантиде, об истории открытия Трои Генрихом Шлиманом, о греках, римлянах, империи инков и Древнем Египте. И меня всегда восхищали их продвинутые знания в области астрономии, математики и медицины, их невероятные достижения, возведение этих огромных монументов и построение высокофункциональных социальных систем. Что ещё более невероятно, так это то, что всё это было сделано за тысячи лет до появления христианской культуры!

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


Теперь для миллионов пользователей Windows 10 компания Microsoft выпускает новый браузер Edge на основе Chromium. И это означает конец целой эпохи, которая прошла под знаком движка Trident.

Но разве эра Trident уже не закончилась, когда появился Edge? Не совсем.

Когда Microsoft создала браузер Edge в 2015 году, в реальности она просто форкнула Trident в EdgeHTML и почистила множество устаревших путей кода, таких как ActiveX (версия Java-апплетов Microsoft) или эмуляция старых движков рендеринга IE. Родственность двух браузеров очевидна, если почитать статьи самих разработчиков или по баг-репортам, когда одни и те же уязвимости одинаково влияют на IE 11 и Edge 17. На самом деле большинство первоначальных улучшений Edge получено от Chakra, движка JavaScript, и мало что можно отнести к самому движку рендеринга. Переименование браузера можно рассматривать скорее как маркетинговый ход, поскольку удаление устаревших функций уже началось раньше, когда браузер ещё назывался Internet Explorer.

Перезагрузка Internet Explorer под новым названием не вернула сердца веб-разработчиков. До сегодняшнего дня Microsoft занята игрой в догонялки. Поэтому, когда мы сегодня волнуемся о веб-платформе, это происходит не из-за нового выпуска Edge, а из-за того, что Google представляет новые идеи или API во время Google I/O или саммита Chrome Dev. Многие из этих инноваций приходят от других команд в Google, работающих на таких платформах Google, как Angular и AMP, или на продуктах Google, таких как Gmail, Search, Drive, Maps, Google Docs, Analytics или, в последнее время, Lighthouse. На самом деле, многое из того, что определяет HTML5, связано с тем, что Google ищет способ улучшить веб-платформу, чтобы лучше применить свои идеи в веб-приложениях. Помните Google Gears? Или потом Google Chrome Frame?

Забавно, что в старые времена тот же процесс стимулировал инновации в Internet Explorer. Возможности ActiveX добавили в Internet Explorer 3.0 вместе с тегом , добавив ещё одну «цель компиляции» для конкурента Java. Конечно, идея исходила не от команды IE. Или возьмём то, что мы сегодня знаем как AJAX: идея ленивой выборки контента в фоновом режиме с помощью JavaScript родилась в команде Exchange / Outlook Web Access, этот продукт можно рассматривать как предшественника Gmail. Произведя несколько трюков на серверах Microsoft, они тихо выкатили компонент вместе с Internet Explorer 5.0 в 1999 году. Только через шесть лет был изобретён термин AJAX и его концепции стали широко известны.

«Мы довольно быстро договорились выпустить это как часть библиотеки MSXML. Вот откуда взялось название XMLHTTP — компонент в основном работает по HTTP и не имеет конкретной связи с XML, но так проще всего было вытолкнуть его в прод, так что нам пришлось втиснуть XML в название (к тому же, XML была модной технологией в то время, и это казалось хорошим маркетингом для компонента)».


То же самое касается и document.designMode (видимо, пожелание исходило от команды Hotmail) и contentEditable, DOM, Drag-n-Drop API, iframе и доступа к буферу обмена. Internet Explorer также стал первым браузером, который научился менять разрешения на лету через всплывающее окошко с запросом:

95fab1aff85d1713848f69b3b26045c6.png

В те дни Microsoft в одиночку двигала вперёд интернет. Над Internet Explorer работало около тысячи (!) человек с бюджетом 100 миллионов долларов в год. С ними почти никто не мог конкурировать. Это было грандиозно!

»[Скотт] Айзек также изобрел HTML-тег iframe. Было высказано предположение, что название означает «фрейм Айзекса», хотя Скотт отрицал это».


В 2012 году Internet Explorer последний раз представил новые функции по запросу других бизнес-подразделений. В то время для операционной системы Windows 8 сделали Windows Store, и появились соответствующие приложения Windows Store Apps. Однажды написанные, эти приложения потом запускаются на Windows, Xbox и Windows Phone. Поскольку Microsoft опоздала с каталогом приложений, то должна была максимально снизить барьер входа для разработчиков. Поэтому появилась идея разрешить в каталоге веб-приложения. В качестве прокси между веб-стеком и операционной системой была создана JavaScript- библиотека под названием WinJS, а средой выполнения для этих приложений стал Internet Explorer 10.

492ea0ec209fb889ec39e0f731570c69.png

Но чтобы смоделировать Windows UI с помощью веб-технологий, Microsoft пришлось добавить в IE множество новых возможностей: CSS Grid, CSS Flexbox, CSS Scroll Snap Points и Pointer Events API для взаимодействия с сенсорным экраном и стилусом (последнее было необходимо, поскольку Apple подала патент на Touch API).

Your browser does not support HTML5 video.


Microsoft даже изобрела то, что позже стало Origin Trials. Об этом рассказывается в подкасте, которое мы записали с Джейкобом Росси из команды Edge в 2015 году.

Возвращаясь к моим рассуждениям о древних цивилизациях и их достижениях, мне кажется, что Internet Explorer представил многие технологии, которые впоследствии были реализованы заново и которые мы теперь отмечаем как инновации. Хотя наши современные переосмысления предлагают больше возможностей и удобств, меня удивляет, почему сообщество разработчиков выбрало только очень немногие из них. Упомянутые выше инновации были подхвачены либо потому, что браузеры стремились к совместимости с IE, либо потому, что Microsoft оказалась в нужное время в нужном месте. Но их было гораздо больше!


MHTML


Первый в списке — MHTML или «MIME-инкапсуляция агрегированных HTML-документов». MHTML задумывался как формат упаковки контента, а концепция во многом повторяла способ добавления вложений в электронной почте. MHTML берёт HTML-файл, а в дополнительные разделы встраивает все необходимые ресурсы, такие как CSS, JavaScript-файлы и изображения, в кодировке base64. Это как data URI на стероидах. Можете считать MHTML предшественником Web Bundles. Формат поддерживался начиная с IE 5, а также в Opera на движке Presto. Ни один другой браузер официально не поддерживал MHTML, но Chromium позже добавил эту функцию, за флагом chrome://flags/#save-page-as-mhtml. MHTML предложили в качестве открытого стандарта IETF, но он почему-то не взлетел.

Интересный факт: Outlook Express использует MHTML внутри файлов .eml для хранения писем вместе с соответствующими вложениями на диске.

Спецэффекты между страницами


В Internet Explorer были фильтры перехода между страницами, которые можно определить как заголовок HTTP или в виде метатега:


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

  • 0 — Box in
  • 1 — Box out
  • 2 — Circle in
  • 3 — Circle out
  • 4 — Wipe up
  • 5 — Wipe down
  • 6 — Wipe right
  • 7 — Wipe left
  • 8 — Vertical blinds
  • 9 — Horizontal blinds
  • 10 — Checkerboard across
  • 11 — Checkerboard down
  • 12 — Random dissolve
  • 13 — Split vertical in
  • 14 — Split vertical out
  • 15 — Split horizontal in
  • 16 — Split horizontal out
  • 17 — Strips left down
  • 18 — Strips left up
  • 19 — Strips right down
  • 20 — Strips right up
  • 21 — Random bars horizontal
  • 22 — Random bars vertical
  • 23 — Случайный фильтр из списка


Фильтр можно активировать на ввод страницы Page-Enter, а также установить дополнительные спецэффекты на Page-Exit, Site-Enter и Site-Exit. Эти мягкие переходы между страницами — то, что предлагают в новом формате порталов.

Спецэффекты между объектами


Аналогично переходу между страницами, можно использовать фильтры для перехода между двумя состояниями одного и того же объекта DOM. Это похоже на ramjet Рича Харриса, только он не трансформируется между двумя состояниями, а вместо этого смешивается в киношном стиле.

По своему эффекту эти фильтры похожи на CSS Transitions или анимированную функцию CSS crossfade ().

Сначала применяем к элементу фильтр смешивания (длительностью 600 мс):

img.style.filter = 'blendTrans(duration=0.600)';


Затем, прежде чем вносить какие-либо изменения в объект, замораживаем его текущее состояние:

img.filters.blendTrans.apply();


Наконец, изменяем источник изображения и вызываем переход:

img.src = 'different-src.jpg';
img.filters.blendTrans.play();

Your browser does not support HTML5 video.


Фильтры эффектов


Многие помнят эту категорию фильтров ещё со времён Internet Explorer 4+. В 1997 году они уже предлагали функциональность, близкую к CSS Filters, когда те впервые появились в Apple Safari 6 в 2012 году.

d079e8a76b0263fbc9fb12884c6fb25d.jpg

Matrix Filter из Internet Explorer можно применять для выполнения действий, которые позже будут представлены как часть функциональности CSS Transforms:

transform: rotate(15deg);
filter: progid:DXImageTransform.Microsoft.Matrix(
            M11=0.9659258262890683,
            M12=-0.2588190451025207,
            M21=0.2588190451025207,
            M22=0.9659258262890683,
            SizingMethod='auto expand');


Или можете использовать Chroma Filter для выделения пикселей определённого цвета, чтобы создать закруглённые углы или применить маску.

Градиентный фильтр


Вы думали, что поддержка градиентов впервые появилась в Internet Explorer 10? Это не совсем так, потому что для градиентов тоже был CSS-фильтр:

filter: progid:DXImageTransform.Microsoft.gradient(enabled='false',
                startColorstr=#550000FF, endColorstr=#55FFFF00)


Также обратите внимание, что Internet Explorer уже поддерживал 8-значные hex-коды для цветов RGBA, которые официально появились в CSS только в 2016 году как часть CSS Color Module Level 4.

Стилизация полосы прокрутки


Internet Explorer внедрил стилизацию полосы прокрутки ещё в 1999 году, и только в 2013 году разработчики Safari придумали собственную механику.

836f02c2c6f97d1f2183b5d7af0d335c.gif

body {
  scrollbar-base-color: #C0C0C0;
  scrollbar-3dlight-color: #C0C0C0;
  scrollbar-highlight-color: #C0C0C0;
  scrollbar-track-color: #EBEBEB;
  scrollbar-arrow-color: black;
  scrollbar-shadow-color: #C0C0C0;
  scrollbar-darkshadow-color: #C0C0C0;
}


Box-Sizing


Internet Explorer изначально реализовал эту модель так, словно box-sizing: border-box установлен по умолчанию. Хотя многим подход Microsoft показался более логичным и удобным, но CSS WG в конечном счёте выбрала другое значение по умолчанию, где width относится не к внешней ширине блока, а к ширине контента внутри.

4d6a4350294d67dff4765e326f1bdf04.png

«Логично, что блок измеряется от края до края. Возьмите физическую коробку, любую коробку. Положите внутрь какой-нибудь предмет, который значительно меньше коробки. Попросите любого измерить ширину коробки. Он измерит расстояние между краями коробки («границы»). Никому и в голову не придёт измерять содержимое внутри. Веб-дизайнеры, создающие блоки для контента, заботятся о видимой ширине блока, о расстоянии от границы до границы. Именно границы, а не контент, являются визуальными сигналами для пользователей. Никого не интересует ширина контента».


Только в IE 6 добавили дополнительный режим рендеринга, на этот раз совместимый со стандартом. Он не был включен по умолчанию, чтобы не испортить старые макеты. Его нужно было специально выбрать объявлением doctype в начале HTML-документа (аналог 'use strict'; в JavaScript).

Сегодня все возвращаются обратно к модели IE, переопределяя термины в самом начале CSS:

html {
  box-sizing: border-box;
}

*, *::before, *::after {
  box-sizing: inherit;
}


CSS Expressions


До седьмой версии у Internet Explorer была отличная функция под названием CSS Expressions, выражения CSS, также известные как «динамические свойства». По сути, это были фрагменты JavaScript, завёрнутые в функцию CSS, а результат вычисления в этой функции становился значением свойства CSS. Их можно рассматривать как один из предшественников CSS Houdini и функции calc() и других функций.

Например, можете написать собственные функции min() и max():

width: expression(Math.min(this.parentElement.clientWidth, 400) + 'px');


Приведённый выше код устанавливает ширину элемента равной ширине родителя до тех пор, пока она не превысит 400 px. На этом она остановится, примерно как действует max-width. Ключевое слово this ссылается на текущий элемент.

Поскольку IE поддерживает псевдоэлементы только с восьмой версии, вы можете использовать выражения CSS для их «полифиллинга», например:

zoom: expression(
    this.runtimeStyle.zoom = '1',
    this.insertBefore(document.createElement('span'),(this.hasChildNodes()
                        ? this.childNodes[0]
                        : null)).className='before',
    this.appendChild(document.createElement('span')).className='after'
  );


Приведённый код присваивается относительно постороннему CSS-свойству zoom. Первым делом он отключает дальнейшее выполнение выражения, заменив его статическим значением 1. Это предотвращает создание всё новых и новых элементов с каждым новым запуском. Затем создаёт элементы , которые вводит в начале и в конце своей области содержимого, с именами классов .before и .after. Internet Explorer 8 был первой версией, которая поддерживала псевдоэлементы, но в то же время отказалась от поддержки CSS-выражений, поэтому приведённый код не повредит браузерам с псевдоэлементами.

От CSS-выражений в IE практически сразу отказались, потому что они быстро приобрели плохую репутацию. Всё дело в том, что с помощью CSS-выражений очень легко нагрузить CPU и снизить скорость рендеринга. «Проблема» с выражениями CSS заключалась в том, что они выполнялись после каждого события, зарегистрированного браузером, включая изменение размера, прокрутку и перемещение мыши. Посмотрите на следующий пример:

background: expression('#'+Math.floor(Math.random()*16777216).toString(16));


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

Your browser does not support HTML5 video.


Видите, как цвет фона изменяется при каждом движении мыши? Это действительно плохо сказывается на производительности, поэтому ведущие специалисты по веб-разработке советовали не использовать выражения CSS или заменить их реальным JavaScript. Однако в те дни немногие хорошо разбирались в написании JavaScript, включая меня. Сегодня я бы сказал, что всё зависит от качества кода: можно нагрузить CPU и плохим кодом JavaScript тоже. Одно из решений проблемы показано в коде псевдоэлемента, где выражение отключается после первого запуска, присваивая статическое this.style или this.runtimeStyle (ещё одно фирменное изобретение Microsoft, представляющее объект style с ещё более высоким приоритетом в каскаде CSS, чем встроенные стили). Если значение должно остаться динамическим, вы могли изменить код — и выполнять дорогостоящие вычисления только когда это необходимо:



Но почему не использовать простой JavaScript? Действительно, всё это можно делать на чистом JavaScript. Но выражения легче запустить для многих различных типов элементов, поскольку вы можете использовать селекторы. А для псевдоэлементов выражение polyfill в CSS имеет ещё больше смысла, потому что здесь же создаются и реальные псевдоэлементы. Так что всё зависит от обстоятельств.

Шрифты


Internet Explorer также был первым браузером, который позволил использовать произвольные шрифты. Соответствующее правило @font-face появилось CSS 2.0, но его удалили в CSS 2.1, поскольку поддержка браузерами оказалась слишком плохой. Microsoft продолжала поддерживать его и связала с новым форматом файлов, который разработали вместе с компанией-разработчиком шрифтов Monotype: это Embedded OpenType (EOT). Формат EOT должен был решить эти проблемы с двух сторон. С одной стороны, средства разработки вроде Microsoft Web Embedding Fonts Tool (WEFT) принимали только исходные шрифты, не отмеченные флагом no embedding. Таким образом, создатели шрифтов могли запретить их использование в интернете. С другой стороны, во время создания вы указываете список разрешённых URL-адресов для шрифта, а браузер будет проверять его и отображать шрифт только в том случае, если текущий URL-адрес совпадает с адресом в списке.

В 2008 году Microsoft и Monotype передали EOT для стандартизации в W3C. Но в конечном счёте разработчики других браузеров его не поддержали, поскольку вместо стандартного алгоритма сжатия gzip он (тогда) использовал запатентованный алгоритм MicroType Express. Поэтому вместо этого они попросили W3C разработать другой формат встраивания шрифтов, только на основе gzip, и так в 2010 году появился формат WOFF.

«Вместо того, чтобы внедрять в шрифт URL документа, он использует функцию HTTP (origin), которая позволяет задать доменную часть URL документов: менее точно, чем полный URL, но достаточно для большинства производителей шрифтов. В конце концов, WOFF всё же принял части алгоритма MicroType Express и новый алгоритм сжатия Brotli, чтобы увеличить степень сжатия по сравнению с gzip».


Интересный факт: когда вы хотите встроить шрифты в презентацию PowerPoint 2007 или 2010, шрифты встраиваются в файл .pptx в формате EOT.

HTML-компоненты: Attached Behaviors, Element Behaviors и Default Behaviors


Ещё в 1998 году Microsoft предлагала методы, близкие к тому, что мы сегодня знаем как CSS Houdini и Web Components. Они назвались HTML Components:

«В последнее время HTML со скриптами всё чаще используется в качестве прикладной платформы для разработки. Одним из сдерживающих факторов является то, что невозможно было формализовать сервисы приложения HTML или повторно использовать их в качестве компонентов на другой HTML-странице или приложении. HTML-компоненты устраняют этот недостаток; HTML-компонент (сокращённо HTC) обеспечивает механизм многоразовой инкапсуляции компонента, реализованного на HTML, CSS и JavaScript.

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


На самом деле, работу Microsoft признали образцом prior art в начале обсуждения Web Components.

Первым HTML-компоненты реализовал Internet Explorer 5 в 1999 году, а последним — Internet Explorer 9 в 2010 году.

Всего было три типа HTML-компонентов: Attached Behavior, Element Behavior и Default Behavior.

Attached Behavior


Поведение Attached Behavior работало аналогично CSS Houdini Worklet, где у вас есть файл (.htc), который добавляет новые возможности любому элементу, к которому он присоединён. Само присоединение делается через CSS:

img {
  behavior: url(roll.htc);
}


Файлы .htc состояли из специальной XML-разметки для связи с внешним миром и скриптового блока, который определяет, как будет вести себя элемент. Присоединённый элемент DOM был представлен как глобальный element. Следующее Attached Behavior в примере ниже адаптировано для элементов изображения и будет менять их источник каждый раз, когда наводится курсор мыши (спасибо за помощь автору всех последующих примеров Джасперу Пьерру):




Element Behavior


Element Behavior идёт чуть дальше: он переносит в файл .htc не только поведение, но и разметку, тем самым создавая пользовательский элемент. Это очень похоже на элементы Custom Elements в стандарте Web Components. Они тоже снаружи выглядят тривиальными (Light DOM), но внутри скрывают сложную структуру Shadow DOM. Версия Shadow DOM от Microsoft называется Viewlink. Поддержку Viewlink нужно указать явно (opt-in). Как и Shadow DOM, она защитит внутреннюю структуру от любых стилей документа или внешних скриптов, которые пытаются ею манипулировать.

«Viewlink — функция Element Behavior, которая позволяет писать полностью инкапсулированные динамические HTML (DHTML) поведения и импортировать их в качестве надёжных пользовательских элементов на веб-странице».


Для Element Behavior уже было недостаточно привязать элемент HTML к поведению средствами CSS. Вместо этого приходилось использовать возможности XML, создавая для пользовательских компонентов новое пространство имён:




  


custom — это произвольное название пространства имён XML. Тег делает то, для чего мы ранее использовали CSS: ссылается на файл .htc с кодом этого компонента. В файл .htc нужно было добавить ещё несколько частей:

  1. Определить пользовательский HTML-тег, под которым будет использоваться элемент:
  2. Определить любые атрибуты HTML, которые допускает этот элемент, например:
  3. Добавить внутреннюю разметку вашего элемента аналогично современному элементу