前言
一直觉得自己的博客站点页面加载很慢, 就想着去优化一下. 呐, 下图是一次文章页面的加载, 需要2.5s. 其中 js 文件就有18个. 众所周知, 浏览器对资源文件的并行下载数量是有限制的(不同浏览器限制不同). 也就是说, 这18个 js 文件是无法同时下载的, 再说了, 页面中还有其他资源文件, 因此. 减少资源文件的数量, 就可以提高页面的加载速度.

合并 js 文件
首先, 尝试将页面的 js 文件进行合并. 这里我使用了比较通用的方法, 正则匹配. 因此需要的话, 你大概率也可以使用:
<?php
ob_start(function($content){
$mergePatternJsData = function ($content, $pattern, $replaceStr){
$noMatch = fn() => str_replace($replaceStr, "", $content);
preg_match($pattern, $content, $matches);
if(empty($matches[0])) return $noMatch();
$pattern = "/<script\s*src='(.*)'.*><\/script>/U";
preg_match_all($pattern, $matches[0], $itemMatch);
$itemMatch = fileCantMergeFile($itemMatch);
if(empty($itemMatch[0])) return $noMatch();
$replaceUrl = self::mergeResData($itemMatch[1]);
$content = str_replace($itemMatch[0], '', $content);
return str_replace($replaceStr, "<script src='{$replaceUrl}'></script>", $content);
};
$headerPattern = '/<head>[\S\s]*<\/head>/U';
$content = $mergePatternJsData($content, $headerPattern, self::JS_REPLACE_HEAD_STR);
$bodyPattern = '/<body[\s>][\S\s]*<\/body>/U';
return $mergePatternJsData($content, $bodyPattern, self::JS_REPLACE_FOOTER_STR);
});
function mergeResData($urlList){
if(empty($urlList)) return null;
$workPath = __DIR__;
$relativePath = '';
$filename = md5(implode('', $urlList)).'.js';
$filepath = "{$workPath}/{$relativePath}/{$filename}";
if(!file_exists($filepath)){
$allContent = '';
foreach ($urlList as $itemUrl){
$allContent .= PHP_EOL.file_get_contents($workPath.parse_url($itemUrl, PHP_URL_PATH));
}
$dirname = dirname($filepath);
if(!is_dir($dirname)) mkdir($dirname, 0777, true);
file_put_contents($filepath, $allContent);
}
return "http://xxx.com/{$relativePath}/{$filename}";
}
如此一来, 就可以将页面中的 js 文件数量降低为2个了. 看一下效果, 效果还是十分显著的, js 数量减少了12个(多出来的是由 js 文件引入的 js), 时间减少了差不多0.9s

合并 css
既然 js 文件可以合并, 那么自然, css 也能够合并. 合并的代码拿上面的改改就出来了. 这里直接上效果
在合并之前, css 文件9个. 合并后为2个(因为其中一个使用了相对路径), 时间减少了差不多0.1s 左右. 这里是因为 css 文件数量不多, 且文件本身较小, 所以效果没有 js 那么明显.

js 和 css 都进行了合并, 难道就完了么? 不. 我们还可以对其进行压缩.
压缩 js/css
找到了这个库: mrclay/minify . 直接composer require mrclay/minify 引进来就行.
使用如下方法在将内容写入到缓存文件时, 对其进行压缩:
<?php
$allContent = JSMin::minify($allContent)
$allContent = Minify_CSSmin::minify($allContent)
这里, 因为加载的 js 和 css 本身大部分就已经是压缩过的了, 因此效果并不是那么明显. 时间仅减少了0.1s. 若是 资源文件本身没有压缩, 效果会更明显.

最终
最终效果, 页面的加载时间从原本的2.5s, 降低到了1.4s. 当然, 不同的网络环境, 时间也会不同, 但这也减少了差不多45%的加载时间, 而这, 还仅仅是通过合并资源文件来实现的. 想象平常我们究竟为了这玩意浪费了多少用户的时间啊.
|