Как стать автором
Обновить

Комментарии 73

Это не минимальная работа для сервера, а очень значитальная разница в использовании ресурсов. Одно дело отдать просто несколько килобайтный js статический файл при помощи nginx, другое дело — nginx передаёт запрос Apache, тот подгружает кучу библиотек, парсит скрипт, запускает php, отрабатывает его, отдаёт nginx и nginx уже отдаёт клиенту. А ещё ведь nginx сам заголовки ставит нормально.

Вывод — это кошмар и ужас. Так делать не стоит.
Но речь как раз и идет о том, чтобы разделить файлы, которые будут отдаваться статически и файлы, в которых будет отрабатывать PHP. Количество таких «гибридных» динамических скриптов минимальное, они нужны не всегда и потому, в зависимости от расширения, их может отрабатывать Apache. nginex при этом будет делать свою работу, а ничего никуда не передавать.
Проще в страницу встраивать то что нужно.
Результат подобной оптимизации — HTML, PHP, JS в одном файле. Приходилось подобное встречать, по 4000 строк в файле. Сомневаюсь что это лучший вариант, хотя доводы в первом комментарии и понятны.
Я думаю что пользователю неважно как он получит работающее приложение. Однако серверу имеет значение, что отдавать, просто файлик пнуть с диска или из кэша операционки/nginx или совершить кучу ненужной работы.
Мы говорим об одном и том же ))) Этот метод точечный, по необходимости. Кроме того, кеширование действительно никто не отменял. А так же есть еще удобство разработки и сопровождения. Кроме всего прочего, в подавляющем большинстве веб-приложений речь не идет о критических нагрузках, когда 1-2 динамически обработанных скрипта перевернут сервер. В конце-концов, железо должно отрабатывать свои деньги )))
Вы абсолютно правы. Кроме того, такие скрипты можно подгружать динамически в процессе взаимодействия пользователя со страницей в браузере. Это собственно и есть AJAX подход — не пересоздавшем всю страницу, а высылаем данные об ее изменении в виде JS-объектов.
Если скрипт JS будет подгружаться в любом случае и необходим для работы страницы, то лучше получить всё через один запрос к странице. С точки зрения пользователя преимущество в скорости, с точки зрения программиста разницы никакой (в простейшем случае будет include).
А если назначить их Nginx-у через fpm, и установить fastcgi_cache, тогда стоит?
Нет, не стоит, потому что это излишнее усложнение. UNIX-way это лучшее что придумало человечество. Если что-то можно сделать проще — так и нужно делать.
Интересно. Главное чтоб при этом был заблокирован аплоад js файлов. А то так и бэкдор повесить могут.
Речь о данных?.. откройте для себя
<?php echo json_encode($data); ?>
Я не понял, что вы хотели мне открыть? :)
Вероятно развитие событий, при которых вы обращаетесь к контроллеру за необходимыми данными, а он отдает и в JSON.

startof nudnik_mode
rPman, только лучше что-то вроде
echo JSON::encode($data);

А то вдруг придется резко расширить функционал под быстро меняющиеся требования :)

endof nudnik_mode
Если Вам действительно нужен динамический js-файл, то генерите его кроном.
То, что в статье, — это ужас.
Слово «ужас» это тренд? )))
Крон это один из вариантов. Также никто не отрицает пользу кеширования.
PHP-код внутри js — это слишком неочевидно. Плюс вырастет нагрузка на сервер засчет того, что файл будет запускать php-интерпртетатор итд. В худшем случае оно будет запускаться не только на Ваш волшебный файл, но и на все другие js-файлы, даже если в них нет php вставок.

Если Вам уж так сильно хочется вставить php-код в яваскрипт, дайте этому файлу другое расширение, например pjs, чтобы было понятно, что это не обычный js-файл, далее обязательно в php-коде сделайте правильную обработку заголовков ETag и If-Not-Modified, ну, и по-возможности включите кеширование на стороне nginx.
> Если Вам уж так сильно хочется вставить php-код в яваскрипт, дайте этому файлу другое расширение, например pjs, чтобы было понятно, что это не обычный js-файл,
У меня сложилось мнение, что вы не прочитали заметку, а решили написать комментарий после первого абзаца.
Re: PHP-код внутри js — это слишком не очевидно.
Не менее не очевидно, чем PHP-код внутри HTML.
ИМХО, самый простой способ — это назвать файл, например, mycode.js.php
По его виду понятно, что этот файл содержит JS и будет «зачем-то» обработан PHP-сервером.
Не менее не очевидно, чем PHP-код внутри HTML.

Ну… Можно xslt, можно шаблонизировать на сервере или клиенте ведь. Однако php — по своей задумке и есть шаблонизатор, так что его появление около html тегов понятно и объяснимо.
PHP код внутри html вполне очевидно — PHP же сам себе шаблонизатор. PHP в javascirip'e это лютый ппц. Это как быдлокодить надо, чтобы до этого дойти?
Для меня PHP внутри html тоже неочевидно :)
По мне, его нужно класть либо внутрь файлов с расширением php, если там только код, либо в phtml, если там html в перемешку с php или, если используется шаблонизатор, то в tpl.
По мне так все файлы с php кодом должны иметь расширение php.
Именно так.
Вот кроном точно бред, лучше уж как автор предложил, только добавить кэш на nginx для таких файлов, равный интервалу вашего крона.
НЛО прилетело и опубликовало эту надпись здесь
Например, при валидации большой формы заказа с многими товарами, когда нужно еще и считать скидки по разным параметрам (за общее количество, за количество лицензий по каждой позиции, плюс акции, особые условия или товары без скидок). Для это используется весьма приличный кусок бизнес-логики, реализованной на JavaScript. Для поддержки актуальности цен, значений скидок и пр. весьма удобно иметь включения PHP-кода, чтобы в случае изменений не заниматься поиском блох.
Субъективно решение выглядит грязно.

Данные о товарах (цены, категории, названия, описания) очень удобно держать в регулярно перегенерируемых json-файлах и отдавать из nginx'ом как статику. А все расчеты скидок всё равно придётся дублировать в PHP, иначе не безопасно, так что здесь лучше использовать простой ajax запрос с параметрами заказа для обсчёта на сервере. Кстати данные для скидочных алгоритмов тоже удобно держать в json-статике.

На хабре давно была отличная статья о решении для большого магазина, где все товары были разделены на 4 регулярно перегенерируемых json-файла по живучести данных (цены меняются часто — в один файл, описания редко — в другой, например). Только линк найти не могу.
Спасибо за толковый комментарий.
Данные о товарах (цены, категории, названия, описания) очень удобно держать в регулярно перегенерируемых json-файлах и отдавать из nginx'ом как статику.


Поясните, пожалуйста, в каком случае? Когда у нас одностраничное приложение на js, которое им же шаблонизируется, визуализируется?
Я просто работал с магазинами и слабо представляю зачем мне js с данными на тридцать тысяч товарных предложений. Хотя там и сложный расчет скидок и карты и складов много, etc в общем.
Данные о товарах и их характеристиках пишутся сильно реже, чем читаются. Значит кэширование выгодно.

Если на фронтенде есть развитые фасеты, пагинация и люди приземляются на страницы категорий сильно чаще, чем на страницы товаров, то имеет смысл начать отдавать на фронтенд сразу все товары (ну или товары сгруппированные по категориям самого верхнего уровня).

Ну и JSON прекрасно поддаётся gzip'у. А при условии, что генерация происходит редко, можно жать даже на девятке.

Плюсы очевидны: сильно меньше нагрузки на сервер, фильтрация и пагинация работают у клиента практически мгновенно.

Есть, кажется, только один не очевидный момент: нужно уметь отдавать готовые страницы уже с данными.
Объясните, пожалуйста, чем для этой цели не подошел json, дергающийся с помощью асинхронного запроса, который генерирует нормальный контроллер?
Откройте для себя метапрограммирование. Значения можно выдергивать из html например, из специальных аттрибутов или скрытых полей.
Повторюсь, что в статье ужас и мне было бы стыдно писать такую статью.
Согласен, но опять таки в HTML эти значения тоже надо положить предварительно. И какая разница, грубо говоря, какой файл обработает интерпретатор?

А про ужас и стыд, по-моему не уместно говорить при обсуждении технических моментов. Я ведь не самоутверждаюсь, а просто описал один из вариантов решения, кстати придуманный не мною. Он, естественно, имеет свои плюсы и минусы.
Согласен data-* как нельзя кстати
В вашей задаче некорректное 'если'. Я поясню.
иногда бывает лучшим решением подключить PHP и сгенерировать содержимое JS-файла «на лету» (например, получить актуальные цены на продукты из БД и передать их JavaScript-программе для валидации формы заказа)

Курсивом выделено некорректное 'если'. В этом случае нам нет никакой необходимости включать php код в js. Это не пример лучших практик, скорее наоборот.
Вашу задачу можно сформулировать так:
как включить обработку php-кода в формате, отличном от .php

Понимаете какая детская задача?

И эти утверждения будут верными, пока вы не приведете живого примера, когда это и правда полезно и несет какую-то выгоду.
Это софистика. Как ни прочитай, все равно постановка выглядит так: «Как, при необходимости, сделать доступным выполнение PHP-кода в таких-то файлах, используя при этом вариации и ограничения». Остальные разговоры притянуты за уши — я ведь не утверждал что это единственно правильное решение. И речь нигде не шла об обсуждении архитектуры какого-то конкретного решения :)
Это не софистика. Я прошу вас привести пример, когда ваше решение имеет право на жизнь, когда оно нужно и удобно. Так просто ведь.

Это критически важно для принятия решения — 'вот, блин фигню сморозил' или 'вот это у него задачи, что он так хитро вывернулся'.
В моем случае ситуация такова. Есть веб-приложение, работающее, продающее, писанное-переписанное давно и многими людьми. Серьезные рефакторинг на данном этапе не поощряется руководителем, полное переписывание возможно в отдаленной перспективе. Тоесть всеми силами приходится бороться с плохой наследственностью. И нет никакой красивой и умной архитектуры, а есть хитросплетение различных методов и заблуждений, которые надо еще умудриться не нарушить, чтобы все продолжало работать. Но при этом приложение надо сопровождать, регулярно внося оперативные изменения.
Спасибо за ответ на мой вопрос.
В таком случае возможно это и служило какой-то цели и сэкономило время/деньги.

Но честное слово, лучше бы вы написали статью о борьбе с кучей лапши, доставшейся вам, чем о том, как .js заставить понимать вставки php кода.
Это уже другой вопрос. Заметка касалась всего-навсего практической стороны вопроса: как сделать то-то и то-то если оно вдруг понадобится :)
Но зато люди хорошо поговорили на различные темы вокруг да около )))
Кстати, не думали подключить все-таки к проекту фреймворк и дописывать логику уже в нормальном стиле? Например yii очень удобен в этом плане.
Вы можете не стартовать веб-приложение, но пользоваться всеми приятностями, в том числе умной автозагрузкой, валидаторами, моделями, etc. Так можно было бы начать процесс переписывания постепенно, маленькими частями.
Не знаю насколько приемлема подобная полумера.
Мне кажется, гораздо лучше параллельно разрабатывать новый вариант, учитывая практические особенности того, что уже работает. А в нужный момент переключиться.
Если финансовые и человеческие ресурсы позволяют, то да, это здорово, но только при наличии толкового менеджера, который вдохновит людей, допиливающих труп, что скоро закопают на усердную работу :)
Пробовал такой подход — очень неудачный. Нужна новая/измененная функциональность «вчера»: забиваем костыль в старый код и внедряем красивое решение в новый (пускай этот кусок уже написан) — двойная работа.

По-моему, тут лучше подойдёт «плавный рефакторинг». Нужна новая/измененная функциональность — рефакторим так, чтобы выделить старую для замены или выделить единственную (в идеале) точку вставки новой. А новую уже пишем по всем правилам. Появилось свободное время, которое сейчас выделяется на новый вариант — просто рефакторим старый в произвольном (утрируя) месте.

Единственное, что такой вариант неприемлем, если новый вариант это не только замена движка, но и изменение юзкейсов и бизнес-логики. Грубо говоря, нельзя оторвать пол рулевого колеса в автомобиле, поставить пол джойстика и сказать пользователю: «езди пока так, как сделаем джойстик — будешь им рулить, а пока начиная поворот баранкой, а потом за джойстик хватайся».
В любом варианте приходится чем-то жертвовать.
Как говорится, на ветхую одежду нет смысла пришивать новые заплатки.
Если новой нет пока, не ходить же в дырявом… Да и рефакторинг это не латание дыр, а скорее замена кусков (или как их там портные называют) с дырами на новые, более прочные чем были старые изначально.

Я просто делюсь личным опытом. Пробовал оба варианта, выбрал плавный рефакторинг из-за избежания двойной работы и получения фидбэка от пользователей сразу (а главное синхронизации двух версий после получения этого фидбэка). Единственное использую не Yii, а Symfony 2 Components (не сам Symfony 2) и Doctrine 2, потому что не хочется нарушать ссылочную целостность и т. п. Когда целиком закончу, тогда сразу переведу. Может быть. А может получится свой фреймворк на базе этих компонентов, хотя ориентируюсь на её архитектуру.
потому что не хочется нарушать ссылочную целостность

А в Symfony нельзя определить только на часть роутов? В моем случае роут-система была из рук вон плохая и я со спокойной душой по тихому переводил ее на Url Manager от yii.
Определить можно. Проблема в том, что ссылки захардкожены в шаблонах и в коде, и выискивать все места где оно ссылается неблагодарное дело.
Сколько человек в команде? Насколько вялотекущий процесс разработки? Какие, сколько и как вносятся изменения, как они влияют на профит с проекта.

Нарисуйте график. В подавляющем большинстве случаев, когда проект большой с огромным количеством легаси-кода, в команде больше 3-х человек, процесс внесения изменений очень медленный (оценка задачи производиться в днях, а не часах) то можно переложить на красивые и понятные руководству графики отношения затраченного бабла на поддержку и получаемого профита.

И если по ним видно, что полтора года назад реализация какой-то фичи, которая приносила бабла X занимала допустим 0.1X, то сейчас фича, той же сложности приносящая теже X, уже по баблу занимает 0.3X.

Часто помогает, тем более что зачастую задача взять и все переписать обрисовывается так: ну там п@#$&ц, надо переписывать, ща всей командой навалимся и за пару месяцев сделаем все. Надо по другому подходить к этому всему…
Согласен, но опять таки в HTML эти значения тоже надо положить предварительно. И какая разница, грубо говоря, какой файл обработает интерпретатор?

А про ужас и стыд, по-моему не уместно говорить при обсуждении технических моментов. Я ведь не самоутверждаюсь, а просто описал один из вариантов решения, кстати придуманный не мною. Он, естественно, имеет свои плюсы и минусы.
Я так понимаю что вы мне отвечали =)
Да, ошибся ссылочкой.
Действительно, прошу прощения за слишком резкую оценку. Но разделять код нужно обязательно, потому код должен быть всегда одинаков, он должен зависеть только от входных параметров. Тогда его можно протестировать и переиспользовать. Но вы код генерируете, что означает не только сложность его понимания (что если в команду пришел человек, знающий JS но не знающий PHP?), но и сложность отладки и нахождения ошибок.
Я бы сказал, что я не генерирую код, а скорее параметризую его данными, доступ к которым изначально JS не имеет.

Описанное выше предложение дергать AJAXом котроллер для определения нужных параметрических данных тоже накладывает определенные накладные расходы, несравнимые с одноразовым парсингом JS-файла. В принципе, все зависит от конкретных условий.
Мне лично не нравится вариант «дергать AJAXом контроллер для получения параметров», тоже костыль, лишняя нагрузка как вы верно заметили. Почему просто не положить данные в html-разметку и потом вытащить их уже с помощью JavaScript?
Как вариант — возможно и да. Но я как бы не вижу явных преимуществ. Ну да, JS поработает на стороне клиента (нас вроде это и не должно беспокоить), вместо того чтобы прийти готовым с сервера. В любом случае есть и будут накладные расходы на такую передачу данных из одной языка в другой. Лишний запрос запрос к серверу, о котором тут уже много говорилось — не самый важный аргумент, на мой взгляд.
Какой клевый велосипед с колесами из гусеничной цепи
Почти такой же, как и комментарий )))
Но зачем? Если нужно включение данных, меняющихся от страницы к странице, то лучше включить нужные переменные в страницу через JSON::encode. Если генерируется js-файл, то делать это по требованию, или кроном.
Зачем динамически генерировать js? Это может вызвать много проблем.
Решение (генерация JS на сервере) имеет право на жизнь (при нормальной реализации). В конце-концов какая разница PHP что генерировать, а серверу что отдавать — HTML, XML, JSON, JS или CSS. Первые три почему-то протеста не вызывают, холивары только по поводу как генерировать.

Единственное вызывает вопросы именно реализация. Манипулирование обработчиками в веб-сервере не есть хорошо. Предложенный выше somesript.js.php куда лучше. Нет места неоднозначности. То же относится к html. somepage.html.php (или somepage.html.twig) регулярно использую на практике.

P.S. А Content-Type вы не забываете выставлять?

P.P.S. В статье нет ни одного слова Apache, хотя конфиги именного для него.
Да, речь идет о том, как реализовать это при необходимости в Apache. Content-Type можно выставить в том же .htaccess. А вопроса об оптимизации работы сервера путем использования Apache + nginx для разделения статики и динамики я не касался, хотя собственно весь сыр-бор тут начался именно на эту тему.
Хотел полюбопытствовать. Почему " Манипулирование обработчиками в веб-сервере не есть хорошо"? Это манипулирование стандартными возможностями ПО.
Усложняет поддержку. Например на связке nginx+php-fpm уже так просто не запустишь. А на shared хостинге вообще эти настройки могут быть недоступны.
Ну это понятно. Речь же об Apache.
Тут главное не злоупотреблять. Я не могу спокойно смотреть на конструкции вида «if (<?php echo $condition ?>)» и стараюсь все выносить в отдельные JS файлы. Поэтому в 95 процентах случаев генерация JS осуществляется только для передачи данных внутри HTML шаблона. Если же данных не много, предпочитаю создать скрытый HTML блок с данными.

За всю свою практику генерировал отдальный JS файл только когда нужно было собрать все JS файлы в один и упаковать. Чтобы не вешать лишних обработчиков веб-сервера, JS отдавался в обычном контроллере. После генерации сохранялся в файловой системе по тому же адресу.
Именно об этом и речь — каждый сам определяет целесообразность подобных решений (способ передачи данных из серверного скрипта в клиентский).
Прочитал залоговок, подумал, — нахер это нужно?
Прочитал код
[code]
var jsVar = "";
[/code]
закрыл нафиг.

Мисье знает толк…
Я против такого и с радостью оторвал бы руки за кучу говнокода в js. Если файл js, пишите туда только js. Если что-то надо локализовать, заведите объект var Locale = {} и туда на php натыкайте все что требуется.
Если как вы пишите вам надо валидировать большую формочку, так валидируйте по ajax на сервере, оно надежней ибо серверной алидации не избежать все равно.
Самое страшное, что всякие начинающие воспримут статью как призыв к действию, ведь «крута же».
Никогда не видели как html+css генерится на javascript, который в свою очередь обрабатывается через php, который частично лежит в базе данных? А я видел. И мне было не смешно :(
Вы утрируете. Речи о призывах к действию и близко нет. Кроме того, не говорится о самом подходе — хорошо это или плохо. Все зависит от конкретного случая и стремления к перфекционизму тут ни при чем.
Я не против использовать то, что вы описали, когда это сильно необходимо, будет понятно и т.п.
Проблема в том, что человеку знающему, когда это может быть использовано, статья не пригодится, т.к. он уже знает как это сделать. А вот людей начинающих она, в таком контексте, может сбить с толку и направить по неправильному пути.
Можно даже совсем не париться и отдавать js точно таким же способом, которым отдаётся и HTML. И расширением жонглировать при этом нет никакого смысла. Просто будем знать, что по ссылке .../styles.php отдаётся js.

Однако при этом встаёт вопрос «а чем же статичные js лучше динамически генерируемых»? Да тем, что они отдаются мгновенно и на стороне клиента кэшируются. Поэтому основную статику лучше оставить статикой, а то, что меняется, вынести в отдельный небольшой файл и полностью или почти полностью его пересоздавать, а лучше даже вообще js-код в HTML засунуть, ибо бессмысленно при этом кусок js кидать в отдельный файл, а потом по каждому запросу его из этого файла подгружать. Дополнительный запрос = дополнительная загрузка сервера.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории