Pull to refresh

Решаем проблему с кешированием динамического JavaScript кода на фронтенд WordPress

Reading time4 min
Views5.6K

В процессе разработки анти-спам плагина 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!

Tags:
Hubs:
Total votes 5: ↑2 and ↓3-1
Comments21

Articles

Information

Website
cleantalk.org
Registered
Founded
Employees
2–10 employees
Location
Россия