Подтвердить что ты не робот

Решение для конвейера 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 см. в следующих связанных вопросах:

4b9b3361

Ответ 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, все остальное приведет к проблемам.