20、大型 Web 应用性能优化全攻略

大型 Web 应用性能优化全攻略

1. 缓存实现

1.1 模型中的缓存

在处理汽车搜索结果视图时,为了提高性能,采用了缓存机制。通过在 GreenSearchResultsModel 中添加 setCache 方法来实现缓存。当展示汽车扩展列表时,事件处理程序会调用 GreenSearchResultsView show 方法,该方法会进一步调用模型的 setCache 方法。

GreenSearchResultsView.prototype.show = function()
{
   // When we show the view, check whether we can use the cache or not.
   this.model.setCache();
};

如果模型中已经包含汽车列表,将使用缓存列表,无需向服务器发送请求;若模型中没有该列表,则通过 Model setState 方法向服务器发送请求,并将返回的列表进行缓存,供下次使用。请求时会使用模型的 carID 成员作为参数。

1.2 使用 Expires 头

控制 Ajax 应用缓存的另一种方法是在服务器上设置 Expires 头。该头信息会告知浏览器结果何时过期。对于高度动态的数据,将其设置为 0 尤为重要。
在 PHP 中,可按以下方式设置:

// 设置立即过期
header("Expires: 0");
// 设置特定过期时间
header("Expires: Fri, 17 Jul 2009 16:00:00 GMT");

2. JavaScript 管理

2.1 JavaScript 放置位置

为了避免页面渲染因 JavaScript 文件加载而暂停,应尽可能将 JavaScript 放置在页面底部。不过,当页面的主要操作需要 JavaScript 支持,且相关组件位于页面顶部时,可使用 Page 类的 set_js_top 方法将 JavaScript 放置在页面顶部。
同时,为了保证模块的独立性,不要依赖 JavaScript 的特定放置位置来使用 DOM,可使用 YUI 库的 onDOMReady 方法在 DOM 稳定后执行回调函数。

2.2 JavaScript 压缩

压缩(Minification)是指去除 JavaScript 文件中的空白、注释等内容,以减小文件大小,从而缩短下载时间。可使用 Douglas Crockford 的 JSMin 工具(http://www.crockford.com/javascript/jsmin.html)或 YUICompressor(http://developer.yahoo.com/yui/compressor)进行压缩。
为了在开发环境和生产环境之间平滑过渡,可使用 Page 类的 register_links 方法,通过设置 $js_is_local 标志来选择不同的文件路径。

class SitePage extends Page
{
   ...
   public function register_links()
   {
      $this->aka_path = "http://...";
      $this->loc_path = "http://...";
      $this->js_linked_info = array
      (
         "sitewide.js" => array
         (
            "aka_path" => $this->aka_path."/sitewide_20090710-min.js",
            "loc_path" => $this->loc_path."/sidewide_20090710.js"
         ),
         ...
      );
      // Access the minified JavaScript files on the production servers.
      $this->js_is_local = false;
   }
   ...
}

2.3 去除重复文件

模块化开发可能会导致同一 JavaScript 文件被多次包含。使用键(keys)来管理 JavaScript 文件可以避免这种情况。 Page 类的 manage_js_linked 方法会检查文件是否已被添加到页面中,避免重复添加。

class Page
{
   ...
   private function manage_js_linked($keys)
   {
      $js = "";
      if (empty($keys))
         return "";
      // Normalize so that we can pass keys individually or as an array.
      if (!is_array($keys))
         $keys = array($keys);
      foreach ($keys as $k)
      {
         // Log an error for unknown keys when there is no link to add.
         if (!array_key_exists($k, $this->js_linked_info))
         {
            error_log("Page::manage_js_linked: Key \"".$k."\" missing");
            continue;
         }
         // Add the link only if it hasn't been added to the page before.
         if (array_search($k, $this->js_linked_used) === false)
         {
            $this->js_linked_used[] = $k;
            $js .= $this->create_js_linked($k);
         }
      }
      return $js;
   }
   ...
}

3. 资产分发

3.1 内容分发网络(CDN)

内容分发网络(如 Akamai 等)可通过复杂的缓存算法将内容分发到地理上接近用户的服务器,提高访问速度。Amazon 的 CloudFront 也为更多网站提供了这种高性能技术。
若公司可以使用 CDN,可将其服务器路径存储在 SitePage 类的 $aka_path 成员中。

3.2 减少 DNS 查找

资产分发到不同服务器时,要注意控制 DNS 查找次数。可在 SitePage 类中集中定义资产路径,以平衡 DNS 请求数量。一般建议将资产分布在 2 - 4 个主机上。

3.3 减少 HTTP 请求

3.3.1 CSS 文件管理

管理大型 Web 应用中 CSS 文件数量的一个好方法是定义一个通用的 CSS 文件供所有页面使用,为每个站点部分定义一个 CSS 文件,并尽量减少其他 CSS 文件的使用。同时,尽可能将多个 CSS 文件请求合并为单个请求。

3.3.2 JavaScript 文件管理

对于 JavaScript 文件,可使用一个通用文件包含适用于大部分站点的代码,为每个站点部分定义一组特定的文件,并尽量减少其他文件。可将相关文件合并以减少请求,并利用库中提供的组合文件。

3.3.3 图像文件管理

可使用精灵图(Spriting)技术将多个小图像合并为一个大图像,通过偏移量来显示所需部分。但该技术存在一些实际限制,如重复背景图像的合并条件,以及精灵图更新时的版本管理问题。
可按模块或 CSS 文件创建精灵图,并使用命名约定来管理。

#navbar .ichome .selected
{
   width: 50px;
   height: 50px;
   background: url(http://.../navbar_20090712.jpg) 0px 0px no-repeat;
}
#navbar .ichome .noselect
{
   width: 50px;
   height: 50px;
   background: url(http://.../navbar_20090712.jpg) -50px 0px no-repeat;
}

4. 网站指标控制

Google Analytics 是一个免费的服务,可用于分析用户如何使用 Web 应用。在 SitePage 类中添加 Google Analytics 代码,可轻松为整个 Web 应用启用指标跟踪。

class SitePage extends Page
{
   protected $google_site_id;
   protected $google_site_nm;
   ...
   public function __construct()
   {
      // You get the ID for your site once you've signed up with Google.
      $this->google_site_id = "...";
      $this->google_site_nm = "...";
   }
   ...
   public function get_all_js()
   {
      // First, get all the JavaScript that was assembled for the page.
      $js = parent::get_all_js();
      // This is the snippet of Google Analytics code from registering.
      $analytics = <<<EOD
<!-- Google Analytics -->
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol)
   ? "https://ssl."
   : "http://www.");
document.write(unescape("%3Cscript src='" +
   gaJsHost + "google-analytics.com/ga.js'
   type='text/javascript'%3E%3C/script%3E"));
var pageTracker = _gat._getTracker($this->google_site_id);
pageTracker._setDomainName($this->google_site_nm);
pageTracker._trackPageview();
</script>
EOD;
      // Append Google Analytics to the JavaScript that was assembled
      // otherwise for the page.
      return <<<EOD
$js
$analytics
EOD;
   }
   ...
}

为了确保指标的准确性,可定义一个标志来排除开发、测试等环境。

总结

通过上述缓存、JavaScript 管理、资产分发和指标控制等方法,可以有效提高大型 Web 应用的性能和用户体验。在实际应用中,可根据具体需求选择合适的优化策略。

流程图

graph TD
    A[开始] --> B[缓存实现]
    B --> B1[模型缓存]
    B --> B2[使用 Expires 头]
    A --> C[JavaScript 管理]
    C --> C1[放置位置]
    C --> C2[压缩]
    C --> C3[去除重复]
    A --> D[资产分发]
    D --> D1[CDN]
    D --> D2[减少 DNS 查找]
    D --> D3[减少 HTTP 请求]
    D3 --> D31[CSS 文件管理]
    D3 --> D32[JavaScript 文件管理]
    D3 --> D33[图像文件管理]
    A --> E[网站指标控制]
    E --> E1[添加 Google Analytics]
    B1 --> F[结束]
    B2 --> F
    C1 --> F
    C2 --> F
    C3 --> F
    D1 --> F
    D2 --> F
    D31 --> F
    D32 --> F
    D33 --> F
    E1 --> F

表格

优化方面 具体方法
缓存 模型缓存、设置 Expires 头
JavaScript 管理 放置位置优化、压缩、去除重复
资产分发 使用 CDN、减少 DNS 查找、减少 HTTP 请求
网站指标控制 添加 Google Analytics

5. 各优化方法的对比与选择

5.1 数据对比

为了更直观地了解不同优化方法的效果,我们可以通过以下表格进行对比:
| 优化方法 | 优化效果 | 实现难度 | 适用场景 |
| ---- | ---- | ---- | ---- |
| 模型缓存 | 显著减少服务器请求,提高响应速度 | 中等,需要处理缓存逻辑和数据一致性 | 数据更新频率较低,且请求数据量较大的场景 |
| 设置 Expires 头 | 控制浏览器缓存,减少不必要的请求 | 低,仅需在服务器端设置头信息 | 静态资源或数据更新频率可预测的场景 |
| JavaScript 放置底部 | 避免页面渲染阻塞,加快页面加载 | 低,调整文件位置即可 | 大部分页面场景,尤其是对首屏加载时间敏感的页面 |
| JavaScript 压缩 | 减小文件大小,缩短下载时间 | 中等,需要使用压缩工具 | 所有依赖 JavaScript 的页面,尤其是文件较大的情况 |
| 去除重复 JavaScript 文件 | 避免重复加载,节省带宽和加载时间 | 低,通过代码逻辑判断 | 模块化开发的大型应用 |
| 使用 CDN | 加速内容分发,提高访问速度 | 中等,需要配置 CDN 服务和路径 | 面向全球用户或访问量较大的网站 |
| 减少 DNS 查找 | 降低请求延迟,加快页面加载 | 中等,需要合理规划资产路径 | 资产分布在多个服务器的场景 |
| 减少 HTTP 请求 | 减少请求开销,提高性能 | 中等,需要合并文件或使用精灵图技术 | 页面资源较多的场景 |
| 添加 Google Analytics | 收集用户行为数据,优化用户体验 | 低,仅需添加代码片段 | 需要了解用户行为和优化网站的场景 |

5.2 选择建议

根据不同的业务需求和场景,我们可以选择合适的优化方法:
- 性能优先场景 :如果追求极致的性能和响应速度,可以优先考虑模型缓存、使用 CDN、减少 HTTP 请求等方法。例如,电商网站的商品列表页,需要快速展示大量商品信息,可使用模型缓存减少服务器请求,同时利用 CDN 加速图片和脚本的加载。
- 开发效率优先场景 :对于开发周期较短或资源有限的项目,可以选择实现难度较低的方法,如 JavaScript 放置底部、设置 Expires 头、去除重复 JavaScript 文件等。这些方法可以在不增加太多开发成本的情况下,提升页面性能。
- 数据监测场景 :如果需要了解用户的行为和使用习惯,以便优化网站体验,添加 Google Analytics 是必不可少的。例如,新闻网站可以通过分析用户的浏览路径和停留时间,优化文章推荐和页面布局。

6. 优化实践案例

6.1 案例背景

假设我们有一个大型的在线旅游网站,该网站包含大量的图片、JavaScript 脚本和 CSS 样式文件,同时需要频繁地从服务器获取旅游产品信息。由于用户访问量较大,网站的性能和用户体验成为了关键问题。

6.2 优化步骤

  1. 缓存实现
    • 在旅游产品数据模型中添加缓存机制,当用户请求旅游产品列表时,首先检查缓存中是否存在数据。如果存在,则直接使用缓存数据;如果不存在,则向服务器发送请求,并将返回的数据进行缓存。
    • 在服务器端设置 Expires 头,对于静态资源(如图片、CSS 文件)设置较长的过期时间,减少浏览器的重复请求。
  2. JavaScript 管理
    • 将大部分 JavaScript 文件放置在页面底部,避免页面渲染阻塞。对于一些需要在页面加载时立即执行的脚本,使用 onDOMReady 方法确保 DOM 稳定后再执行。
    • 使用 YUICompressor 对 JavaScript 文件进行压缩,减小文件大小。同时,通过 Page 类的 register_links 方法,在开发环境和生产环境中分别使用未压缩和压缩后的文件。
    • 利用 Page 类的 manage_js_linked 方法,避免重复加载 JavaScript 文件。
  3. 资产分发
    • 引入 CDN 服务,将图片、CSS 文件和 JavaScript 文件分发到全球各地的节点服务器,提高用户的访问速度。
    • SitePage 类中集中定义资产路径,合理规划 DNS 查找,将资产分布在 2 - 4 个主机上,减少请求延迟。
    • 对于 CSS 文件,合并多个文件为一个请求;对于图片,使用精灵图技术将多个小图标合并为一个大图片,减少 HTTP 请求。
  4. 网站指标控制
    • SitePage 类中添加 Google Analytics 代码,收集用户的访问数据,包括页面浏览量、停留时间、转化率等。通过分析这些数据,优化网站的页面布局和内容推荐。

6.3 优化效果

通过以上优化措施,该在线旅游网站的性能得到了显著提升:
- 页面加载时间缩短了 30%,用户可以更快地浏览旅游产品信息。
- 服务器请求次数减少了 40%,降低了服务器压力,提高了系统的稳定性。
- 通过 Google Analytics 数据分析,用户转化率提高了 15%,用户体验得到了明显改善。

7. 未来优化方向

7.1 新技术应用

随着 Web 技术的不断发展,一些新兴技术可以进一步提升网站性能,如 Service Worker、WebAssembly 等。
- Service Worker :可以在浏览器和网络之间充当代理,实现离线缓存和后台同步功能。通过注册 Service Worker,可以在用户离线时继续提供部分功能,提高用户体验。
- WebAssembly :是一种新的二进制指令格式,可以在浏览器中以接近原生的速度运行代码。对于一些计算密集型的任务,如复杂的数据分析和图形处理,使用 WebAssembly 可以显著提高性能。

7.2 持续优化策略

性能优化是一个持续的过程,需要不断地监测和调整。可以建立性能监测系统,实时监控网站的各项性能指标,如页面加载时间、服务器响应时间、吞吐量等。根据监测结果,及时发现性能瓶颈,并采取相应的优化措施。

7.3 用户体验优化

除了性能优化,用户体验也是至关重要的。可以通过 A/B 测试等方法,对网站的界面设计、交互流程等进行优化,提高用户的满意度和忠诚度。

8. 总结与回顾

8.1 关键要点回顾

本文详细介绍了大型 Web 应用性能优化的多种方法,包括缓存实现、JavaScript 管理、资产分发和网站指标控制等方面。通过合理运用这些方法,可以有效提高网站的性能和用户体验。
- 缓存实现 :通过模型缓存和设置 Expires 头,减少服务器请求,提高响应速度。
- JavaScript 管理 :优化 JavaScript 文件的放置位置、进行压缩和去除重复文件,避免页面渲染阻塞,缩短下载时间。
- 资产分发 :使用 CDN、减少 DNS 查找和 HTTP 请求,加速内容分发,降低请求延迟。
- 网站指标控制 :添加 Google Analytics 收集用户行为数据,为网站优化提供依据。

8.2 行动建议

在实际应用中,建议根据具体的业务需求和场景,选择合适的优化方法。同时,要建立性能监测和优化机制,持续改进网站的性能和用户体验。

流程图

graph TD
    A[确定业务需求和场景] --> B{选择优化方法}
    B --> C1[缓存实现]
    B --> C2[JavaScript 管理]
    B --> C3[资产分发]
    B --> C4[网站指标控制]
    C1 --> D1[模型缓存]
    C1 --> D2[设置 Expires 头]
    C2 --> D3[放置底部]
    C2 --> D4[压缩]
    C2 --> D5[去除重复]
    C3 --> D6[使用 CDN]
    C3 --> D7[减少 DNS 查找]
    C3 --> D8[减少 HTTP 请求]
    C4 --> D9[添加 Google Analytics]
    D1 --> E[实施优化]
    D2 --> E
    D3 --> E
    D4 --> E
    D5 --> E
    D6 --> E
    D7 --> E
    D8 --> E
    D9 --> E
    E --> F[性能监测]
    F --> G{是否满足要求}
    G -- 是 --> H[持续优化]
    G -- 否 --> B

表格

未来优化方向 具体技术或策略 预期效果
新技术应用 Service Worker、WebAssembly 实现离线缓存、提高代码运行速度
持续优化策略 建立性能监测系统 及时发现性能瓶颈,持续改进
用户体验优化 A/B 测试、界面设计优化 提高用户满意度和忠诚度
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值