当我试图改善我拥有的画廊中缩略图的加载时间时,一切都开始了。所有图像的路径都来自 JSON 文件/字符串/响应以及有关它们的一些详细信息,以构建 UI。
我的第一个想法是用 JavaScript 本身缓存它们:
for( let i = 0; i < data.length; i++ ) {
let thumbnail = new Image();
thumbnail.src = data[ i ].thumbnail;
}
使用 BabelJS 的 ES2015
我知道这不是最好的方法,因为我应该按需加载它们(即在 JSON 中访问它们的偏移量时),甚至与 AJAX 异步加载。事实上,我也尝试了两种方法,但我没有设法让其他数据在填充 UI 之前等待图像完全加载。
不过这是以后的事了^_^
因此,我检查了 Chrome Inspector 并在Network选项卡下按预期加载了所有 JPG,但是当实际使用图像时,修改src
为预览设计的容器的属性(见下文),每个图像都被再次加载。
$( 'figure img' ).attr( 'src', data[ current ].thumbnail );
这只是一个片段。'current' 是通过 JSON 导航的画廊计数器
在用尽我的测试技能后,我最终相信问题出在我的服务器上。
我目前正在使用 PHP Internal Webserver 进行开发,因为至少到目前为止,我不需要完整的服务器解决方案。打开几个命令行窗口很糟糕,但无论如何......
为了记录,网络服务器是这样启动的:
php.exe -c "path\to\php.ini" -S "0.0.0.0:8080" -t "." "routing.php"
Windows环境下运行>.<
我以前的路由文件很生硬,false
如果请求图像,js,css,字体就返回......所以,在阅读了这里的几个主题之后,我改变了它,试图包含一些缓存:
<?php
if( preg_match( '/\.(js|ico|gif|jpg|png|css|eot|svg|ttf|woff|php)$/', $_SERVER["REQUEST_URI"] ) ) {
date_default_timezone_set( 'America/Sao_Paulo' );
$file = sprintf( '.%s', $_SERVER['REQUEST_URI'] );
if( ! file_exists( $file ) ) {
header( 'HTTP/1.1 404 Not Found' );
}
$eTag = md5_file( $file );
if( $eTag !== FALSE ) {
header( 'Etag: ' . $eTag );
}
header( 'Cache-Control: public, max-age=2592000' );
$mTime = filemtime( $file );
if( $mTime !== FALSE ) {
$GMD = gmdate('D, d M Y H:i:s', $mTime );
header( sprintf( 'Last-Modified: %s GMT', $GMD ) );
if( isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) {
$mSince = strtotime( $_SERVER['HTTP_IF_MODIFIED_SINCE'] );
if( $mSince !== FALSE && $mSince == $GMD ) {
header( 'HTTP/1.1 304 Not Modified' ); return false;
}
}
if( isset( $_SERVER['HTTP_IF_NONE_MATCH'] ) ) {
$noneMatch = str_replace( '"', '', stripslashes( $_SERVER['HTTP_IF_NONE_MATCH'] ) );
if( $noneMatch == md5( $file . $mTime ) ) {
header( 'HTTP/1.1 304 Not Modified' ); return false;
}
if( $noneMatch == $eTag ) {
header( 'HTTP/1.1 304 Not Modified' ); return false;
}
}
}
// Resource not cached yet
header( 'Content-Type: ' . mime_content_type( $file ) );
header( 'Content-Length: ' . filesize( $file ) );
return false;
}
include __DIR__ . '/index.php';
性能要好得多,但是,直接用一个文件进行测试,第一次加载大约需要 300 毫秒,第二次大约需要 5 毫秒,第三次大约需要 300 毫秒,第四次大约需要 5 毫秒,依此类推。oO
然后我在整个应用程序中对其进行了测试,缓存问题仍然存在,尽管理论上,图像已经用 JavaScript 加载并存储在图像对象中,当它们在 JSON 中的相应偏移量通过导航访问时再次加载。
此外,当多次刷新页面时,我没有与直接访问相同的“跳跃”响应时间。所有不是来自 CDN(jQuery、Bootstrap...)的东西都被一次又一次地加载。>:(
经过更多研究,我发现的两个罪魁祸首是Cache-control
未设置和整体状态代码。
我找不到304 Header
使用 PHP Internal WebServer 发送的方法,不是因为我不知道怎么做,毕竟代码是一样的,而是因为我看到的所有实现都依赖于一些$_SERVER
条目,就我而言知道,是由 Apache(可能还有其他专用服务器应用程序)提供的。
此外,由于某种原因,在 Chrome Inspector 中,打开资源的Headers部分,我看不到Response HeadersCache-control
下的指令,即使我确实设置了它,如您所见,到期时间约为 30 天。
除了如何解决这些问题之外,我还想了解为什么会发生这种情况。