В процессе разработки анти-спам плагина CleanTalk для WordPress мы стокнулись с проблемой кеширования динамического JavaScript кода на фронтенде сайтов. А именно, если разместить JavaScript содержащий какие либо куски кода динамически подставляемые из бекенд сайта, то при наличии на сайте любого плагина кеширования страниц, JavaScript код становится не возможно использовать по назначению.
Рассмотрим пример
В бэкенд у нас есть шаблон JavaScript кода,
<?php
$html = '
<script type="text/javascript">
function ctSetCookie(c_name, value, def_value) {
document.cookie = c_name + "=" + escape(value.replace(/^def_value$/, value)) + "; path=/";
}
ctSetCookie("%s", "%s", "%s");
</script>
';
$ct_checkjs_key = rand(0,100); // Значение переменной динамическое
$field_name = 'ct_checkjs'; // Значение статическое
$ct_checkjs_def = 0; // Значение статическое
$html = sprintf($html, $field_name, $ct_checkjs_key, $ct_checkjs_def);
?>
Пример вывода на фронтенд,
<script type="text/javascript">
function ctSetCookie(c_name, value, def_value) {
document.cookie = c_name + "=" + escape(value.replace(/^def_value$/, value)) + "; path=/";
}
ctSetCookie("ct_checkjs", "455", "0");
</script>
Соответственно в кеш попадает JavaScript код в котором параметр value функции ctSetCookie неизменен на всех страницах сайта и одинаков для всех посетителей, что приводит к невозможности использования JavaScript персонально для каждого посетителя. Рассмотрим варианты решения.
Используем встроенные средства отключения кеширования
Если плагин кеширования контента на WordPress более-менее популярен, то у него обазятельно есть средства для исключения списка страниц из кеша. К примеру для WP Super cache можно указать в коде вашего плагина строчку,
define( "DONOTCACHEPAGE", true );
Этого будет достаточно чтобы страницы с вашим динамическим кодом не попадали в кеш. Минусы такого подхода,
- Необходимо интегрировать и тестировать ваш плагин с популярными плагинами кеширования.
- Все равно будут случаи когда ваш код некорректно отрабатывают, по причине того, что на том или ином сайте установле редко используемый плагин кеширования.
- Ну и самое главное, такой подход сводит практически к 0 применение плагинов кеширования, если ваш JavaScript код размещается на всех страницах сайта, либо на наиболее нагруженных страницах.
Посмотрим на другой вариант решения.
AJAX вызов в бэкенд
Суть этого подхода в том, что на фронтенде размещаем только статичный JavaScript код, а все что требуется использовать динамически получаем из бекэнд сайта через AJAX вызов. Пример кода на фротенд,
//
// Делаем вызов к admin-ajax.php
//
function sendRequest(url,callback,postData) {
var req = createXMLHTTPObject();
if (!req) return;
var method = "GET";
req.open(method,url,true);
if (postData)
req.setRequestHeader('Content-type','application/x-www-form-urlencoded');
req.onreadystatechange = function () {
if (req.readyState != 4) return;
if (req.status != 200 && req.status != 304) {
return;
}
callback(req);
};
if (req.readyState == 4) return;
req.send(postData);
return null;
}
var XMLHttpFactories = [
function () {return new XMLHttpRequest()},
function () {return new ActiveXObject("Msxml2.XMLHTTP")},
function () {return new ActiveXObject("Msxml3.XMLHTTP")},
function () {return new ActiveXObject("Microsoft.XMLHTTP")}
];
function createXMLHTTPObject() {
var xmlhttp = false;
for (var i=0;i<XMLHttpFactories.length;i++) {
try {
xmlhttp = XMLHttpFactories[i]();
}
catch (e) {
continue;
}
break;
}
return xmlhttp;
}
//
// Обрабатываем результаты AJAX вызова.
//
function ct_callback(req)
{
ct_cookie=req.responseText.trim();
ct_setCookie('ct_checkjs', ct_cookie);
return null;
}
//
// Устанавливаем куку
//
function ct_setCookie(name, value)
{
document.cookie = name+" =; expires=Thu, 01 Jan 1970 00:00:01 GMT; path = /";
document.cookie = name+" =; expires=Thu, 01 Jan 1970 00:00:01 GMT";
var date = new Date;
date.setDate(date.getDate() + 1);
setTimeout(function() { document.cookie = name+"=" + value + "; expires=" + date.toUTCString() + "; path = /;"}, 500);
return null;
}
var ct_ajaxurl = 'http://wordpress.local/wp-admin/admin-ajax.php';
sendRequest(ct_ajaxurl+'?'+Math.random(),ct_callback,'action=ct_get_cookie');
Прошу обратить внимание на конструкцию,
ct_ajaxurl+'?'+Math.random()
Такой прием используется для исключения кеширования в том числе и AJAX вызов.
Двигаемся к последнему листингу, посмотрим на бэкенд,
add_action( 'wp_ajax_nopriv_ct_get_cookie', 'ct_get_cookie',1 );
/**
* Возвращает новую куку
*/
function ct_get_cookie()
{
global $ct_checkjs_def;
$ct_checkjs_key = ct_get_checkjs_value(true);
print $ct_checkjs_key;
die();
}
Минус у такого подхода только в одном — ваш плагин делает на 1 вызов в бэкенд WordPress больше. С учетом того, что хостинг может быть не самым быстрым, либо на WordPress может быть установлено не один десяток плагинов, такой вызов приведет к увеличению времени ответа сайта.
Успехов в разработке под WordPress!
Комментарии (21)
sefus
19.04.2016 16:10+2Чтобы js-код кэшировался, его не нужно генерировать динамически, а необходимые переменные запрашивать по ajax с сервера по динамическому адресу. Вот и вся статья.
oxidmod
я вижу только один минус. разработка на ВП чегото отличного от бложика.
конечно можно, но зачем есть кактус?
delfi
Как вопрос относится к данному топику?
По описанию плагина — это антиспам и для блогов в том числе.
WP уже давно перерос «бложики» и на нем можно делать достаточно разнообразные по тематике сайты. При том, как показывает практика, конечному администратору сайта на данной CMS, мало понимающему в верстке, программировании — очень удобно пользоваться WP.
oxidmod
объясняю как мой коммент относится к теме:
js, который собирается на бекенде — это, мягко говоря, очень пахнущий код.
>> Минус у такого подхода только в одном — ваш плагин делает на 1 вызов в бэкенд WordPress больше.
зачем так мужественно побеждать ВП и его говно-код, если можно использовать чтото более подходящее?
и да, минусить в карму — это вин, однозначно.
delfi
> js, который собирается на бекенде — это, мягко говоря, очень пахнущий код.
Так это проблема уж не CMS, а плагинов, которые не могут предоставить возможность отключать кэш для каких-то блоков. Хотя смутно себе это представляю. Возможно, какой-то механизм должна предложить сама CMS для плагинов, чтобы не приходилось костыли писать для всевозможных плагинов кеширования.
> зачем так мужественно побеждать ВП и его говно-код, если можно использовать чтото более подходящее?
Кто-то побеждает, кто-то пользуется. Предложите пример хорошей CMS, на которой можно за 4-5 дня сделать хороший сайт-визитку, лендинг, за неделю-две сделать магазин, где не было бы проблем, говно-кода и т.д… При этом обычному пользователю не надо будет тратить кучу времени на панели администратора.
И да, я за качественное исполнение в программной части, но и не стоит забывать, что конечному заказчику не важно какой код, главное, безопасный. А WP обновляется достаточно часто и еще не было у меня случаев взлома WP.
> и да, минусить в карму — это вин, однозначно.
Зачем это писать? Кто минусил — ему это не интересно, думаю
Wedmer
Опишите что то более подходящее. На данный момент WP хорош соответствием понятию «Из коробки».
Большинство дргих систем требует девайс «Напильник», ssh и ftp доступ.
Видимо от вас и ждали реплики про карму.
oxidmod
ответ вам и delfi
лендинг, зачастую, не требует cms вовсе. это статика + просто хендлер формы для сбора контактов.
аналогично сайт-визитка. Но любая другая ЦМС будет лучше для визитки чем wp, если нужно редактировать контент с админки.
для магазинов есть специализированные системы, начиная с простого openCart и заканчивая такими монстрами как Magento и ShopWare (на любые потребности и карман). Даже самые простые и бесплатные e-commerce движки из коробки предоставляют все необходимое для онлайн-магазина. остается скачать с магазина тем понравившийся шаблон + пару модулей по вкусу на оплату и доставку.
delfi
Лендинг — согласен, статикой лучше.
openCart идеален по коду? Да, есть MVC. Но как насчет костылей с qmod (или как-то так), через который написано куча плагинов, т.к. иначе их не написать, не залезая в исходники движка. Не знаю, исправили это во 2 версии или нет, но в wordpress хоть хуки есть и они покрывают 95% необходимого, когда нужно внедрить свой функционал в систему.
И как в openCart решается вопрос, затронутый в данном топике?
«остается скачать с магазина тем понравившийся шаблон » — в 60-70% случаев шаблон приходится допиливать под потребности клиента. Чаще клиенты заказывают отдельно дизайн. Но при чем здесь CMS?
Вы же писали, что WP — это ужасный код. Отсюда и возник вопрос о CMS с нормальным кодом, где не нужны напильники.
oxidmod
я же написал, начиная с простого openCart.
да, он не идеален, но всяко лучше WP.
то что тему нужно допиливать под запрос клиента тоже не минус движка. под ВП точно также придется тему допиливать.
если хотите прямо академический код, то смотрите на мадженто или ShopWare
>> И как в openCart решается вопрос, затронутый в данном топике?
не используется js генерируемый на бекенде, как и везде, кроме плагинов ВП видимо
delfi
> да, он не идеален, но всяко лучше WP.
Обоснованно, да
> то что тему нужно допиливать под запрос клиента тоже не минус движка. под ВП точно также придется тему допиливать.
Видимо, у Вас не очень большой опыт.
Например, делал недавно интернет магазин, где своя система скидок, для которой нет готовых плагинов, соответственно, интеграции в шаблон. Допиливать пришлось бы под любую CMS.
Если так рассуждать, что некоторые потребности клиента не могут быть покрыты стандартным функционалом, то тут можно начинать с корня, что значит и бизнес построен неправильно, да?
> если хотите прямо академический код, то смотрите на мадженто или ShopWare
Мадженто для магазина в 10000 товаров — это как пушкой по воробьям.
> не используется js генерируемый на бекенде, как и везде, кроме плагинов ВП видимо
Если у нас есть конфигурируемые параметры, которые затем обрабатываются с помощью JS, то как выходить из положения?
И да, у купленных тем тоже таких примеров куча — настройки слайдеров, например. Значит это неправильные шаблоны? Если отказываться от настраиваемости, то мы вернемся к пункту, которые обсудили ранее, где шаблон не может покрыть требования заказчика.
oxidmod
>> Обоснованно, да
хотябы приличный MVC, который позволяет отделить мух (вывод инфы) от котлет (кастомной системы скидок)
>> Видимо, у Вас не очень большой опыт.
2.5 года в сфере ecommerce
>> Например, делал недавно интернет магазин, где своя система скидок, для которой нет готовых плагинов, соответственно, интеграции в шаблон. Допиливать пришлось бы под любую CMS.
в e-commerce движках скидки в каком либо виде присутствуют всегда. Значит в нормальном движке вам нужно подпилить/заменить БЛ (рассчет этой скидки в зависимости от нужных параметров), а уж в шаблоне они выведутся нормально
>> Мадженто для магазина в 10000 товаров — это как пушкой по воробьям.
пушка то на то и нацелена, но хорошо, вот вам другой пример: OXID eShop. В базовой поставке он запуститься на шаред хостинге с мускулем и пхп5.3. У одного из клиентов он на нем крутилось 300к товаров, но конечно дополнительно устанавливались модули для поиска на базе sphinx, для кеширования страниц на базе varnish и для кеша сущностей на базе memcahe. Тут уж конечно шаред хостингом не обойдешься, но это была все та же Community Edition движка, которая по мере роста бизнесса обростала необходимыми модулями. Сожержит удобное АПи для написания модулей любой сложности под любые запросы, хотя и не идеален с точки зрения архитектуры.
>> Если у нас есть конфигурируемые параметры, которые затем обрабатываются с помощью JS, то как выходить из положения?
уж всяко не генерацией js-а на бекенде. js должен быть статическим, и в идеале грузиться с cdn.
в случае слайдеров:
1) либо верстка слайдеров генерится на бекенде и js её оживляет, добавляя реакцию на клики/свайпы
2) либо js аяксом тянет с бекенда список елеметов и ихъ параметры и динамически генерит контент на странице
но ни в 1 ни во 2 случае ему не нужны никакие динамические параметры
ЗЫ: имхо, качество кода самого ВП лишь стимулирует писать под него такие же плагины.
delfi
>> хотябы приличный MVC, который позволяет отделить мух (вывод инфы) от котлет (кастомной системы скидок)
Только, как написал выше, без внедрения в системные файлы — в openCart не внедрить свою систему. А обновили системные файлы — потеряли возможность обновляться.
В Wordpress реализовал это с помощью хуков, система обновляется без проблем и функционал не ломается.
> в e-commerce движках скидки в каком либо виде присутствуют всегда. Значит в нормальном движке вам нужно подпилить/заменить БЛ (рассчет этой скидки в зависимости от нужных параметров), а уж в шаблоне они выведутся нормально
Есть 3 типа товаров (как их пометить?). Для каждого типа есть свой порог для оптовой цены и для среднего опта. Скидка считается из расчета набранной суммы в корзине + по прошлым покупкам для каждого типа товара отдельно. Назовите хоть 1 плагин, который сможет такое сделать из коробки. Назовите хоть 1 шаблон, который адаптировался под все доработки такого плана.
>> Если у нас есть конфигурируемые параметры, которые затем обрабатываются с помощью JS, то как выходить из положения?
уж всяко не генерацией js-а на бекенде. js должен быть статическим, и в идеале грузиться с cdn.
в случае слайдеров:
1) либо верстка слайдеров генерится на бекенде и js её оживляет, добавляя реакцию на клики/свайпы
2) либо js аяксом тянет с бекенда список елеметов и ихъ параметры и динамически генерит контент на странице
но ни в 1 ни во 2 случае ему не нужны никакие динамические параметры
Хм, разве не п. 2 предлагается в статье?
> ЗЫ: имхо, качество кода самого ВП лишь стимулирует писать под него такие же плагины.
Я не спорю, что код там не очень, но иногда вопрос результата и клиентов не волнует код. CMS удобна, гибкая под разные задачи, при должном подходе не ломают
oxidmod
>> Только, как написал выше, без внедрения в системные файлы — в openCart не внедрить свою систему
именно с модулями openCart бодаться не приходилось. хватало доступных в магазине.
а вот модули в magento и OXID встраиваются в систему без проблем.
>> Есть 3 типа товаров (как их пометить?)
а как вы их разделяете? по категории? по артикулу? по названиях? не факт что для этого вообще нужны какието допилы
>> Для каждого типа есть свой порог для оптовой цены и для среднего опта. Скидка считается из расчета набранной суммы в корзине + по прошлым покупкам для каждого типа товара отдельно. Назовите хоть 1 плагин, который сможет такое сделать из коробки. Назовите хоть 1 шаблон, который адаптировался под все доработки такого плана.
Скейл цены от количества искаропки:
http://i.piccy.info/i9/d6807c9075551da6419daf5abab0b5e6/1461076128/37491/1026532/scale.png
искаропки там также есть разные цены для груп юзеров, скидки для груп юзеров, смена цен по наступлению определенной даты (флеш распродажи например), расчет скидка от суммы заказа,
в сторе модулей есть модули бонусных систем (накопление бонусов за покупку и их последующее использование в новых заказах)
>> Хм, разве не п. 2 предлагается в статье?
в статье это предлагается как решение проблемы для ВП. хотя в нормальных системах такой пробелмы просто нет.
delfi
>именно с модулями openCart бодаться не приходилось. хватало доступных в магазине.
50% модулей для не 2 версии устанавливаются с заменой системных файлов. Часть из них через qmod. Если просто заменяют, то 2 модуля перезатирают друг друга.
> а вот модули в magento и OXID встраиваются в систему без проблем.
Не сталкивался, не могу ничего сказать
>> Есть 3 типа товаров (как их пометить?)
а как вы их разделяете? по категории? по артикулу? по названиях? не факт что для этого вообще нужны какието допилы
По тегам
>> Для каждого типа есть свой порог для оптовой цены и для среднего опта. Скидка считается из расчета набранной суммы в корзине + по прошлым покупкам для каждого типа товара отдельно. Назовите хоть 1 плагин, который сможет такое сделать из коробки. Назовите хоть 1 шаблон, который адаптировался под все доработки такого плана.
Скейл цены от количества искаропки:
http://i.piccy.info/i9/d6807c9075551da6419daf5abab0b5e6/1461076128/37491/1026532/scale.png
Не подходит, считается не по количеству товара, а по общей сумме товаров определенного типа, находящегося в корзине и приобретенного ранее.
>искаропки там также есть разные цены для груп юзеров, скидки для груп юзеров, смена цен по наступлению определенной даты (флеш распродажи например), расчет скидка от суммы заказа,
в сторе модулей есть модули бонусных систем (накопление бонусов за покупку и их последующее использование в новых заказах)
В моем случае — было для всех групп пользователей. Бонусные начисления за покупки тоже не решают задачу.
>> Хм, разве не п. 2 предлагается в статье?
в статье это предлагается как решение проблемы для ВП. хотя в нормальных системах такой пробелмы просто нет.
Не совсем понимаю логики.
Думаю, что обсуждение ушло совсем в другое русло, поэтому, откланиваюсь. Всего хорошего
oxidmod
>> Думаю, что обсуждение ушло совсем в другое русло, поэтому, откланиваюсь. Всего хорошего
вот не понимаю людей которые цепляются за откровенное г*но, аргументируя тем, что в других случаях всеравно нужно будет дописывать. Да любые кастомные вещи нужно дописывать. Другое дело как это дописывать и как потом поддерживать.
я очень плотно работал с OXID, и скажу, что модуль для рассчета скидки по сумарной стоимости продуктов сгрупированных по тегам пишеться без правок фронта от слова вообще. И при выключении этого модуля из админки ничего не сломается, просто начнет считать как считало из каробки
shagimuratov
По долгу службы приходится развивать плагины для более чем 10 CMS, так вот в поддержку WordPress скажу, что тамошняя система хуков наиболее продуманная и документированная.
Поддерживать тамошние плагины одно удовольствие.
oxidmod
открываем wp-includes/plugin.php
и находим:
да, очень удобная и надежная система
delfi
https://github.com/OXID-eSales/oxideshop_ce/search?utf8=%E2%9C%93&q=global&type=Code
oxidmod
окай, вы нашли грязный легаси код, поверх которого дана нормальная абстракция для работы. сисема постоянно развивается и со временем эти вещи будут выпилены. В то времякак в ВП это и есть основа на которой нужно работать. Но оставайтесь в своих розовых мечтах
delfi
О том и речь была, что цепочку обсуждения потеряли.
Система скидок, которую сделал хуками не затрагивает фронт и при отключении прекрасно все работает без нее, а Вы уже все перемешали и выставили ситуацию иначе.