减少页面加载时间方法
1.概论
Web应用程序与传统的客户端服务器应用程序相比有几个优点:由于业务代码来自唯一的服务器(在此处忽略集群),因此它们始终是最新的。 此外,部署新版本仅需几分钟。
但是,它们有一个很大的缺点。 由于HTML代码是通过网络发送的,因此响应性通常比传统应用程序要小得多。
一个交互式系统的响应描述如何Swift响应用户输入(即通信与系统的速率)。
http://en.wikipedia.org/wiki/响应度
Ajax克服了其中的一些建议,建议在开始时加载整个页面以及修改页面的相关块。 但是,这只是解决方案的一部分,因为页面的初始加载对用户而言将是最困难的。 用户不喜欢等待页面加载。 作为用户,您不喜欢等待。 作为一个很好的经验法则,您必须尽一切努力实现小于1秒的初始页面加载时间(您可以在这篇非常有趣的文章中找到有关加载时间步骤的其他信息)。 此加载时间不包括整个页面,样式表和脚本完成下载的时间,而仅包括用户显示相关信息并开始与屏幕进行交互的时间。 这取决于上下文,但是结论是:页面显示的时间越少,效果越好。
2.减少加载时间
雅虎提供了34种最佳实践来加速您的网站 。 如果您使用Mozilla Firefox,并且已经使用了出色的FireBug插件,则应向其中添加YSlow插件(如果没有,请事先下载FireBug )。 YSlow会检查您正在使用Firefox浏览的网页中的13条规则。 有关此事的重要规则是:
- 将JS和CSS置于外部,
- 发出更少的HTTP请求,
- 缩小JS (和CSS )。
第一点很不言而喻。 无需将JS代码和CSS信息放入HTML中,而是将它们放入外部文件中并从页面中引用它们:没什么大不了的,如今每个人都在做。 第二点与第一点相反:对于每个文件,必须发出一个单独的HTTP请求。 因此,最好的解决方案是您的主要HTML加上一个JavaScript文件和一个CSS文件。 第三点是缩小这些文件,即删除注释,多余的空格和换行符,以使这些文件更轻。 选项还包括重命名变量,以使它们的名称更短(可能会(有意或无意)混淆)。
3.在构建时缩小
在所有可用的工具中, Yahoo UI Library Compressor是一个用于缩小JS和CSS(从v2.0开始)的好工具。 它是用Java开发的,可以从命令行运行。 这样的命令可以在构建过程中发生。 以下Ant任务在simple.js上执行缩小过程:
<!-- Executes YUI compressor on simple JS file -->
<targetname="simplest">
<javajar="tools/yuicompressor-2.4.2.jar"fork="true">
<argvalue="-v"/>
<argvalue="web/script/simple.js"/>
</java>
</target>
该解决方案的主要缺点是,您丢失了原始脚本,而使用了缩小的脚本。 YUI压缩器允许在新脚本中输出缩小的脚本,因此可以输出以下Ant目标:
<!-- Executes YUI compressor on simple JS file -->
<targetname="simple">
<javajar="tools/yuicompressor-2.4.2.jar"fork="true">
<argvalue="-v"/>
<argvalue="web/script/simple.js"/>
<argvalue="-o"/>
<argvalue="${build.dir}/web/script/simple.js"/>
</java>
</target>
这使过程稍好一些。 但是,我无法在自己喜欢的IDE下测试缩小的脚本,因为该脚本仅在WAR创建范围内正确,而在IDE内部署范围内正确。
4.在运行时缩小
为了避免这种缺陷,我们可以缩小运行时进程。 为此,我们创建一个与.js扩展名关联的过滤器:
packagech.frankel.blog.jawr.web;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.InputStreamReader;
importjava.io.PrintWriter;
importjava.io.Reader;
importjava.io.StringWriter;
importjavax.servlet.Filter;
importjavax.servlet.FilterChain;
importjavax.servlet.FilterConfig;
importjavax.servlet.ServletException;
importjavax.servlet.ServletRequest;
importjavax.servlet.ServletResponse;
importjavax.servlet.http.HttpServletRequest;
importcom.yahoo.platform.yui.compressor.JavaScriptCompressor;
/**
* Filter that minifies JavaScript files. Can be used with CSS files with less configuration.
*
* @author Nicolas Fränkel
* @since 17 mars 2009
*/
publicclassYuiCompressorFilterimplementsFilter{
/** Configuration object. */
privateFilterConfigconfig;
/** Number of kept linebreaks. */
privateintlinebreak;
/** Munge. */
privatebooleanmunge;
/** Verbose. */
privatebooleanverbose;
/** Should all semicolons be kept. */
privatebooleanpreserveAllSemiColons;
/** Should optimization be disabled. */
privatebooleandisableOptimizations;
/**
* This implementation does nothing.
*
* @see javax.servlet.Filter#destroy()
*/
@Override
publicvoiddestroy(){}
/**
* Compress JS and CSS output.
*
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
* javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
@Override
publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)
throwsIOException,ServletException{
StringWriterstringWriter=newStringWriter();
finalPrintWriterprintWriter=newPrintWriter(stringWriter);
HttpServletRequesthttpRequest=(HttpServletRequest)request;
Stringpath=httpRequest.getServletPath();
InputStreamstream=config.getServletContext().getResourceAsStream(path);
Readersource=newInputStreamReader(stream);
stream.close();
JavaScriptCompressorcompressor=newJavaScriptCompressor(source,newBasicErrorReporter());
compressor.compress(printWriter,linebreak,munge,verbose,preserveAllSemiColons,disableOptimizations);
response.getWriter().write(stringWriter.getBuffer().toString());
printWriter.close();
}
/**
* Reads filter parameters.
*
* @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
*/
@Override
publicvoidinit(FilterConfigconfig)throwsServletException{
this.config=config;
StringlinebreakString=config.getInitParameter("linebreak");
StringmungeString=config.getInitParameter("munge");
StringverboseString=config.getInitParameter("verbose");
StringpreserveAllSemiColonsString=config.getInitParameter("preserveAllSemiColons");
StringdisableOptimizationsString=config.getInitParameter("disableOptimizations");
munge=Boolean.parseBoolean(mungeString);
verbose=Boolean.parseBoolean(verboseString);
preserveAllSemiColons=Boolean.parseBoolean(preserveAllSemiColonsString);
disableOptimizations=Boolean.parseBoolean(disableOptimizationsString);
try{
if(linebreakString!=null){
linebreak=Integer.parseInt(linebreakString);
}
}catch(NumberFormatExceptione){
thrownewServletException(e);
}
}
}
现在,我们的压缩器可以在我们最喜欢的IDE内外运行。 但是缺点是每次需要资源时应用过滤器都会降低性能。 为了减少此成本,我们可以:
- 实现将路径映射到内存中最小化脚本(作为字符串)的缓存,
- 通过使用与到期值相关的HTTP标头来依赖浏览器缓存。
尽管如此,我还是觉得这并不令人满意...首先,YUI压缩机不应该以这种方式使用。 这之所以显示出来,是因为找不到关于方法的单独使用的文档(JavaDoc或其他文档)。 然后,我编写的代码越少,我的感觉就越好。 在这种情况下,我必须编写一个完整的过滤器,并带有初始化参数。 最后但并非最不重要的一点是,您还记得本文顶部的3条规则吗? 我们只解决了第三点,将脚本最小化,但是通过使用YUI压缩程序,我们绝不会减少HTTP请求。 如果我们有15个不同的源脚本,那么最后仍然会有15个缩小的脚本,因此需要15个HTTP请求才能全部获得。
5. Jawr
Jawr是解决我们问题的解决方案:它使开发过程中具有不同的脚本(第三方脚本,企业框架脚本,应用程序脚本等),并在应用程序启动时将它们捆绑在一个大脚本文件中。 该过程对开发人员来说是完全透明的,并且是轻量级的,因为所有工作都在应用程序启动时完成。
其他功能包括:
- 捆绑任何JavaScript或CSS文件,无论所选的目录结构如何,
- 动态修改这些文件,例如使用
ResourceBundle
消息, - 可以使用YUI Compressor或JSMin实现JavaScript和CSS最小化(哦,真是个惊喜!),
- 通过缓存实施是对发送的HTTP标头的修改,
- GZip支持兼容的浏览器。
为了做到这一点,Jawr使用了三种组件:
- 一个服务于JavaScript和CSS内容的servlet,
- 引用JS和CSS的颚式标签库,
- Java属性格式的配置文件。
Web部署描述符的配置如下所示:
<servlet>
<servlet-name> JawrServlet </servlet-name>
<servlet-class> net.jawr.web.servlet.JawrServlet </servlet-class>
<init-param>
<param-name> configLocation </param-name>
<param-value> /jawr.properties </param-value>
</init-param>
<load-on-startup> 1 </load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name> JawrServlet </servlet-name>
<url-pattern> *.js </url-pattern>
</servlet-mapping>
一个示例属性文件如下所示
#Turning on compression when possible jawr.gzip.on=true #Using YUI compressor jawr.js.bundle.factory.bundlepostprocessors=YUI #Bundling into all.js jawr.js.bundle.all.id=/script/all.js #Bundled scripts jawr.js.bundle.all.mappings=/script/simple.js, /script/sub/b.js, /script/sub/subsub/a.js
然后,您将在页面中像这样使用它:
<%@taglibprefix="jawr"uri="http://jawr.net/tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<metahttp-equiv="Content-Type"content="text/html; charset=ISO-8859-1">
<title> Jawr test welcome page </title>
</head>
<bodyonload="a();b()"/>
<jawr:scriptsrc="/script/all.js"/>
</html>
您将在其中找到用Eclipse制作的Jawr示例项目以及前面的YUI Compressor示例。 本示例向您展示Jawr的主要用途,主要是:
- 捆绑JavaScript文件,
- 缩小它们,
- 压缩捆绑的文件(如果您的浏览器支持的话)。
作为示例,它将仅输出两个JavaScript警报框,但是如果需要进一步说明,它将为您提供框架。
六,结论
缩小外部文件并不是减少网页加载时间的唯一考虑。 您还应该减少这些文件的最大数量。 Jawr是一个用于优雅地完成这两项工作的OpenSource组件:我希望本文使您确信Jawr是用于此用法的正确工具。
减少页面加载时间方法