解决 Yii2 assets 不自动更新问题

问题描述:core 里的 Asset (AssetBundle)更新 js 或 css 时,更新内容没有直接同步到其他模块

-- 如果想节约时间,直接拖到文章底部看结果就好~ 

一、项目目录结构(大概介样子)

二、需求

我希望在 core 建一个目录来管理各模块共同的 js 和 css(非共同放 backend/web 里就好)

三、core 静态目录

注:$sourcePath 指定静态文件资源目录,$css 说明要引入的 css 文件,$js 说明要引入的 js 文件

四、具体配置

corecommonconfigootstrap.php

Yii::setAlias('@statics', dirname(dirname(__DIR__)) . '/statics');

注:这里定义上一步 $sourcePath 里用到的目录别名

corecommonconfigmain.php

<?php
// 检查目录下文件的修改时间
if (!function_exists('_checkfilemtime_')) {
    function _checkfilemtime_($dir, $path, $pathHash) {
        $handle = opendir($dir);
        $hash = '';
        while (false !== ($entry = readdir($handle))) {
            if ($entry === '.' || $entry === '..') {
                continue;
            }
            $file  = $dir . '/' . $entry;

            if (is_dir($file)) {
                _checkfilemtime_($file, $path, $pathHash);
            } else {
                $dist = Yii::getAlias('@backend') . '/web/assets/' . $pathHash . str_replace($path, '', $file);
                if (!is_dir(dirname($dist))) {
                    mkdir(dirname($dist), 0755, true);
                }

                // 两个文件的修改时间相差5分钟及以上,则重新生成文件
                if (!file_exists($dist) || (filemtime($file)-filemtime($dist))>=300) {
                    file_put_contents($dist, file_get_contents($file));
                }
            }
        }
    };
}

return [
    ...
    'components' => [
        ...
        'assetManager' => [
            'hashCallback' => function ($path) {
                // 保持和 vendoryiisoftyii2webAssetManager.php 里 hash 函数的算法一致
                $pathHash = (is_file($path) ? dirname($path) : $path) . filemtime($path);
                $pathHash = sprintf('%x', crc32($pathHash . Yii::getVersion()));

                // 处理二级目录
                if (is_dir($path)) {
                    $path = str_replace("\", "/", $path);
                    _checkfilemtime_($path, $path, $pathHash);
                }

                return $pathHash;
            }
        ],
        ...
    ]
];

注:

1、Yii2 默认的 asset 管理器只会判断 assets 内一级文件的修改时候(生成hash值),不会扫描判断 assets 内二级目录下的文件。这里需要自定义处理;

2、需要在配置里设定 components.assetManager.hashCallback 函数来自定义处理静态资源的 hash 判断(返回的 hash 值一样则不会重新 publish);

3、所以,一个简单的做法就是:扫目录,判断 filemtime,重新生成 hash 值。例如这篇文章说一这样:https://upliu.net/yii2-assetbundle-does-not-update-auto.html

4、如果直接用 filemtime 重新生成 hash 值,会有一个新问题。那就是 backend/web/assets 下的目录会越来越多(你修改了文件就会生成一个新目录,但旧目录不会被删除)。生成太多无用的旧目录也是挺让人头疼的。

5、所以,我的处理方法是:不改变 return 的 hash 值(不会生成新的目录),只替换有更新的文件。具体操作请看上面代码~

 https://www.cnblogs.com/tujia/p/11114759.html


 完

原文地址:https://www.cnblogs.com/tujia/p/11114759.html