Абстракции с нулевой стоимостью в разработки веб-интерфейсов
Перевод | Автор оригинала: Pascal Hertleif
Одна из самых удивительных особенностей компиляторов - это их способность не только преобразовывать код в машиночитаемые объекты, но и оптимизировать абстракции.
Такие языки, как C++ и Rust, рекламируют нечто, называемое «абстракциями с нулевой стоимостью»:
В целом реализации C++ подчиняются принципу нулевых накладных расходов: то, что вы не используете, вы не платите […]. И еще: то, что вы используете, лучше написать код не получится. - Бьярне Страуструп1
Это может быть очень мощно, как итераторы, которые компилируются в машинные инструкции, эквивалентные таковым из вручную закодированных циклов (или gotos), или библиотека Futures, которая компилируется до конечных автоматов2. «Нулевая стоимость» означает «отсутствие затрат во время выполнения»; за эти функции обычно приходится платить за время компиляции, сложность реализации (компилятора или библиотеки) или за знания, которые вам необходимы как разработчику. Такой же уровень оптимизации обычно невозможен в интерпретируемых языках, таких как JavaScript или Ruby. Некоторые реализации JIT-компиляторов могут оптимизировать удивительно сложный код3, но вы, как разработчик, не можете на это полагаться.
Проблема вздутия живота
Зная это, иногда довольно сложно понять, на что похожа разработка веб-интерфейса.
Допустим, вы хотите создать новый статический веб-сайт для своего садоводческого бизнеса. Легко: добавьте начальную CSS-структуру для выравнивания и панель навигации, новую блестящую галерею JavaScript, которая также содержит некоторые изображения и код CSS, а затем, когда вы решите действительно принять современные веб-стандарты, включите несколько полифилов для таких вещей, как теги изображений, плавная прокрутка и Fetch API. Это, конечно, все складывается, и вы получите много вещей, которые будут загружены, хотя текущая страница в этом не нуждается. Если вы думаете, что это плохо, попробуйте представить, что включают в себя эти модные темы WordPress за 40 долларов или сколько JavaScript нужно включить для современного одностраничного приложения.
Я думаю, что это можно улучшить, и некоторые технологии для этого уже существуют. Например, такие инструменты, как критический css и Closure Compiler, уже могут избавиться от некоторых неиспользуемых CSS / JS. Однако использовать это в наших интересах не так просто, и, конечно, не по умолчанию для большинства разработчиков.
Отслеживание точных зависимостей
Мое первое утверждение таково: если бы мы лучше указали, от чего зависят элементы нашего веб-сайта4, мы могли бы получить гораздо больше абстракций бесплатно. Предположим, что наш элемент «основной навигации» указывает, что ему нужна сетка начальной загрузки (и только сетка), собственный небольшой модуль JavaScript (который зависит только от библиотеки медиа-запросов без внешних зависимостей) и собственный модуль CSS (есть модули CSS. spec), мы можем разрешить все эти зависимости и получить только то, что нам действительно нужно.
Лучшие компиляторы
Следующий шаг - использовать лучшие компиляторы и инструменты сборки.
Для JavaScript с помощью babel можно преобразовать код ES2017 во что-то, что может анализировать Internet Explorer 11, а UglifyJS2 - хороший минимизатор для сохранения драгоценных байтов размера файла, но оба они не подходят для оптимизирующих компиляторов, таких как Google Closure Compiler. В любом случае сравнение не совсем справедливо: компилятору Closure требуется много аннотаций, чтобы иметь возможность использовать все его оптимизации (например, строгое удаление мертвого кода и встраивание). К счастью, я почти не вижу причин, по которым эти аннотации не могут быть созданы на основе информации о типах, доступной при написании кода на TypeScript.
Ориентируясь на CSS, мне нравится, насколько мощным является SASS. К сожалению, он не имеет понятия об отслеживании зависимостей, как модули CSS, а это означает, что написание «логотипа» @import дважды означает, что код вводится дважды. PostCSS выглядит как надежная основа для написания преобразователей кода CSS, но я не использовал ее.
В конце концов, нужно будет исключить дубликаты CSS, встроить соответствующие ресурсы и оптимизировать, когда вся страница будет построена.
Отличный опыт разработчика
Для меня это означает две вещи:
- Быстрые инкрементальные сборки
- Читаемые, значимые ошибки, которые легко отлаживать
Я даже не говорю о горячей перезагрузке кода или написании целой кучи документации. Просто сделайте это быстро во время разработки (не оптимизируя JS) и выводите отлаживаемый код (с помощью SourceMaps).
Будет добавлено больше контента.
-
Страуструп Б. (2012, март). Основы C++. В Европейском симпозиуме по программированию (стр. 1-25). Springer Berlin Heidelberg.
-
См. Футуры с нулевой стоимостью в Rust
-
Например: замечательный JIT-компилятор трассировки LuaJIT может оптимизировать сложный функциональный код с помощью luafun (библиотеки для написания функционального Lua) в действительно эффективный машинный код (см. Их Readme).
-
Я имею в виду только статические страницы и надеюсь, что мы сможем их использовать.
Спасибо за чтение.