Пишу, по большей части, про историю, свою жизнь и немного про программирование.

Сжатие JavaScript с использованием PNG и Canvas

Jacob Seidelin в своём блоге «Nihilogic» опубликовал небезынтересную статью, где он рассказывает о своих экспериментах по сжатию кода JavaScript при помощи Canvas и PNG.

Идея простая, из разряда «как мне раньше не пришло это в голову». JavaScript переводится в последовательность байт, которая записывается как изображение. Изображение сохраняется в PNG-формате, в PNG используется довольно эффективное сжатие, что даже при расходах на заголовок даёт ощутимые результаты — известная библиотека Prototype (124 килобайта) стала занимать всего 30 килобайт в восьмибитном PNG-файле. Каждый пиксель в 24-битном PNG позволяет хранить три байта информации, в 8-битном формате — один.

Далее PNG-изображение загружается в тег CANVAS (нужный функционал поддерживается FireFox, WebKit/Safari и бета-версией «Оперы») и считывается попиксельно функцией getImageData, после чего полученный код выполняется (eval) и мы получаем исходный JavaScript.

Единственный недостаток метода — скорость. Извлечение скрипта в 255Кб может занять несколько секунд, что, впрочем, не всегда является проблемой.

32 комментария
indeyets.livejournal.com 2008

ты уверен, что deflate сжимает хуже? ;)

romik-g.livejournal.com 2008

Это из разряда brain fuck что-то... практической ценности не вижу =)

Евгений Степанищев (bolknote.ru) 2008

Комментарий для indeyets.livejournal.com:

Так же. Был бы он ещё везде, этот deflate :)

Евгений Степанищев (bolknote.ru) 2008

Комментарий для romik-g.livejournal.com:

Всё просто — сжимать JavaScript.

Slaver (slaver.info) 2008

Бред!

bealex.livejournal.com 2008

А LZW на JS еще никто не реализовал?

victorgr.livejournal.com 2008

Комментарий для Евгения Степанищева:

Сжимать JavaScript... А зачем его сжимать таким способом?

Какие преимущества несёт данный способ перед обычным gzip/deflate-сжатием?

Евгений Степанищев (bolknote.ru) 2008

Комментарий для slaver.info:

ага :)

Евгений Степанищев (bolknote.ru) 2008

Комментарий для bealex.livejournal.com:

Медленно, думаю, будет :)

Евгений Степанищев (bolknote.ru) 2008

Комментарий для victorgr.livejournal.com:

Во-первых, это способ из разряда «а ещё вот так можно», т. е. практического применения, возможно, у него никакого :)

Во-вторвых, на хостингах, где нет сжатия файлов и не подключены языки программирования, это выход.

david-m.livejournal.com 2008

«В PNG используется довольно эффективное сжатие» — да, только эффективно оно для изображений (то есть, предполагается что соседние писели не сильно отличаются и т. п.). Битовый «шум», полученный из JS, сожмётся не лучше чем простым гзипом. Что мы, вероятнее всего и наблюдаем.

Хотя конечно, сама идея, что и так тоже можно выпендриться — она внушаетъ:)

Евгений Степанищев (bolknote.ru) 2008

Комментарий для david-m.livejournal.com:

PNG использует тот же deflate, который в gzip :)

o4kapuk (o4kapuk.ru) 2008

Феерично. Наверняка эта возможность будет проверяться в ACID4 :)

maxim-zotov.livejournal.com 2008

Был бы он ещё везде, этот deflate :)

И где это его нет?

Сделал страницу
http://maxim.rusf.ru/cmp.html
проверил во всех доступных мне в 3 часа ночи браузерах, работает везде кроме Netscape 3.04/Linux (есть такое чудо у меня).

Linux:
Firefox 1.0
Firefox 2.0
Opera 9.1

Windows XP:
MSIE 6.0
Opera 9.0

Windows Vista:
MSIE 7.0

Windows CE (КПК то бишь):
MSIE 4.0

Телефон Nokia 6300:
Какой безымянный встроенный браузер
Opera Mini 4.0

Есть у вас что-то, не аналогичное по идиотизму 3-му Нетскейпу, где на <a href=» http://maxim.rusf.ru/cmp.html%22%3E%D1%8D%D1%82%D0%BE%D0%B9 странице</a> не выдалось бы «OK, gzipped JS is supported»?

maxim-zotov.livejournal.com 2008

Комментарий для Евгения Степанищева:

на хостингах, где нет сжатия файлов и не подключены языки программирования

Зачем для выкладывания файла script.js.gz нужны какие-то там языки программирования или «сжатие файлов на хостинге»?

Евгений Степанищев (bolknote.ru) 2008

Комментарий для maxim-zotov.livejournal.com:

Не в браузерах его нет, а на хостингах может и не быть.

Евгений Степанищев (bolknote.ru) 2008

Комментарий для maxim-zotov.livejournal.com:

Для этого .gz должен быть прописан заголовок content-encoding и правильный content-type.

maxim-zotov.livejournal.com 2008

Комментарий для Евгения Степанищева:

Корректная выдача заголовков для gz и тип для js прописаны в конфигах «из коробки» в самом массовом сервере — Апаче. Нужно специально приложить усилия, чтобы _не_ работало, а не дополнительно настраивать, чтобы работало.

Может быть, конечно, вебмастера сначала выкидывают всё из конфига, а потом начинают по строчке добавлять, не знаю.

Евгений Степанищев (bolknote.ru) 2008

Комментарий для maxim-zotov.livejournal.com:

Многим нужно чтобы файлы .gz просто скачивались, а не распаковывались в браузер. Так как это — просто архивы в одном из распространённых форматов во всяких Линуксах.

Кроме того, я не защищаю этот метод. Мне он просто нравится, он остроумен.

shoorick.livejournal.com 2008

Комментарий для maxim-zotov.livejournal.com:

Не работает:

Browser: Mozilla/5.0 (compatible; Konqueror/3.5; FreeBSD; X11; i386; en_US, ru) KHTML/3.5.8 (like Gecko)
Result: external script is not loaded

Евгений Степанищев (bolknote.ru) 2008

Комментарий для shoorick.livejournal.com:

А разве где-то написано, что под KHTML будет работать?

maxim-zotov.livejournal.com 2008

Комментарий для shoorick.livejournal.com:

«Не работает:»

Жаль.

maxim-zotov.livejournal.com 2008

Комментарий для Евгения Степанищева:

«А разве где-то написано»

Да, я считал, что script.js.gz сработает в любом современном браузере.

maxim-zotov.livejournal.com 2008

Комментарий для Евгения Степанищева:

«Многим нужно чтобы файлы .gz просто скачивались, а не распаковывались в браузер. Так как это — просто архивы в одном из распространённых форматов во всяких Линуксах.»

Если то, что сжато гзипом, не должно отображаться в браузере, оно не отобразится. gzip — это не формат архива, это формат сжатия. Архив (набор файлов) — это tar. У файлов tar mime-тип application/x-tar, поэтому он не отображается, а скачивается.

Если вы сжимаете файл html или txt, то он, разумеется, отобразится. И было бы очень нелогично, если бы не отображалось, а скачивалось. Это ведь html и текст, с какой стати оно должно скачиваться?

Если человек выкидывает из конфига веб-сервера поддержку content-encoding gzip’а, скорее всего, он не понимает, что делает, и пытается добиться какого-то своего результата неправильным способом.

Евгений Степанищев (bolknote.ru) 2008

Комментарий для maxim-zotov.livejournal.com:

Я знаю всё про gzip, tar и MIME-заголовки. Я же хакер.

Не вижу ничего нелогичного в том, что .html.gz или .txt.gz должен скачиваться, а не распаковываться. Если я указываю браузеру, что файл должен скачаться, я знаю что я делаю. Значит этот txt или html не предназначен для того, чтобы читать его из браузера, например, там очень большой текст, который 99% скачает и откроет на PDA/телефоне/любом наладонном устройстве.

Евгений Степанищев (bolknote.ru) 2009

Комментарий для bealex.livejournal.com:

Реализовали :)

Александр Бабаев (bealex.moikrug.ru) 2009

Комментарий для Евгения Степанищева:

Хех, скорость ответа — пять баллов.
А насколько оно адекватно? В смысле, например, крупных AJAX-ответов? Тестов не было? Или просто блочный lzw передавать в условиях потоковой передачи… не?

/Перечитал — какой-то бред несу, но пускай остается для потомков/

Евгений Степанищев (bolknote.ru) 2009

Комментарий для bealex.moikrug.ru:

Ага узнал, так и сообщил :))

Оно вполне адекватно и хорошо сжимает. Но есть загвоздка — скорость распаковки даже какого-нибудь prototype (чуть больше 100КБ) может достигнуть секунд под не шустром браузером на не шустром ноуте.

Александр Бабаев (bealex.moikrug.ru) 2009

Комментарий для Евгения Степанищева:

То есть в идеале надо бы анализировать скорость ответа (соединения) и в зависимости от нее — выбирать тот или иной способ упаковки… Да еще и зависимость получается нелинейная. Дамс, проще забить. :) Но сама мысля — интересна.

Диман 2012

Единственный недостаток метода — скорость.

Это не единственный недостаток, ie только с 9-ого поддерживает canvas.
А так очень эффективный способ сжатия.

plutov.by 2013

Спасибо за материал. А я вот так автоматизировал процесс сжатия — http://plutov.by/post/js_css_auto_compress

Евгений Степанищев (bolknote.ru) 2013

Комментарий для http://plutov.by:

А почему вы не используете что-нибудь готовое? Например: http://gruntjs.com