Webpack 配合 Laravel 实现静态资源版本号

1,616 阅读1分钟

虽然有Laravel Mix可以实现类似的功能,但是我个人并不喜欢这种把webpack配置细节都隐藏起来的方式。

首先写了一个简单的webpack插件,用来生成对应文件的hash版本号:

var md5 = require('md5');
var fs = require('fs');
var path = require('path');

function PHPAssetVerPlugin(configFile) {
    this.configFile = configFile;
}

PHPAssetVerPlugin.prototype.apply = function(compiler) {
    compiler.plugin('emit', function(compilation, callback) {
        var phpconfig = ['<?php\n', 'return ['];
        for (var filename in compilation.assets) {
            var buf = fs.readFileSync(
                            `${compiler.outputPath}/${filename}`);
            var hash = md5(buf).substr(0, 10);
            phpconfig.push(`    '${filename}' => '${hash}',`);
        }
        phpconfig.push('];');

        fs.writeFileSync(this.configFile, phpconfig.join('\n'));

        callback();
    }.bind(this));
};

使用时,在 webpack.config.jsplugins 部分加入我们的插件:

const config = {
    ...
    plugins:[
        ...

        // 初始化插件时传入,所需生成的php配置文件的路径,
        // 这里假设 webpack.config.js 在项目路根目录中,
        // 可以根据实际情况修改
        new PHPAssetVerPlugin(
            path.resolve(__dirname, 'config/assetver.php')
        )
    ]
    ...
}

这样配置好之后,每次webpack编译,都会在laravel的config目录生成 assetver.php, 文件内容类似:

<?php

return [
    'js/app.bundle.js' => '6b7650ed8c',
    'css/style.css' => '1041370383',
];

这样就可以通过laravel的配置,获取到对应文件的hash值,将hash值通过参数的方式接在引入文件的地方就可以。

也可以通过一个简单的helper函数来简化:

function vasset($path, $secure = null) {
        static $assetMap;
        if (!$assetMap) {
                $assetMap = config('assetver', []);
        }

        $url = asset($path, $secure);
        if (isset($assetMap[$path])) {
                $url .= '?v=' . $assetMap[$path];
        }

        return $url;
}

之后生成静态文件url的时候通过vasset函数,生成出来的url类似 http://localhost/js/app.bundle.js?v=6b7650ed8c

配置好后,每次通过webpack编译文件,对应的hash都会更新,起到自动更新资源文件缓存的作用。

这里只是提供一个思路,以上的代码都可以根据实际需要再进一步优化。

主要目的是让整个流程更直观易懂,并且简化复杂度,获取文件hash利用了laravel自己的配置来实现,没有引入其他新的概念。