В этой статье я покажу вам, как я оптимизировал время загрузки кода javascript, используя методы кэширования как на стороне сервера, так и на стороне браузера. Глобальный код Javascipt собирается из разных файлов Javascript на локальном диске. Окончательный код зависит от таможенных параметров, присланных клиентом, который хочет использовать скрипт. Это зависит существенно от двух переменных:

  • appid: уникальный идентификатор, который ссылается на клиента.
  • language: язык, выбранный клиентом.

Таким образом, URL-адрес скрипта выглядит следующим образом:

https://site.com/language/script.js?appid=xxxxxx

Чтобы оптимизировать загрузку кода, на этот раз мы будем использовать нативный PHP-код, потому что при использовании любого PHP-фреймворка время выполнения увеличится, даже если фреймворк легкий и простой в использовании.

Сначала создадим файл конфигурации PHP (config.php) для скрипта.

$currentversion = '1.0';
define("REDIS_SERVER","127.0.0.1");
define("REDIS_PORT",6379);
define('DEV_MODE',0);

затем файл js.php, который вернет глобальный скрипт клиенту.

include_once dirname(__FILE__) .DIRECTORY_SEPARATOR.'config.php';
include_once(dirname(__FILE__) .DIRECTORY_SEPARATOR.'init.php');
$mtime = explode(" ",microtime());
$starttime = $mtime[1]+$mtime[0];
$redis_file_key="script.$appid.$lang.js"
$redis_time_key=  "time.".$redis_file_key;
ob_start();
if(($redis->get($redis_file_key)!=false) && (DEV_MODE==0)){
   if(!empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])&& (strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])==$redis->get($redis_time_key))){
    header("HTTP/1.1 304 Not Modified");
    exit();
   }
  echo $redis->get($redis_file_key);
  $js = ob_get_clean();
} else{
include_once dirname(__FILE__). '/js/s1.js';
include_once dirname(__FILE__). '/js/s2.js';
$js = ob_get_clean();
$redis->set($redis_file_key,$js);
$redis->set($redis_time_key,time());
}
$lastModified = $redis->get($redis_time_key);
header('Content-type: text/javascript;charset=utf-8');
header("cache-control: public, no-cache");
header("Last-Modified: ".gmdate("D, d M Y H:i:s",$lastModified)." GMT");
header('Expires: '.gmdate("D, d M Y H:i:s",time()+3600*24*365).' GMT');
echo $js;
$mtime = explode(" ",microtime());
$endtime = $mtime[1]+$mtime[0];
echo "\n\n/* Execution time: ".($endtime-$starttime)." seconds */";

Как видите, мы использовали Redis для создания кеша сервера и заголовки HTTP для создания кеша браузера.

Мы создаем собственный сценарий для каждого клиента, используя клиентское приложение и предпочтительный язык клиента в имени ключа. Например, для этого URL:

https://site.com/en/script.js?appid=12542

Наш скрипт создаст файл скрипта с именем: script.12542.en.js, а затем сохранит ключ в Redis. В следующий раз, когда клиент вызовет ту же строку, он вернет скрипт из кеша. Но при смене языка создается другой файл с ключом: script.12542.fr.js и так далее.

$redis_time_key используется для добавления заголовка Last-Modified к возвращаемому скрипту, а также для проверки, должны ли мы возвращать заголовок 304 Not Modified или нет в Браузер, когда сервер получает запрос.

Давайте теперь посмотрим содержимое скрипта init.php, вызываемого в начале скрипта js.php.

if (defined('DEV_MODE') && DEV_MODE == '1') {
    error_reporting(E_ALL);
    ini_set('display_errors','On');
}
$appid=$_REQUEST["appid"]??"";
$lang=$_REQUEST["language"]??"en";
include_once(dirname(__FILE__).DIRECTORY_SEPARATOR.'languages'.DIRECTORY_SEPARATOR.'en.php');
if (file_exists(dirname(__FILE__).DIRECTORY_SEPARATOR.'languages'.DIRECTORY_SEPARATOR.$lang.'.php')) {
  include_once(dirname(__FILE__).DIRECTORY_SEPARATOR.'languages'.DIRECTORY_SEPARATOR.$lang.'.php');
}
$redis = new Redis(); 
$redis->connect(REDIS_SERVER, REDIS_PORT);
$redis->select(1);

Как видите, в этом файле мы выполняем проверку параметров, полученных от url, вставляем соответствующий языковой файл и инициируем подключение к серверу Redis Cache.

конечно, скрипт s1.js, например, будет использовать соответствующие языковые сообщения, используя внедренные php-переменные. например:

/** check if browser support websockets **/    
        if(check_websocket()===false){
        this.errorEvent("<?=$language[6]?>");        
        $.gui_engine.alert("<?=$language[10]?>","<?=$language[6]?>");
        return;
        }