Задача такая: есть готовый виджет обратного звонка (набор html, php, css, js) необходимо это скомпоновать (я думаю завернуть в бандл) с целью установки на другие ресурсы (сторонние домены). Идея такая - размещаем виджет обратного звонка (допустим скрипт) единоразово. Если необходимо редактировать - это делается в одном месте, все остальные сайты "транслируют" уже отредактированный код. Либо JS скриптом вставляется (это пример как у других реализовано, здесь куча параметров собирается, которые не нужны). Код (Text): <script> (function(w,d,n,c){w.CallDataObject=n;w[n]=function(){w[n]["callbacks"].push(arguments)};if(!w[n]["callbacks"]){w[n]["callbacks"]=[]}w[n]["loaded"]=false;if(typeof c!=="object"){c=[c]}w[n]["counters"]=c;for(var i=0;i<c.length;i+=1){p(c[i])}function p(cId){var a=d.getElementsByTagName("script")[0],s=d.createElement("script"),i=function(){a.parentNode.insertBefore(s,a)},m=typeof Array.prototype.find === 'function',n=m?"init-min.js":"init.js";s.async=true;s.src="https://mod.calltouch.ru/"+n+"?id="+cId;if(w.opera=="[object Opera]"){d.addEventListener("DOMContentLoaded",i,false)}else{i()}}})(window,document,"ct","123879457"); </script> Сколько по времени и по деньгам?
Спойлер: 500 рублей. За пример. 1. Центральный сервер (PHP) Файл: widget-api.php Этот файл генерирует данные и, самое главное, убивает кэш. PHP: <?php // widget-api.php // 1. ЗАГОЛОВКИ ДЛЯ ОТКЛЮЧЕНИЯ КЭША (Космически важно!))) header("Content-Type: application/json; charset=utf-8"); header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0"); header("Cache-Control: post-check=0, pre-check=0, false"); header("Pragma: no-cache"); header("Expires: 0"); // 2. ГЕНЕРАЦИЯ ДАННЫХ (Имитация базы данных) $config = [ "version" => time(), // Уникальная версия (timestamp) для обхода кэша файлов "widget" => [ "type" => "loader", "text" => "Загрузка данных...", "color" => "#3498db", "size" => "50px", // Можно передавать HTML шаблон или просто данные для рендера "template_id" => "spinner-v1" ] ]; echo json_encode($config); 2. Библиотека виджета (JS + CSS) Файл: widget-core.js Это "тяжелая" часть, которая содержит стили и логику. Она загружается только после получения конфига. PHP: // widget-core.js (function() { // CSS стили виджета (инжектим их прямо в JS, чтобы не грузить отдельный файл CSS) const styles = ` .central-widget-container { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255,255,255,0.9); display: flex; flex-direction: column; justify-content: center; align-items: center; z-index: 9999; font-family: sans-serif; transition: opacity 0.5s ease; } .spinner { border: 5px solid #f3f3f3; border-top: 5px solid var(--widget-color); border-radius: 50%; width: var(--widget-size); height: var(--widget-size); animation: spin 1s linear infinite; margin-bottom: 15px; } .widget-text { color: #333; font-weight: bold; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } `; // Функция инициализации виджета window.initCentralWidget = function(config) { const data = config.widget; // 1. Создаем стили const styleSheet = document.createElement("style"); styleSheet.innerText = styles; document.head.appendChild(styleSheet); // 2. Создаем HTML const container = document.createElement("div"); container.className = "central-widget-container"; container.style.setProperty('--widget-color', data.color); container.style.setProperty('--widget-size', data.size); container.innerHTML = ` <div class="spinner"></div> <div class="widget-text">${data.text}</div> `; document.body.appendChild(container); // 3. Пример логики: скрыть виджет через 3 секунды (имитация загрузки) setTimeout(() => { container.style.opacity = '0'; setTimeout(() => container.remove(), 500); }, 3000); console.log("Widget loaded with version:", config.version); }; })(); 3. Загрузчик (Loader) Файл: loader.js Этот скрипт размещается на сайтах клиентов. Он делает запрос к PHP, получает версию и динамически подключает widget-core.js. PHP: // loader.js (function() { // URL центрального сервера const API_URL = 'https://your-central-site.com/widget-api.php'; // Путь к самому виджету (на том же сервере) const WIDGET_LIB_URL = 'https://your-central-site.com/widget-core.js'; // Функция загрузки скрипта function loadScript(src, callback) { const script = document.createElement('script'); script.src = src; script.async = true; script.onload = callback; document.head.appendChild(script); } // 1. Делаем запрос к API за конфигом // Добавляем random, чтобы сам этот запрос тоже не закэшировался браузером агрессивно fetch(API_URL + '?t=' + new Date().getTime()) .then(response => response.json()) .then(data => { // 2. Получаем версию из JSON const version = data.version; // 3. Формируем URL библиотеки с параметром версии (Cache Busting) // Браузер увидит новый URL и скачает файл заново const libUrlWithVersion = `${WIDGET_LIB_URL}?v=${version}`; // 4. Загружаем библиотеку виджета loadScript(libUrlWithVersion, () => { // 5. Когда библиотека загрузилась, запускаем её с данными if (typeof window.initCentralWidget === 'function') { window.initCentralWidget(data); } }); }) .catch(err => console.error("Widget load error:", err)); })(); 4. Пример использования на клиентском сайте PHP: <!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <title>Сайт клиента с виджетом</title> </head> <body> <h1>Контент сайта клиента</h1> <p>Здесь виджет должен появиться поверх всего.</p> <!-- Подключение загрузчика виджета --> <!-- defer гарантирует, что скрипт выполнится после парсинга HTML --> <script src="https://your-central-site.com/loader.js" defer></script> </body> </html> Как это решает проблему кэша? API (widget-api.php): Заголовки Cache-Control: no-store гарантируют, что браузер каждый раз пойдет на сервер за JSON-файлом, а не возьмет его из памяти. Версионирование файлов: В JSON возвращается version (timestamp). Загрузчик берет этот timestamp и добавляет его к URL загрузки JS-библиотеки: widget-core.js?v=171562345. Если вы изменили код виджета и обновили timestamp в PHP, URL изменится. Браузер увидит новый URL и скачает новый JS файл, игнорируя старый кэш. Ленивая загрузка: Скрипт loader.js выполняется асинхронно и не блокирует отображение основного контента сайта клиента. Как обновить виджет? Вам нужно просто изменить файл widget-core.js или widget-api.php на центральном сервере. Если меняете логику/стили: обновляете widget-core.js. Если меняете текст/цвет: обновляете массив $config в widget-api.php. Важно: Убедитесь, что в $config поле "version" меняется (например, time() делает это автоматически каждую секунду). 15 минут заняло