Добавление времени последнего изменения в качестве версии для CSS и JS

11 июн. 2017 г., 00:07:11
Просмотры: 20.1K
Голосов: 3

Мне удалось добавить время последнего изменения файла в качестве версии для CSS и JS файлов. Как видите, мне приходится повторно добавлять filemtime(get_theme_file_path('...')) каждый раз при добавлении новой ссылки.

function _enqueue_scripts() {
    wp_enqueue_style('_base', get_theme_file_uri('/assets/css/base.css'), array(), filemtime(get_theme_file_path('/assets/css/base.css')));
    wp_enqueue_script('_base', get_theme_file_uri('/assets/js/base.js'), array(), filemtime(get_theme_file_path('/assets/js/base.js')));
}
add_action('wp_enqueue_scripts', '_enqueue_scripts');

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

Похоже на функцию ниже (для удаления номеров версий), но я хотел бы добавлять номера версий.

function _remove_script_version($src) {
    return $src ? esc_url(remove_query_arg('ver', $src)) : false;
}
add_filter('style_loader_src', '_remove_script_version', 15, 1);
add_filter('script_loader_src', '_remove_script_version', 15, 1);
0
Все ответы на вопрос 5
0

Вы можете использовать add_query_arg(), но тогда вам придется парсить URI каждый раз. Я бы предпочел создать обертку для функций wp_enqueue_script/style:

function my_enqueuer($my_handle, $relpath, $type='script', $my_deps=array()) {
    $uri = get_theme_file_uri($relpath);
    $vsn = filemtime(get_theme_file_path($relpath));
    if($type == 'script') wp_enqueue_script($my_handle, $uri, $my_deps, $vsn);
    else if($type == 'style') wp_enqueue_style($my_handle, $uri, $my_deps, $vsn);      
}

Добавьте это в ваш файл функций, а затем вместо, например:

wp_enqueue_script('_base', get_theme_file_uri('/assets/js/base.js'), array(), filemtime(get_theme_file_path('/assets/js/base.js')));

используйте:

my_enqueuer('_base', '/assets/js/base.js');

и вместо:

wp_enqueue_style('_base', get_theme_file_uri('/assets/css/base.css'), array(), filemtime(get_theme_file_path('/assets/css/base.css')));

используйте:

my_enqueuer('_base', '/assets/css/base.css', 'style');

Вы можете передать массив зависимостей в качестве последнего аргумента, когда это необходимо. Для скриптов, если вы передаете массив зависимостей, вам также придется передать третий параметр 'script', несмотря на то, что я установил его значение по умолчанию.

11 июн. 2017 г. 01:32:37
0

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

<?php wp_enqueue_style( 'child-theme', get_stylesheet_directory_uri() . '/css/styles.css', array(), '20150731' ); ?>

Мой пересмотренный подход начинается с создания переменной для пути к CSS/JS файлу, а затем использования функции filemtime вместо YYYYMMDD в качестве номера версии:

<?php
$themecsspath = get_stylesheet_directory() . '/css/styles.css';
wp_enqueue_style(
    'child-theme',
    get_stylesheet_directory_uri() . '/css/styles.css',
    array(),
    filemtime( $themecsspath )
);
?>

Теперь вместо номера версии WordPress в подключаемых файлах, как здесь:

<link rel='stylesheet' id='child-theme-css'  href='http://example.com/wp-content/themes/child/css/styles.css?ver=4.3.1' type='text/css' media='all' />

Файлы выглядят так:

<link rel='stylesheet' id='child-theme-css'  href='http://example.com/wp-content/themes/child/css/styles.css?ver=1447781986' type='text/css' media='all' />
8 февр. 2018 г. 08:46:43
0

Этот ответ адаптирован из решения @CGodo.

Я получал фатальные ошибки с оригинальным кодом. Я протестировал этот код, и он делает то, что, как я считаю, предполагалось в исходном ответе.

/**
 * Заменяет версию запроса в зарегистрированных скриптах или стилях на время последнего изменения файла
 *
 * @param string $src Исходный URL
 *
 * @return string URL с добавленной версией
 */
function add_modified_time( $src ) {

    $clean_src = remove_query_arg( 'ver', $src );
    $path      = wp_parse_url( $src, PHP_URL_PATH );

    // Пытаемся получить время модификации файла
    if ( $modified_time = @filemtime( untrailingslashit( ABSPATH ) . $path ) ) {
        $src = add_query_arg( 'ver', $modified_time, $clean_src );
    } else {
        // Если не удалось - используем текущее время
        $src = add_query_arg( 'ver', time(), $clean_src );
    }

    return $src;

}

// Подключаем фильтры для скриптов и стилей
add_filter( 'style_loader_src', 'add_modified_time', 99999999, 1 );
add_filter( 'script_loader_src', 'add_modified_time', 99999999, 1 );
27 авг. 2019 г. 16:46:57
1

Если кому-то понадобится, эти хуки добавят версии на основе времени модификации ко всем скриптам и стилям WordPress, кроме загружаемых напрямую из PHP.

Причина использования синглтонов WP_Scripts и WP_Styles в том, что эти экземпляры уже содержат вычисленный base_url.

/**
 * Заменяет версию в запросе для зарегистрированных скриптов или стилей на время модификации файла
 * @param string $src Исходный URL
 * @param string $baseUrl Базовый URL сайта
 * @return string
 */
function put_modified_time_version($src, $baseUrl)
{
    // Работаем только с объектами из baseUrl
    if ($src && strpos($src, $baseUrl) === 0) {
        // Удаляем любую существующую версию
        $newSrc = remove_query_arg('ver', $src);
        // Получаем путь после base_url
        $path = substr($newSrc, strlen($baseUrl));
        $path = wp_parse_url($path, PHP_URL_PATH);
        // Добавляем версию на основе времени модификации, если файл существует
        if ($mtime = @filemtime(untrailingslashit(ABSPATH) . $path)) {
            $src = add_query_arg('ver', $mtime, $newSrc);
        }
    }
    return $src;
}

/**
 * Фильтрует источники стилей, добавляя время модификации файла как строку запроса
 * @param $src
 * @return string
 */
function modified_time_version_style($src) {
    // base_url из WP_Versions уже в памяти
    return ($src) ? put_modified_time_version($src, wp_styles()->base_url) : $src;
}

/**
 * Фильтрует источники скриптов, добавляя время модификации файла как строку запроса
 * @param $src
 * @return string
 */
function modified_time_version_script($src) {
    // base_url из WP_Styles уже в памяти
    return ($src) ? put_modified_time_version($src, wp_scripts()->base_url) : $src;
}

add_filter('style_loader_src', 'modified_time_version_style', 15, 1);
add_filter('script_loader_src', 'modified_time_version_script', 15, 1);
20 февр. 2018 г. 02:48:26
Комментарии

Я целый день искал способ версионировать свои таблицы стилей. У меня возникла проблема с использованием этого для всех скриптов, но я просто закомментировал фильтр для скриптов, так как он мне не был нужен для этого случая.

Примечание: мне пришлось изменить приоритет с 15 на 9999, чтобы это заработало. Уверен, что плагины, с которыми я работал, устанавливали приоритет выше, чем следовало.

Mike Averto Mike Averto
14 дек. 2020 г. 00:57:05
0

Я только что написал два метода для класса своего плагина, которые значительно упрощают регистрацию и подключение скриптов и стилей. И, конечно же, как и требовалось, в параметр версии всегда добавляется время последнего изменения. Возможно, это кому-то пригодится.

Как их использовать:

/**
 * Для этих примеров предположим, что ресурсы вашего плагина находятся в
 * wp-content/plugins/my-plugin/path/to/assets/
 */

// добавить ваш стиль
$this->registerAsset('path/to/assets/your-style.css');

// добавить ваш скрипт работает точно так же
$this->registerAsset('path/to/assets/your-script.js');

// добавить скрипт с зависимостью
$this->registerAsset('path/to/assets/script-with-dependencies.js', [
    'jquery'
]);

// добавить скрипт с внутренней зависимостью
$this->registerAsset('path/to/assets/script-with-dependencies.js', [
    'jquery',
    $this->getAssetHandle('path/to/assets/your-script.js')
]);

// для внутренних зависимостей вы также можете передать путь к зависимости напрямую
$this->registerAsset('path/to/assets/script-with-dependencies.js', [
    'jquery',
    'path/to/assets/your-script.js'
]);

Есть еще несколько опций, но просто ознакомьтесь с документацией по методам в исходном коде, который вам нужен:

class myPlugin
{
    public function __construct()
    {
    }
    
    /**
     * Регистрирует и подключает скрипт или стиль
     * 
     * @param   STRING        $path          Путь к файлу, который вы хотите зарегистрировать или подключить (относительно папки вашего плагина).
     * @param   ARRAY         $dependencies  Зависимости, как вы знаете из wp_enqueue_script, но также допускаются пути к другим ресурсам, зарегистрированным этим методом.
     * @param   BOOLEAN       $enqueue       Если FALSE, ресурс будет только зарегистрирован, в противном случае он также будет подключен.
     * @param   STRING|NULL   $type          Тип ресурса. Допустимые типы: 'script' и 'style'. Если NULL, тип автоматически определяется по расширению файла.
     * @param   STRING        $media         Определение 'media' при добавлении CSS (игнорируется для JS ресурсов - JS ресурсы всегда получают TRUE для параметра in_footer, так как это обычно рекомендуемый способ)
     * 
     * @return  BOOLEAN|NULL  Когда $enqueue равен TRUE, возвращаемое значение всегда NULL. В противном случае TRUE при успехе, FALSE при неудаче.
     */
    public function registerAsset($path, $dependencies = [], $enqueue = true, $type = null, $media = 'all')
    {
        $path = '/' . ltrim($path, '/');
        $pluginDirName = explode(DIRECTORY_SEPARATOR, ltrim(str_replace(realpath(WP_PLUGIN_DIR), '', realpath(__FILE__)), DIRECTORY_SEPARATOR), 2)[0];
        $pluginDir = realpath(WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $pluginDirName);

        if ($type === null) {
            $extensions = ['js' => 'script', 'css' => 'style'];
            $extension = pathinfo($path, PATHINFO_EXTENSION);
            $type = isset($extensions[$extension]) ? $extensions[$extension] : null;
        }
        if (!in_array($type, ['script', 'style']) || !file_exists($pluginDir . $path)) {
            return;
        }

        foreach ($dependencies as $index => $dependency) {
            if (preg_match('/\.(js|css)$/', $dependency) && file_exists($pluginDir . DIRECTORY_SEPARATOR . ltrim($dependency, '\\/'))) {
                $dependencies[$index] = $this->getAssetHandle($dependency);
            }
        }

        $func = 'wp_' . ($enqueue ? 'enqueue' : 'register') . '_' . $type;
        return $func($this->getAssetHandle($path), plugins_url($pluginDirName . $path), $dependencies, filemtime($pluginDir . $path), $type === 'script' ? true : $media);
    }

    /**
     * Получает handle ресурса, который автоматически использует registerAsset()
     * 
     * @param   STRING        $path          Путь, который вы использовали с registerAsset()
     * 
     * @return  STRING        Имя handle ресурса
     */
    public function getAssetHandle($path)
    {
        $pluginDirName = explode(DIRECTORY_SEPARATOR, ltrim(str_replace(realpath(WP_PLUGIN_DIR), '', realpath(__FILE__)), DIRECTORY_SEPARATOR), 2)[0];
        return preg_replace('/[^a-zA-Z0-9]+/', '-', $pluginDirName . '-' . $path);
    }
}
9 июл. 2021 г. 19:13:17