Решение для конвейера Rails для IE 4096. Селектор/лимит таблиц стилей
Проблема
Документация поддержки Microsoft IE объясняет, что в Internet Explorer 6-9:
- Все теги стиля после первых 31 тегов стиля не применяются.
- Все правила стиля после первых 4095 правил не применяются.
- На страницах, которые используют правило @import для непрерывного импорта внешних таблиц стилей, которые импортируют другие таблицы стилей, таблицы стилей, содержащие более трех уровней, игнорируются.
Существует много свидетельств этой проблемы с script demos. См. Также Bless.
Необходимое решение
Нам нужен способ разделить скомпилированные таблицы стилей, созданные Sprockets в конвейере активов, чтобы сохранить максимальный селектор ниже 4096 и связать их с HTML в развернутом Rails-приложении. Как мы можем передать скомпилированный вывод обработанных активов (в частности, таблиц стилей) в качестве аргумента для метода, который может затем модифицировать файлы?
См. приведенные ниже попытки начать создание места. Если кто-то может помочь мне найти способ сделать либо оперативное (или совершенно новое решение), это будет фантастично!
Существующие попытки решения
-
Bless был создан для решения этой проблемы путем разделения таблиц стилей, чтобы сохранить максимальное количество селекторов на листе под лимитом, Bless запускается на сервере в node.js. Я еще не видел эквивалент Ruby. Эрик Филдс пытался обслуживать активы, скомпилированные с компасом, для Bless (работает в node), но это решение зависит от компиляции активов Compass и таким образом, похоже, не работает с конвейером активов. Обратите внимание, что вместо привязки к нескольким таблицам стилей Bless добавляет операторы @include
к первому листу, что может быть способом сделать так, чтобы не касаться разметки.
-
Когда Christian Peters (@crispy) обнаружил эту проблему, он реализовал splitter, например Bless, который также передал вывод Compass в пользовательский модуль, который отлично работал перед Rails 3.1. Позже он адаптировал свой сплиттер с помощью SprocketsEngine для интеграции с конвейером Rails Asset. Я пробовал реализовать новый код, но он не работает автоматически (хотя сплиттер отлично работает при вызове вручную в консоли).
Дополнительная информация
Дополнительные сведения о ограничениях CSS в IE 6-9 см. в следующих связанных вопросах:
Ответы
Ответ 1
У нас есть автоматическое (хотя и неудобное) решение, работающее на производстве для приложения Rails 3.1 с конвейером активов. Райан уже ссылался на решение в своем вопросе, но я стараюсь дать более исчерпывающий ответ.
Конвейер активов передает ресурс с помощью разных двигателей Sprocket.
Итак, у вас может быть, например, a ie.css.sass.erb
, который проходит через движок звездочки ERB, а затем передается движку Sass Sprocket и т.д. Но это всегда один файл и один файл.
В этой специальной задаче мы хотели бы иметь 1 входящий файл и n исходящих файлов.
Мы не нашли способ сделать это возможным с помощью звездочек. Но мы нашли обходное решение:
Предоставьте ie.css.sass
, который включает полную таблицу стилей и ie_portion2.css.sass.split2
, которая просто импортирует полный файл ie.css:
//= include 'ie.css'
Для расширения файла split2
мы зарегистрируем движок Sprockets Engine:
require 'css_splitter'
Rails.application.assets.register_engine '.split2', CssSplitter::SprocketsEngine
При оценке активов с расширением split2 мы передаем его содержимое в CssSplitter и инструктируем его извлечь часть 2 ( > 4095 селекторов):
require 'tilt'
module CssSplitter
class SprocketsEngine < Tilt::Template
def self.engine_initialized?
true
end
def prepare
end
def evaluate(scope, locals, &block)
part = scope.pathname.extname =~ /(\d+)$/ && $1 || 0
CssSplitter.split_string data, part.to_i
end
end
end
Это также будет работать для дальнейших частей (split3,...).
Разделитель CSS распознает допустимые места, где таблицы стилей можно разделить на части с селекторами менее 4096 и вернуть запрошенную часть.
Результатом является ie_portion2.css, который вы должны связать в голове и предварительно скомпилировать отдельно.
Я надеюсь, что мой пересмотренный CSS Splitter Gist будет достаточно полным, чтобы использовать решение.
Update:
Сегодня упоминание о CssSplitter было выпущено как драгоценный камень: https://github.com/zweilove/css_splitter
Ответ 2
Решение, которое я использую в производстве, очень просто, не автоматизировано, но работает очень хорошо.
Для меня это было очевидным делом, поэтому, возможно, вы об этом подумали и не понравились - в любом случае, здесь мы идем:
Я предполагаю, что вы используете sass, если нет, я думаю, вам нужно:)
Сначала, разделите application.css.scss
в отдельных файлах, например:
application_a.css.scss
и application_b.css.scss
Второй, в файле application.css.scss
используйте:
@import "application_a"
@import "application_b"
Третий, в вашем шаблоне макета, включите либо полный файл, либо обе части:
<!--[if !IE]><!-->
# link to application.css.scss
<!--<![endif]-->
<!--[if IE]>
# link to application_a.css.scss
# link to application_b.css.scss
<![endif]-->
Боковое примечание:
Не создавайте файлы манифеста стилей через конвейер активов, делайте это с помощью sass и оператора @import
, все остальное приведет к проблемам.