Как включить данные UTF-8: URI (для SVG) в LESS?

Рассуждение

Я объединяю небольшие минимизированные SVG (значки) с моим CSS через метод LESS data-uri, чтобы уменьшить HTTP-запросы, аналогичные назначению шрифтов-иконок, таких как Octicons или старые CSS-спрайты.

Однако LESS кодирует их в Base64.
Это неоптимально в случае SVG. , который может быть URI данных в кодировке UTF-8 (пример).

Есть три причины, почему это неоптимально:

1: Base64 глуп для текста

Цель Base64 — кодировать двоичные данные, используя всего 6 бит на байт, что делает их безопасными для встраивания в текстовые файлы. Это отлично подходит для PNG и JPEG, но увеличивает размер любого текстового файла на 33% без всякой причины. Если вы сейчас думаете: "Ну, gzip об этом позаботится", то имейте в виду, что...

2: Кодирование текста в Base64 делает gzip намного менее эффективным

Чтобы понять, почему это так, рассмотрим следующее:

btoa('width')   === 'd2lkdGg='
btoa(' width')  === 'IHdpZHRo'
btoa('  width') === 'ICB3aWR0aA=='

В качестве практического примера возьмем реальный SVG и поэкспериментируем с ним:

$ wc -c *
68630 tiger.svg
25699 tiger.svg.gz
91534 tiger.txt
34633 tiger.txt.gz

Даже после сжатия он все еще примерно на 35% больше.

3: Он игнорирует некоторые бесплатные источники избыточности.

Подумайте о примере width выше. Каждый SVG будет иметь эту подстроку, и если вы встроите SVG в CSS, у вас, вероятно, будет это ключевое слово где-то еще (или в других), от которого gzip может быть полезно (потому что именно так Кодирование Хаффмана работает), но не в том случае, если оно скрыто Base64.


Вопрос

Как встроить SVG в LESS как data: URI, используя UTF-8 вместо Base64?

Я могу представить тысячу способов сделать это с помощью инструментов сборки, таких как Grunt, но это нарушает мой рабочий процесс, потому что я не буду возможность делать такие вещи, как style: include:less all.less из представления Jade (я делаю это в процессе разработки) или даже просто @import 'images.less'; из меньше файла.


person Camilo Martin    schedule 04.09.2014    source источник
comment
jsfiddle.net/estelle/SJjJb недействителен. Вам нужно закодировать зарезервированные символы URI, такие как #, чтобы он работал правильно. Base64 избегает этого FWIW.   -  person Robert Longson    schedule 04.09.2014
comment
@RobertLongson Это работает в Chrome. И после экранирования #, как вы упомянули, я мог заставить его работать и в Firefox. Также нормально в Опере и Сафари. Не знаю, что думать об IE. Он хоть поддерживает?   -  person Camilo Martin    schedule 04.09.2014
comment
Между прочим, одно решение, которое мне не очень нравится, потому что оно не сжимает намного лучше, когда у вас есть много SVG, встроенных в одну таблицу стилей, состоит в том, чтобы сначала преобразовать SVG в SVGZ. Также не поддерживается IE.   -  person Camilo Martin    schedule 04.09.2014
comment
@RobertLongson Это не ошибка, это функция! А Safari — это по-прежнему Webkit, это Chrome, а Opera — это Blink. (И Опера была Престо).   -  person Camilo Martin    schedule 04.09.2014
comment
Вы не можете использовать svgz в URI данных. Однако IE поддерживает svgz как внешний файл.   -  person Robert Longson    schedule 04.09.2014
comment
Нет, это ошибка. В соответствующих спецификациях четко указано, как это должно работать, а Chrome/Safari/Opera это не соответствует. Blink — это форк Webkit.   -  person Robert Longson    schedule 04.09.2014
comment
@RobertLongson IE не поддерживает SVGZ; просто случается, что SVGZ можно спутать с обычным SVG из-за того, что gzip уже используется для большей части веб-контента. Но что значит нарушение спецификации? В Википедии упоминается, что вы можете 'data:text/csv;charset=UTF-8,' + encodeURIComponent(csv), что не так уж далеко от этого примера, чтобы не отказываться от избыточности.   -  person Camilo Martin    schedule 04.09.2014
comment
Отредактировано с примером, который работает в кроссбраузерном режиме. Все еще выигрывает в значительной степени от третьего пункта, который я сделал.   -  person Camilo Martin    schedule 04.09.2014
comment
@RobertLongson Да, но с encodeURIcomponent или подобным вы решаете эту проблему. Я опубликовал скрипт, который работает для IE, но TBH Webkit просто хорошо работает (data: URI не нуждаются в фрагментах, поэтому нет необходимости анализировать фрагменты, т. Е. Он допускает ввод, несмотря на строгость спецификации). В любом случае, я нашел способ сделать это! И с кодировкой URI или без, он все равно выигрывает от сжатия гораздо больше, чем Base64.   -  person Camilo Martin    schedule 04.09.2014
comment
Согласно RFC 3986, идентификатор фрагмента должен работать независимо от схемы. tools.ietf.org/html/rfc3986#section-3.5   -  person Robert Longson    schedule 04.09.2014
comment
@RobertLongson Да, и Javascript должен был идти с CDATA. Но я понимаю вашу точку зрения, и, честно говоря, я согласен с тем, что нужно следовать спецификации просто потому, что это лучше, чем каждый гадает со своим собственным суждением и придумывает кучу несовместимых идей. Так что да, ты прав.   -  person Camilo Martin    schedule 05.09.2014


Ответы (1)


Я идиот. Это просто:

data-uri('image/svg+xml;charset=UTF-8', 'path/to.svg')

Мне пришлось прочитать исходный код LESS чтобы разобраться в этом.

Все преимущества, о которых я упоминал выше, достигаются здесь, в частности, если у вас есть множество маленьких SVG, они выиграют от избыточности друг друга. И это работает во всех браузерах.

person Camilo Martin    schedule 04.09.2014
comment
На самом деле вы не одиноки, я сомневаюсь, что кто-либо из команды Less знает об этой возможности :) Хотя тот факт, что вы можете установить mimetype в первом параметре задокументирован, это довольно редко используемая фича и не столь широко известный формат, о котором нужно помнить... - person seven-phases-max; 05.09.2014
comment
@ семь-фаз-макс Что вы имеете в виду, я ожидаю, что команда LESS знает, что это можно сделать ... Я имею в виду, они написали код. Но даже когда я прочитал эту документацию, все стало ясно только после просмотра источника. - person Camilo Martin; 05.09.2014
comment
› Я имею в виду, они написали код. - Не каждую строку. Не забывайте: при разработке с открытым исходным кодом каждый может отправить код. Очевидно, что пока ребята из основной команды просматривают представленный код, они могут не знать о каждом конкретном скрытом перле :) - person seven-phases-max; 05.09.2014
comment
@seven-phases-max Ну, действительно! Думаю, мне нужно больше практиковаться в командной работе, лол. - person Camilo Martin; 05.09.2014
comment
Любопытно, что (в современных браузерах) data-uri SVG может вообще не нуждаться в какой-либо кодировке (просто тонкое экранирование) -> codepen. - person seven-phases-max; 08.09.2014
comment
@seven-phases-max Боже мой, это впечатляет! Я не знал, что LESS может это сделать. Но, тем не менее, не работать в IE ужасно, потому что это можно исправить простым кодированием URL. - person Camilo Martin; 08.09.2014
comment
О, спасибо за сообщение об IE, в настоящее время идет обсуждение, если это незакодированное Поддержка data-uri для внешнего SVG должна быть включена в Less. - person seven-phases-max; 08.09.2014
comment
@seven-phases-max Я бы хотел, чтобы они просто запускали браузеры, чтобы решать такие вещи: P Например, потрясающая генерация SVG в вашей кодовой ручке. - person Camilo Martin; 10.09.2014