虽然有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.js 中 plugins 部分加入我们的插件:
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自己的配置来实现,没有引入其他新的概念。