网站优化

虽然图像占大多数网站页面重量的大部分,但调用和实现这些图像的 HTML 和 CSS 也会影响总页面加载时间。您构建和命名标记的方式可以帮助您保持网站的可维护性和高性能;有意组织您的 CSS 和设计模式将使您能够专注于可再利用性和网站外观背后的含义。保持你的 HTML 和 CSS 干净和有意义将导致更快的加载网站和更好的整体用户体验。在本章中,我们将介绍在您的站点上加载 HTML、CSS、字体和 JavaScript 的最佳实践。


清理你的 HTML

干净的 HTML 是高性能网站的基础。尽管较旧的站点往往会受到多个设计人员或开发人员编辑和添加标记的影响,但即使是较新的站点也可以从彻底清扫中受益——寻找嵌入式或内联样式、未使用或不必要的元素以及命名不佳的类和 ID。


在第 1 章中,我提到我能够通过简单地清理其标记和样式将一个站点的页面加载时间缩短一半。我专注于消除臃肿的 HTML 和 CSS,这导致 HTML、CSS 和样式表图像文件的大小更小。


查看您网站的 HTML 时,请注意:


  • 应移动到样式表的嵌入式或内联样式
  • 不需要特殊样式的元素(不必要的 HTML 元素,也称为“divitis”,将在下一节中介绍)
  • 可以删除的旧的、注释掉的代码

如果一个网站已经被多个开发人员或设计人员编辑过,可能会有一些看起来没有使用或不必要的标记。随着网站的老化,过时的技术(例如使用表格进行布局)往往会在没有被清理或更新为更新的最佳实践的情况下继续存在。在消除任何多余或过时的 HTML 时要无情。保留不必要或复杂的标记很少有很好的“以防万一”的理由;通常最好杀死它并知道,如果你真的需要,你可以在将来使用版本控制来引用它。


迪维蒂斯

“Divitis”发生在您的 HTML 中有很多除了帮助您设置内容样式之外几乎没有其他用途的元素。当大量 div 元素代替更有意义的语义 HTML 元素时,通常会发生 divitis,但任何类型的 HTML 元素都可能发生混乱:


<div> <div> <header> <div id="header"> <h1><span>Site Name</span></h1> </div> </header> </div> </div>

尚不清楚为什么在前面的示例中有这么多元素;也许跨度内的样式会发生一些奇特的事情;也许其他那些div对页面结构有意义。但这绝对是有问题的迹象,应该使用您的标记进行检查。通常 divitis 表明代码作者对样式的级联特性感到不知所措,并希望尝试覆盖元素的外观和感觉,并通过添加额外的父元素来使用 CSS 来实现目标。


Divitis 应该在你的标记中被根除。它增加了 HTML 和 CSS 的膨胀,并且通过删除不必要的元素,您将为您的站点创建一个更有意义和更直接的层次结构。如果可能,请使用 HTML5 元素(例如header和article)来创建语义层次结构。更容易理解应该如何编写 CSS,并为可重复使用的设计模式提供机会。


要消除 divitis,请查看应用于臃肿区域元素的样式。看看是否可以组合样式声明并将它们应用于正确的语义 HTML 元素以产生更好的 HTML 层次结构,例如:


<header> <h1>Site Name</h1> </header>

或者简单地说:


<h1>Site Name</h1>

有时,您需要为布局和语义结构保留一些元素,例如本示例中的 header 元素。但通常情况下,检查和减少页面上的元素数量会让你大吃一惊;借助 HTML5 和 CSS 的强大功能,您将能够通过稳固、轻量级的 HTML 层次结构完成很多工作。


语义

语义元素名称是那些表示元素内内容类型的名称。良好的语义元素选择包括具有代表性的 HTML5 元素,如headeror nav,或类和 ID 名称,如loginor breadcrumbs。避免使用无意义的名称,如leftor blue,它们向用户描述内容的外观和感觉,而不是内容的含义。


将元素重命名为更具语义性将帮助您为页面创建更好的 HTML 结构,并且还允许您创建设计模式以在整个站点中重用。例如,这是一个带有一点点 divitis 的无语义 HTML 结构:


<div class="right"> <div id="form"> <form> <p class="heading">Login</p> <p> <label for="username">Username:</label> <input type="text" id="username" /> </p> <p> <label for="password">Password:</label> <input type="text" id="password" /> </p> <input type="submit" value="Submit" /> </form> </div> </div>

此侧边栏和登录表单的样式:


form { background: #ccc; } .right { float: right; width: 200px; } #form form { border: 1px #ccc solid; background: yellow; padding: 10px; } .heading { font-weight: bold; font-size: 20px; }

在这个例子中,这些元素当前的命名方式并没有什么特别的意义。很容易覆盖样式表中.right其他地方的样式,而不会意识到它会影响使用此类名称的其他元素。


此外,尚不清楚这些样式中的哪些是可以在整个站点中重新利用的设计模式。在这个 CSS 中,我们设置了一个backgroundfor #form,然后在我们的 CSS 中为这个特定的登录表单覆盖这个背景颜色。我们可能希望这个特殊的登录表单脱颖而出。重命名和重组它以使其更具语义化将导致更易于理解的 CSS 文件和潜在的设计模式:


<div class="sidebar"> <form id="login"> <h2>Login</h2> <ul> <li> <label for="username">Username:</label> <input type="text" id="username" /> </li> <li> <label for="password">Password:</label> <input type="text" id="password" /> </li> <li> <input type="submit" value="Submit" /> </li> </ul> </form> </div>

我们用更语义化的结构和命名约定替换了现有的非语义结构。我们现在有一个侧边栏、一个清晰且唯一的表单名称,以及一个将表单元素组合在一起的无序列表。虽然它会产生更多的 CSS,但这实际上对我们代码的整体清洁度来说是件好事:


form { background: #ccc; } form ul { list-style-type: none; padding: 0; } h2 { font-weight: bold; font-size: 20px; } .sidebar { float: right; width: 200px; } #login { border: 1px #ccc solid; background: yellow; padding: 10px; }

如您所见,将所有无序列表保存在我们网站上的标准表单中以相同的方式设置样式很容易。同样,h2我们的登录表单中的标题(在本例中为 )应该与我们页面中的其他同级标题具有相同的样式。我们的.sidebar样式不太可能被未来对样式表的编辑覆盖,并且#login可以保留其非常独特的样式。尽管这为我们的示例添加了几行 CSS,但它也可能会导致我们的 CSS 文件的其余部分被清理,因为我们可以消除其他样式,这些样式会覆盖表单和段落的样式,使其看起来像标题。


语义命名允许您随着时间的推移维护 HTML 和 CSS,因为随着时间的推移,它更易于阅读、测试和编辑。更干净的 HTML 和 CSS 通常会创建更小的文件,从而缩短页面加载时间,并降低随着网站老化而导致页面重量膨胀的风险。因为它们更有意义,语义结构允许设计和样式的更多用途,从而创造更好的最终用户体验。


可访问性

除了语义标记的可编辑性和性能之外,干净的 HTML 还可以使具有可访问性需求的用户受益。语义 HTML 使内容层次结构对浏览器、搜索引擎和屏幕阅读器有意义。post使用和等新的 HTML5 标签aside,并通过标题、段落和列表等现有语义结构的实现,每个人都可以更容易地访问 Web 上的内容。视障人士的搜索引擎机器人和屏幕阅读器主要查看页面的 HTML 内容,而不是在应用了 CSS 样式并运行 JavaScript 动画和交互性的浏览器中显示它的方式。您的 HTML 越清晰、语义越多,这些用户的体验就越好。


Web 内容可访问性指南 (WCAG) 提供了有关如何使您的网站可供残障人士访问的更多信息。如果您使用的是干净且语义化的 HTML 层次结构,那么您就可以很好地使您的网站易于访问。万维网联盟 (W3C) 提供了完整的WCAG 2.0清单,以帮助您了解并满足所有当前的 WCAG 要求。


框架和网格

Web 上有许多有用的框架和网格,可以帮助希望创建网站但不想从头开始的设计人员和开发人员。Bootstrap、HTML5 Boilerplate 和 960 Grid 是基础 CSS、HTML 和 JavaScript 的示例,可以帮助您启动网站设计。


然而,网格和框架是有代价的。因为它们旨在涵盖大量通用用例,所以它们将包含许多您网站上不需要的东西。这种无关的内容可能会阻碍您的页面加载时间,而不是帮助您的开发时间;如果您在开始实施网格或框架时不注意包含多少内容,您的网站上可能会加载很多不必要的资产、标记或样式。


以下是 HTML5 Boilerplate 框架中包含的一些样式。对于包含 、 或 元素的网站,它们会是有用的样式dfn,hr但是mark在不使用这些元素的网站上可以消除这些行:


/** * Address styling not present in Safari 5 and Chrome. */ dfn { font-style: italic; } /** * Address differences between Firefox and other browsers. * Known issue: no IE 6/7 normalization. */ hr { -moz-box-sizing: content-box; box-sizing: content-box; height: 0; } /** * Address styling not present in IE 6/7/8/9. */ mark { background: #ff0; color: #000; }

如果您真的想使用框架,请务必在最终用户尝试加载您的站点之前清除所有无关材料。请记住,网格和框架可能无法提供我们想要的语义结构,因为它们是通用的并且一刀切。有些,如 HTML5 Boilerplate,为您提供了您应该利用的自定义构建选项,如图 4-1 所示。


在实现开箱即用的框架或网格之后,尽可能地清理页面的命名和元素结构。没有理由强迫您的最终用户加载不必要的样式、标记或 JavaScript。


网站优化

图 4-1。一些框架会在您在站点上实现它们之前为您提供自定义构建选项,例如Initializr的这个 HTMl5 样板定制工具。利用这些优化来减少标记、样式和脚本开销。


清理你的 CSS

一个深思熟虑的 HTML 层次结构和对您网站布局和设计的深思熟虑的选择将为您设置干净、易于编辑和高性能的 CSS。当您检查站点的现有 CSS 以寻找清理它的方法时,请考虑它如何反映您的 HTML 层次结构和设计选择。也许你会看到:


  • 没有语义的元素名称
  • !important声明
  • 特定于浏览器的黑客
  • 很多选择器特异性

寻找未使用的元素、可以组合或重写以提高效率的样式,以及处理浏览器不一致的过时方法。随着网站的老化,我们需要定期检查我们的 CSS 并考虑实施新技术和技术来改善页面加载时间。我们对网站层次结构和设计选择背后的目的越深思熟虑,我们的 CSS 就会越干净。代码可维护性和网站性能齐头并进。


未使用的样式

如果你有一个现有的站点,首先要解决的 CSS 清理任务是删除未使用的样式。随着网站的老化,未使用的样式会在不经意间出现,给您的样式表增加臃肿感。未使用的样式可能来自您网站上已删除的元素或整个页面、已重命名或重新设计的元素,或者您不再使用的第三方小部件的覆盖。没有理由在样式表中保留未使用的选择器或样式并强迫最终用户下载它们;如果您需要回顾历史以查看旧 CSS,您的版本控制将派上用场。


目前有许多工具可供您查找潜在的 CSS 以消除。Dust-Me Selectors是一款适用于 Firefox 和 Opera 的浏览器插件,可以扫描您网站的 HTML 以查找未使用的选择器。在 Chrome DevTools 中,有一个 Audits 选项卡(图 4-2),可让您运行网页性能审核并查看未使用的 CSS 规则列表。


网站优化

图 4-2。Chrome DevTools 允许您在任何页面上运行网页性能审计。审核结果中包含您可以清理的未使用 CSS 规则列表。


警惕这些工具的输出;Dust-Me 选择器可能没有抓取您网站的每个页面,Chrome DevTools 只查看当前页面上的 CSS 选择器(而不是调用相同样式表的任何其他页面)。这些工具非常适合帮助您获得选择器的初始列表以在样式表中检查,然后开始测试删除它们。


合并和压缩样式

您网站上独特元素的重复样式是一致样式和周到设计的重要指标。查看您的样式表,寻找组合或压缩这些样式的机会,因为它们将有助于您的代码的性能和可维护性。在这里,我们有两个具有相似样式的元素:


.recipe { background: #f5f5f5; border-top: 1px #ccc solid; padding: 10px; margin: 10px 0 0; font-size: 14px; } .comment { background: #f5f5f5; border-top: 1px #ccc solid; padding: 10px; margin: 9px 0 0; font-size: 13px; }

这两个元素样式的唯一区别是.comment具有不同的font-size声明和margin声明。我们可以将这些样式组合到一个主要声明块中,然后.comment分别样式的差异:


.recipe, .comment { background: #f5f5f5; border-top: 1px #ccc solid; padding: 10px; margin: 10px 0 0; font-size: 14px; } .comment { margin: 9px 0 0; font-size: 13px; }

.comment或者,问问你自己:为什么字体大小和下面的边距略有不同是有原因的吗?如果您将样式组合在一起.recipe并.comment创建一个真正的模式会怎样?复杂性会降低,维护的容易性会增加,更好的是,我们的 CSS 文件会更短!


.recipe, .comment { background: #f5f5f5; border-top: 1px #ccc solid; padding: 10px; margin: 10px 0 0; font-size: 13px; }

如果您发现这种模式会经常重复,您还可以概括类名,以便在整个站点中使用它,而不是继续将类名添加到这个逗号分隔的列表中。


共享许多样式的元素之间的细微差异可能是由于许多原因造成的:PSD 模型的像素完美 Web 版本,意外更新到一个存在样式但不存在另一个样式的地方,等等。在整个样式表中,您可能会看到定义了许多不同的像素特定高度、宽度、边距和填充。它们是有意地彼此略有不同,还是可以标准化?


寻找这些机会来规范化和创建模式。据推测,这些元素有意共享相同的外观和感觉;随着将来一个元素的设计发生变化,您可能希望另一个元素以相同的方式进行更改。将它们组合起来定义它们的共享样式将有助于节省您将来的开发时间,而较短的 CSS 文件将帮助您缩短页面加载时间。


此外,您可以开始定义易于遵循的间距和字体大小规则。使这些决策更容易的一种好方法是查看您的基础font-size并使用它来通知您的其余设计决策。如果您的主要内容是line-height1.4 em 的 14 px 字体,您可以做一些数学运算来创建:


  • 标题字体大小为 14 像素的倍数
  • 1.4 em 倍数的边距和填充
  • 基于 14 px 或 1.4 em 增量的自定义网格

CSS 还允许您利用速记样式声明的力量。速记声明,例如background,在一行中包含许多单独的样式值。background例如,该声明包括:


  • background-clip
  • background-color
  • background-image
  • background-origin
  • background-position
  • background-repeat
  • background-size
  • background-attachment

使用 时,您可以设置一个、部分或全部这些值background。利用这样的简写声明,您可以在 CSS 中进一步组合和压缩样式。例如,假设我们有三个样式相似的元素,它们的边框和填充略有不同:


.recipe { background: #f5f5f5; margin: 10px 0 0; border: 1px #ccc solid; padding: 10px 0; } .comment { background: #f5f5f5; margin: 10px 0 0; border: 1px #fff solid; padding: 10px 0 0; } aside { background: #f5f5f5; margin: 10px 0 0; border: 2px #ccc solid; padding: 10px 0; }

我们可以为元素之间共同的样式设置简写属性,然后使用单独的(速记)属性设置细微差异的样式:


.recipe, .comment, aside { background: #f5f5f5; margin: 10px 0 0; border: 1px #ccc solid; padding: 10px 0; } .comment { border-color: #fff; padding-bottom: 0; } aside { border-width: 2px; }

这使我们能够编写易于阅读的 CSS。如果我们再次为 重新定义简写的边界声明.comment,就很难确定边界的哪一部分与我们原来的样式声明不同。通过使用 longhand 属性,我们可以很容易地发现我们正在更改样式的哪一部分。速记属性可以减少 CSS 中的行数,这对性能有好处。


有时,重命名元素可以帮助您组合和浓缩样式。看看这些风格相似的元素:


h3 { color: #000; font-weight: bold; font-size: 1.4em; margin-bottom: 0.7em; } #subtitle { color: red; font-weight: bold; font-size: 1.4em; margin-bottom: 0.7em; } .note { color: #333; font-weight: bold; font-size: 1.4em; margin-bottom: 0.7em; }

<h1>My page title</h1> <article> <h2>My article title</h2> <div id="subtitle">My article’s subtitle</div> <p>...</p> </article> <aside> <div class="note">I have a side note</div> <p>...</p> </aside> <footer> <h3>My footer also has a title</h3> </footer>

在这种情况下,可以重命名元素以创建更语义化的层次结构以及更简洁的 CSS。用你最好的判断。在这种情况下,我们将确定事实上#subtitle,.note和h3都是我们页面中语义上的第三级标题,并在我们的 HTML 中重命名它们:


<h1>My page title</h1> <article> <h2>My article title</h2> <h3>My article’s subtitle</h3> <p>...</p> </article> <aside> <h3>I have a side note</h3> <p>...</p> </aside> <footer> <h3>My footer also has a title</h3> </footer>

通过在我们的 HTML 中重命名它们,我们已经自动组合了 CSS 中的原始样式,因为它们现在都属于h3样式块。我们可以添加特殊性来更改此块下方的article和aside标题的颜色:


h3 { color: #000; font-weight: bold; font-size: 1.4em; margin-bottom: 0.7em; } article h3 { color: red; } aside h3 { color: #333; }

最后,如果你使用像 LESS 或 SASS 这样的 CSS 预处理器,你可能仍然会得到一个臃肿的 CSS 文件,其中有很多重新利用或压缩样式的机会。良好的规划和有目的的、可重用的设计模式将帮助您使用预处理器开发 CSS,就像您编写常规 CSS 时一样。专注于保持任何mixin(定义一次的可重用样式块)尽可能高效,并确保随着时间的推移观察样式表的输出。臃肿的文件可能会偷偷摸摸,最好定期并持续检查您的 CSS 效率。


清洁样式表图像

组合和压缩样式后,请查看从样式表中调用的任何图像。请记住,图像占大多数网站页面重量的大部分,因此减少样式表图像请求的大小和数量将大大提高您网站的页面加载时间。


首先,寻找创造精灵的机会。如果您在整个站点中使用了许多图标或其他小图像,则 sprite 可以极大地帮助优化请求。阅读“ Sprites ”,了解更多关于 sprites 如何提高性能以及如何实现它们的信息。


其次,随着网站的老化,它们的精灵也会老化。您可能会注意到现有的 sprite 包含过时或不再使用的图像。检查您现有的精灵:是否有可以删除的部分?你能清理使用这些部分的 CSS 吗?您可以清理然后以更合适的文件类型或更高压缩率重新导出精灵图像吗?你的精灵越干净,你的页面加载时间就越好。


接下来,寻找机会用 CSS3 渐变、数据 URI 或 SVG 替换样式表图像。您可以在“ CSS3 ”中阅读有关创建渐变的更多信息,以及有关如何在“ SVG ”中创建高性能 SVG 替换的更多信息。CSS3 渐变是当前使用 CSS 实现的任何重复背景图像的绝佳替代品;它们在整个样式表中也很容易编辑和重新利用。用 CSS3 替换图像可能会很快加速您的网站。同样,用 SVG 替换样式表图像可以缩短页面加载时间,因为 SVG 文件可以替换样式表中的视网膜和非视网膜图像。


确保添加到样式表中的任何新图标或其他图像在您的网站设计中具有意义或目的。将这些记录在样式指南中,以便其他开发人员或设计人员可以查看已将哪些图标添加到站点以及它们当前的使用方式。通常,样式表图像蠕变会发生,因为不清楚哪些图像已经可以在整个站点中使用。我已经看到许多网站开发了多种方法来使用各种图标和突出显示来指示警告或警报,而不是坚持单一的样式约定。当您检查样式表以寻找设计模式的机会时,请考虑调用的样式表图像的数量以及它们是否可以压缩。


去除特异性

当谈到 CSS 时,特异性是关于如何编写选择器以帮助浏览器确定应用哪些 CSS 规则的术语。选择器有很多种,各有各的分量;特异性是通过基于这些选择器的公式计算的。如果两个选择器适用于同一个元素,则具有更高特异性的选择器获胜。


您经常会在 CSS 文件中看到过于具体的选择器。这通常发生在设计师或开发人员试图增加权重以覆盖先前定义的应用于特定选择器的样式时。例如:


div#header #main ul li a.toggle { ... }

为什么这个样式表作者选择连续添加所有这些选择器?为什么不能简单地设置样式:


.toggle { ... }

为了正确设置样式,作者可能真的需要所有这些特殊性。然而,如此多的特殊性也表明样式表或 HTML 层次结构中的某些内容可能会更有效率。由于 CSS 覆盖了以前过于具体的 CSS,因此往往会发生低效的选择器,这是一件值得关注的事情,因此您可以找到需要清理的区域并提高效率。这种情况经常发生在有很多人接触同一段代码的大型组织中。


过去,低效的选择器被认为本质上不利于性能,但如今对于高性能的现代浏览器来说,这已经不是什么大问题了。但是,清理选择器仍然很聪明,因为它们可以帮助您维护前端架构。


你的 CSS 越高效,它的性能就会越好。减少特殊性意味着使用 CSS 的自然级联功能更容易覆盖样式,而不是增加额外的权重或!important规则。低效的选择器和!important规则往往会使 CSS 文件变得臃肿。始终从最小、最轻的选择器开始,然后从那里添加特异性。


优化网页字体

Web 字体为您的站点增加了更多请求和页面权重。字体是衡量美学和页面速度的经典例子;重要的是要专注于使字体尽可能高效,有意识地加载它们,并衡量它们对性能和参与度指标的影响,以确保它们值得包括在内。


加载网络字体如下所示:


@font-face { font-family: 'FontName'; /* IE9 Compatability Mode */ src: url('fontname.eot'); /* IE6-IE8 */ src: url('fontname.eot?#iefix') format('embedded-opentype'), /* Modern Browsers */ url('fontname.woff') format('woff'), /* Safari, Android, iOS */ url('fontname.ttf') format('truetype'); }

Web Open Font Format或WOFF的支持正在增加,因此根据您的用户群和您的站点支持的浏览器,您可能可以使用更短的@font-face声明,这将支持 Chrome 6+、Firefox 3.6+、IE 9+ 和 Safari 5.1+:


@font-face { font-family: 'FontName'; src: url('fontname.woff') format('woff'); }

然后,您将使用 将此字体应用于选择器font-family,并包含备用字体,以防您的用户尚未加载新字体:


body { font-family: 'FontName', Fallback, sans-serif; }

为什么要包含后备字体?

您网站的一小部分访问者的浏览器不支持网络字体,或​者禁用了网络字体加载。您的字体也有可能损坏或浏览器找不到它。如果用户的浏览器在列表中找不到第一种字体font-family,它将尝试第二种字体,依此类推。您的后备字体列表应包含一种与您的主要字体相似的字体、至少一种跨平台可用的字体(如 Georgia 或 Arial),以及一种通用字体,如sans-serif或serif。


Web 字体文件有多种大小,从几千字节到 200 多字节不等。检查您的网络字体文件,看看它们有多大,并寻找以下机会来减轻它们的重量:


  • 您是否只需要几个字符而不是整个字母表和所有标点符号,例如当您将字体仅应用于徽标时?
  • 字体是否支持多种语言?是否可以将语言支持减少到仅一个子集(例如拉丁语子集)?
  • 你能消除任何不必要的个别字符吗?

字符子集化是减少 Web 字体文件大小的强大工具。如果您使用的是来自托管字体服务(例如 Google)的字体,您可以选择仅加载某个字符子集。在此示例中,我们将使用西里尔字母子集加载 Google 的 Philosopher 字体:


<link href="https://fonts.googleapis.com/css?family=Philosopher &subset=cyrillic" rel="stylesheet" />

如果您只想从 Google 托管字体加载某些字符,您也可以指定这些字符。例如,我们可以加载仅包含字符Howdy的 Philosopher 字体:


<link href="https://fonts.googleapis.com/css?family=Philosopher &text=Howdy" rel="stylesheet" />

像谷歌这样的外部托管字体更有可能已经为您的访问者缓存,但如果它们没有为特定访问者缓存,那么它们将需要额外的查找和来自外部域的请求才能获取。自托管字体可以节省额外的 DNS 查找,但不会在访问者第一次访问您的站点时被缓存。


自己托管字体的另一个好处是自定义字体文件。如果您托管自己的 Web 字体,您可以通过Font Squirrel 的 Webfont Generator 之类的工具运行它,并选择自定义字符子集来优化字体文件,如图 4-3 所示。


网站优化

图 4-3。Font Squirrel 的 Webfont Generator 允许您在字体文件中选择自定义的字符子集。在这种情况下,我们选择了 Basic Latin Unicode 表,并在我们的子集中添加了四个单个字符。


您可能还想为您的网络字体使用多种字体粗细。仔细考虑加载多少字体粗细;当你应用更多的字体文件时,页面会变得更重并且需要更多的请求,这对性能有很大的负面影响。使用尽可能少的替代权重,并确保权衡美观和字体性能之间的平衡(在第 7 章中阅读有关此选择以及如何衡量它的更多信息)。


您可以对 Web 字体加载技术进行的另一项优化是仅在大屏幕上加载字体。这将消除智能手机等小型设备上的请求和额外的页面重量,这些设备往往会对性能造成更大的影响(在“移动网络”中了解更多原因)。使用媒体查询来应用网络字体:


@media (min-width: 1000px) { body { font-family: 'FontName', Fallback, sans-serif; } }

应用网络字体时,您可以采取的最重要的措施是仔细考虑它们的用途。记录何时以及如何使用特定字体粗细,以便在您网站上工作的其他人可以重新利用此标记并了解何时适合应用字体粗细。明确特定的显示权重应该只用于某种类型的标题,或者您为特殊的设计模式保留文本权重。这将有助于教育在您的网站上工作的其他设计师和开发人员,并有望帮助您的网站尽快运行。在“样式指南”中阅读有关创建样式指南的性能优势的更多信息。


创建可重复使用的标记

使用可重复使用的标记创建设计模式是随着站点设计的发展而保持性能的关键。当您决定站点的层次结构、布局和感觉的含义时,您有机会仔细考虑加载资产并为跨站点的标记重用创造机会。设计模式节省了开发时间和页面加载时间。标记重用将:


  • 为资产缓存提供机会
  • 防止设计师或开发人员重新发明轮子
  • 在添加新内容时消除不必要的资产请求
  • 帮助您隔离不再需要的样式和资产

通过标准化整个站点使用的颜色,记录可重复使用的模式(如微调器和精灵),并定义何时以及如何实现字体等资产,您可以让您的团队在站点发展时对页面加载时间做出明智的决策。


让我们以标准化颜色为例。检查您网站的 CSS 文件并找到所有使用的颜色值。实现了多少种不同的灰度?当您在用户界面中显示警告指示符时,它们是使用一组一致的颜色,还是有多种红色或黄色阴影?您的主要站点颜色如何:您是否有一个在整个站点中重复的十六进制值,或者主题周围是否存在亮度和饱和度的变化?


您在整个设计中的颜色变化越多,这些颜色的意义就越小,您的样式表就会变得越混乱。将它们全部收集在一个地方,看看哪些可以浓缩。当您缩小颜色选择范围时,开始确定为什么可以使用这些颜色。例如,List Apart 的模式库包括对何时使用某些颜色的描述(图 4-4)。


网站优化

图 4-4。List Apart 的 Pattern 库包括对何时使用某些颜色的描述。


当我在一个有很多金黄色和深灰色的网站上工作时,我清理了样式表以使网站的颜色更加一致。我记录了当设计师想要使用粗体黄色、浅黄色、红色警告消息、绿色“已更改”消息等时使用哪个十六进制代码。我还检查并清理了所有灰色使用情况,确定应该使用哪些值以及何时使用(例如#aaa禁用的文本和边框,#eee背景等)。在记录了颜色及其含义后,我检查并用新的标准化值替换了现有颜色。这让我可以组合和浓缩许多风格,因为现在有可重复使用的模式。这些努力将主样式表文件减少了 6%,不仅节省了未来的开发和维护工作,还节省了页面加载时间。


风格指南

创建可重复使用的设计模式非常好,它们继续重用的关键是文档。样式指南对于许多受众来说都是很好的资源:编辑、开发人员、设计师以及任何其他可能在您的网站设计和开发最佳实践方面寻求指导的人。


样式指南展示了实现代码和请求资产的最佳方式,使您能够确保在您的网站上工作的其他人也正在帮助使其尽可能高的性能。将您的网站徽标资产放在一个地方并将文件优化为尽可能小并以最适合工作的格式,将有助于确保未来的徽标实施也遵循最佳实践。记录您网站的标准化和优化的加载指示器将使未来的设计师更容易实现这种模式,而不是用一个新的、缓慢的、沉重的微调器重新发明轮子。现在投入到您的风格指南中将有助于确保您的网站在未来尽可能快地保持。


考虑在您的风格指南中包含以下信息:


  • 十六进制颜色值以及何时应该使用它们
  • 按钮类以及如何使用它们
  • Sprites 以及哪些类对应于其中的哪些图标
  • 排版,包括标题的样式以及如何导入和应用任何网络字体

在记录最佳实践时,请包含有关如何实施这些样式的说明。添加示例 HTML 或 CSS 标记,如何包含正确的 JavaScript 文件,或任何其他有关高效实施的说明。例如,Yelp 的样式指南包括一个关于按钮的部分,展示了设置主要、次要和第三个按钮的正确方式,以及一个关于不应再使用的已弃用按钮样式的部分(图 4-5)。


网站优化

图 4-5。Yelp 的样式指南包括一个关于按钮的部分,展示了设置主要、次要和第三个按钮的正确方式,以及一个关于不应再使用的已弃用按钮样式的部分。


使任何标记易于复制和粘贴,以便未来的设计人员和开发人员实现出色实现的障碍很低。例如,星巴克风格指南包括如何实现公司的图标字体,包括 HTML 和 CSS 示例以及每个图标的嵌入示例(图 4-6)。在样式指南中重新利用模式和重用资产应该尽可能简单和直观。


网站优化

图 4-6。Starbucks 风格指南包括如何实现公司的图标字体,例如 HTMl 和 CSS 以及每个图标的嵌入示例。


易于理解的用例、可轻松复制和粘贴的标记以及精美示例的组合将使在您网站上工作的其他人轻松实现这些模式。在保持直观的同时,在文档中做到彻底。例如,在记录 Web 字体使用时,概述您可以包括的潜在字体粗细、如何有效地实现每种字体以及何时使用它们的规则,就像我们在 Etsy 的样式指南中所做的那样(图 4-7)。


可重复使用的模式可以节省页面加载时间以及设计和开发时间。随着您网站的设计在未来发生变化,更新特定模式的所有实例将变得更加容易,因为它们将共享相同的资产和样式。重新利用的模式越多,样式和其他资产已经被缓存的可能性就越大,样式表就越短,网站加载速度就越快。


网站优化

图 4-7。Etsy 的样式指南包括示例@font-face 权重、何时使用各种字体的说明以及用于 CSS 实现的可复制粘贴代码。


其他标记注意事项

清理完标记和样式后,您可以对资产的加载顺序、缩小和缓存进行其他优化,以缩短页面加载时间。有意加载资产并了解它们如何交付给您的用户将帮助您改善网站的整体用户体验。


CSS 和 JavaScript 加载

加载 CSS 和 JavaScript 时有两个主要规则:


  • 从.<head>
  • 在页面底部加载 JavaScript。

现在您已经阅读了“关键渲染路径”中的关键渲染路径,您知道 CSS 会阻止渲染。如果样式表包含在页面底部附近,它们将禁止页面尽快显示其内容。如果样式发生变化,浏览器希望避免重绘页面元素;将您的样式表放入允许内容逐步显示给用户,因为浏览器不再寻找更多样式信息。<head>


将样式表减少到尽可能少的文件将有助于减少站点发出的请求总数,并将导致页面加载时间更快。这也意味着您应该避免使用@import,这会显着增加页面加载时间。更小的 CSS 总是更好;我建议尽可能使用 30 KB 或更少的 CSS 和单个样式表。对于较大的站点,最好有一个站点范围的样式表,然后根据需要使用特定于页面的样式表。这样,站点范围的样式表被缓存,用户只需为每个带有附加样式的页面下载一点额外的 CSS。


JavaScript 文件应在页面末尾加载,并尽可能异步加载。这将允许其他页面内容更快地显示给用户,因为 JavaScript 会阻止 DOM 构造,除非它被显式声明为异步。


当浏览器的 HTML 解析器找到一个script标签时,它知道这个脚本中的任务可能会改变页面的渲染树,所以浏览器暂停它的 DOM 构造,让脚本完成它想要做的事情。完成后,浏览器将从 HTML 解析器停止的地方恢复 DOM 构建。将脚本调用移到页面末尾并使其异步有助于通过优化关键渲染路径和消除那些渲染阻塞问题来提高感知性能。


如果您调用 JavaScript 文件而不是在 HTML 中内联脚本,则用户的浏览器需要从您的服务器(或第三方的服务器,如果它是您从另一个站点调用的资源)请求该文件。在 HTML 解析器可以继续渲染 DOM 之前,这可能会增加数万到数千毫秒的等待时间。但是,您可以通过将 async 标记添加到您的脚本中来向浏览器指示此脚本不需要立即执行,因此不应阻止内容呈现:


<script src="main.js" async></script>

这允许浏览器继续构建 DOM,并在脚本下载并准备好后执行脚本。


当涉及到异步脚本时,需要注意一些“陷阱”。当您实现加载新内容的异步脚本时,请务必注意这会如何影响用户体验。


任何延迟加载并影响页面布局的东西都可能导致内容发生变化,让用户感到惊讶;内置占位符以确保页面在加载时看起来和感觉稳定。


请注意,不保证异步属性加载顺序,这可能会导致依赖性问题。根据内容,您还可以考虑在异步调用内容时构建加载指示器,以便您的用户了解缺少信息。另请注意,异步加载的内容可能无法很好地与书签、后退按钮和搜索引擎配合使用;在优化关键渲染路径和用户体验时请记住这一点。


广告、社交分享按钮和其他小部件等第三方内容可能会影响任何网站的性能。您应该已经在异步加载这些资源,并确保这些外部托管资源不是您站点的单点故障。第三方脚本可能会在页面重量方面增加很多开销,但它们也是一个性能问题,因为它们需要额外的 DNS 查找和连接,因为它们位于您的站点之外。您也无法控制第三方资源的缓存。


尝试消除尽可能多的第三方脚本。您的请求越少,您的页面性能就越好。尝试合并和压缩脚本;您通常可以通过复制、优化然后在您自己的站点上托管第三方脚本来做到这一点。尝试用简单的链接替换社交分享脚本。定期评估在您的页面上调用第三方资源的价值:性能是否超过了该资源为您的用户提供的任何好处?


在脚本性能方面,请注意您的瀑布图,以确保您的 JavaScript 文件在您的其他内容之后加载,并且不会阻止其他下载或呈现页面的重要部分。加载广告、社交分享和其他辅助内容的脚本绝对不应阻止页面上其他内容的加载或呈现。


缩小和 gzip

查看样式表中的所有空格、不必要的分号和前导零?JavaScript 文件中所有那些不需要的空格、换行符和制表符怎么样?现在是时候通过在最终用户看到它们之前从代码中删除不必要的字符来缩小这些资产了。缩小会导致文件更小,这对于提高网站的性能非常有用。


您可以使用命令行工具来缩小代码,或使用CSSMinifier.com和JSCompress.com等在线工具。如图 4-8 所示,我将我网站的 CSS 文件粘贴到 CSSMinifier.com 上的工具中,它会输出缩小、优化和更短的 CSS 供我在我的网站上实施。输出比原始文件小 15%。


网站优化

图 4-8。在这个例子中,我将我网站的 CSS 文件粘贴到 CSSMinifier.com 上的工具中,它会输出缩小、优化和更短的 CSS,供我在我的网站上实施。


您会注意到,当您检查网站的缩小 CSS 时,可能很难找到文件中设置特定样式的位置,因为缩小版本的所有内容都在一行中。请务必保存一份原始的、未缩小的资产的副本,因为它们将来会比缩小版本更容易阅读和编辑。在您的网站上,仅使用缩小版,以便您的用户下载尽可能小的文件。


压缩这些文本文件的另一种方法是通过 gzip 运行它们。gzip 是一种用于基于算法压缩文件的软件应用程序。gzip 的算法在文本文件中查找相似的字符串并替换这些字符串以使整体文件大小更小。浏览器了解如何解码这些替换的字符串,并将正确地向用户显示内容。


要实现 gzip 压缩,您需要在 Web 服务器上启用它。如何执行此操作取决于您的服务器类型:


  • apache:使用mod_deflate。
  • NGINX:使用ngx_http_gzip_module。
  • IIS:配置HTTP 压缩。

gzip 非常适合各种文本文件,如样式表、HTML、JavaScript 和字体。唯一的例外是 WOFF 字体文件,它带有内置压缩功能。


缓存资产

缓存对您网站的性能至关重要;缓存的资产不需要再次从您的服务器请求,保存请求。缓存通过与用户的浏览器共享信息来工作,因此它可以确定是显示以前从磁盘下载(缓存)的文件,还是从服务器再次请求资产。


此信息在 HTTP 标头中进行通信,这是在浏览器和服务器之间来回发送的任何请求的核心部分。HTTP 标头包含许多附加信息,例如浏览器的用户代理、cookie 信息、使用的编码类型、内容所在的语言等等。响应标头中可以包含两种缓存参数:


  • 那些设置浏览器可以使用其缓存资产的时间段,而无需检查您的服务器是否有新的可用资源(Expires和Cache-Control: max-age)
  • 那些告诉浏览器有关资产版本的信息,以便它可以将其缓存版本与服务器上的版本进行比较(Last-Modified和ETag)

您应该为所有可缓存资产设置其中之一Expires或Cache-Control: max-age(不是两者),以及其中之一Last-Modified或(不是两者)。比 得到更广泛的支持。始终是日期,并且是唯一标识资产版本的任何值,例如文件版本号。ETagExpiresCache-Control: max-ageLastModifiedEtag


应缓存所有静态资产(CSS 文件、JavaScript 文件、图像、PDF、字体等)。


  • 使用时Expires,将有效期设置为未来一年。不要将其设置为未来一年以上,因为这会违反 RFC 指南。
  • 设置Last-Modified为资产上次更改的日期。