利用浏览器缓存来优化第三方JS的加载速度

34

我已在我的httpd.conf中设置了过期时间

ExpiresActive On
ExpiresDefault "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType text/css "access plus 1 month"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType application/x-javascript "access plus 1 month"

这有助于图像、字体文件、网站自己的CSS和JS文件的浏览器缓存。但我网站中也包含外部JS:

http://connect.facebook.net/en_US/sdk.js (20 minutes)
http://apis.google.com/js/client.js (30 minutes)
https://apis.google.com/js/rpc:shindig_random.js?onload=init (30 minutes)
https://platform.twitter.com/widgets.js (30 minutes)
https://www.google-analytics.com/analytics.js (2 hours)

Google Pagespeed Insights说对于上述文件:

在HTTP头中设置过期日期或最大年龄,可以指示浏览器从本地磁盘加载之前下载过的资源,而不是通过网络加载。

如何利用浏览器缓存这些外部JS文件?有什么帮助吗?

3个回答

46
一个令人烦恼的问题,确实如此。恐怕这不是一个易于解决的问题。但你可以使用一个cron。
首先,请记住,Google很不可能因为他们自己的工具(如Analytics)而对你进行惩罚。然而,正如之前提到的那样,可以使用cron来解决这个问题,它基本上意味着您在本地加载JavaScript并拉取更新的脚本。
如何做到这一点:
首先,您需要下载正在运行的脚本。我将以Google Analytics为例(这似乎是人们抱怨最多的问题脚本,但您可以为任何外部脚本复制此操作)。
在代码中查找脚本的名称,在我们的例子中为:google-analytics.com/ga.js。将此URL放入您的Web浏览器中,它将显示源代码。只需将其复制并保存为ga.js即可。
将这个新创建的JavaScript文件保存到您的Web服务器上,在我的情况下:
- JS
  - ga.js

接下来,您需要更新调用脚本的页面上的代码,并更改调用JavaScript文件的目录。在我们的案例中,我们将再次更改此行:

ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';

为了

ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.yoursite.com/js/ga.js';

现在,您的网站将从您的网站本地运行脚本!但是,这意味着脚本永远不会更新。除非您每周重新运行此短过程。这取决于您...但我太懒了。

这就是CRON发挥作用的地方:

几乎每个托管服务都会为您提供设置cron作业的选项。在Hostinger上,它位于您的Hosting Panel上,在GoDaddy上,您将在Content选项下找到它。

将以下脚本放入您的cron中,您只需要更改变量$localfile的绝对路径即可。该脚本的功能是从Google中获取更新后的ga.js文件。您可以设置执行此过程的时间范围。从每小时一次到一个月一次及以上。

如果您还要针对Google Analytics以外的外部文件执行此操作,则还需要更改变量$remoteFile。因此,$remoteFile是指外部JavaScript文件的URL,而变量$localFile则是指新的本地存储文件的路径,就这么简单!

<?
// script to update local version of Google analytics script

// Remote file to download
$remoteFile = 'http://www.google-analytics.com/ga.js';
$localfile = 'ENTER YOUR ABSOLUTE PATH TO THE FILE HERE';
//For Cpanel it will be /home/USERNAME/public_html/ga.js

// Connection time out
$connTimeout = 10;
$url = parse_url($remoteFile);
$host = $url['host'];
$path = isset($url['path']) ? $url['path'] : '/';

if (isset($url['query'])) {
  $path .= '?' . $url['query'];
}

$port = isset($url['port']) ? $url['port'] : '80';
$fp = @fsockopen($host, '80', $errno, $errstr, $connTimeout );
if(!$fp){
  // On connection failure return the cached file (if it exist)
  if(file_exists($localfile)){
    readfile($localfile);
  }
} else {
  // Send the header information
  $header = "GET $path HTTP/1.0\r\n";
  $header .= "Host: $host\r\n";
  $header .= "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6\r\n";
  $header .= "Accept: */*\r\n";
  $header .= "Accept-Language: en-us,en;q=0.5\r\n";
  $header .= "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n";
  $header .= "Keep-Alive: 300\r\n";
  $header .= "Connection: keep-alive\r\n";
  $header .= "Referer: http://$host\r\n\r\n";
  fputs($fp, $header);
  $response = '';

  // Get the response from the remote server
  while($line = fread($fp, 4096)){
    $response .= $line;
  }

  // Close the connection
  fclose( $fp );

  // Remove the headers
  $pos = strpos($response, "\r\n\r\n");
  $response = substr($response, $pos + 4);

  // Return the processed response
  echo $response;

  // Save the response to the local file
  if(!file_exists($localfile)){
    // Try to create the file, if doesn't exist
    fopen($localfile, 'w');
  }

  if(is_writable($localfile)) {
    if($fp = fopen($localfile, 'w')){
      fwrite($fp, $response);
      fclose($fp);
    }
  }
}
?>

那就是这样,它可以解决您在Leverage Browser Caching第三方脚本方面遇到的任何问题。
来源:http://diywpblog.com/leverage-browser-cache-optimize-google-analytics/ 注意:
实际上,这些文件对您的页面速度并没有太大影响。但我可以理解您对谷歌惩罚的担忧。但只有当您运行大量这些外部脚本时才会发生这种情况。与谷歌相关的任何内容也不会对您产生负面影响,正如我之前所述。

2
这不能通过所有第三方脚本完成。其中许多需要从它们原始的域名进行访问,以启用cookie设置和其他特定于域的行为。 - Scott A
一个保留cookie和其他特定于域的行为的替代解决方案是通过您的服务器代理这些请求,但指示代理添加到期日期(并不要忘记确保代理仅接受您预期的URL)。我以前见过一个WordPress插件这样做。 - hostingutilities.com
这是否需要编辑每个加载外部脚本的插件? - Shawn W

2

不确定这段代码片段是否会对某个人有所帮助,但无论如何,这就是我缓存外部JS文件的方法。

<script>
 $.ajax({
 type: "GET",
 url: "https://www.google-analytics.com/analytics.js",
 success: function(){},
 dataType: "script",
 cache: true
 });
</script>

我测试了这个方法,但是脚本没有缓存。 - Shawn W
你可能需要将脚本包装成jQuery函数,否则你的WordPress构建将显示错误。 - Nuno Sarmento

1
如果您使用WordPress,则可以使用“Cache External Scripts”插件来实现此功能。通过最小的插件代码调整,您可以为Google之外的第三方JavaScript文件添加支持。

值得一提的是,此插件需要具备 PHP 知识和能力,以便读取和理解所查看的内容。如果您不是 PHP 程序员,则无法使用此插件。 - catbadger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接