第4节 关键CSS

4.1 原理

  • 关键CSS将样式分为两类:首屏样式和页面其余部分的样式

  • 只将首屏样式存储到<style>标签中,并将其内联到HTML,剩下的样式将从外部文件加载。

  • 使用标签加载CSS,而是使用preload提示

    1
    <link rel="preload" href="..." as="style" onload="this.rel=stylesheet'" >

    这样可以在不阻塞渲染的情况下加载CSS。CSS完成下载时,标签上的onload事件处理程序将被触发。下载完成后,rel属性的值就会从preload转换为stylesheet。这将标签从资源提示更改为普通CSS引入,后者将CSS应用于首屏以外的内容。JavaScript polyfill作为兜底,以防浏览器不支持preload提示。就是这么简单!

4.2 实现

  • 480、667、768、800、900、1024和1280像素的位置绘制参考线。这些是流行设备的常见垂直分辨率,并且大多数设备的分辨率包含在两者之间的任何位置。制作好这些参考线后,你需要调整浏览器窗口的大小,以查看内容在每个临界点上的位置。
  • 网站mydevice.io列出了各种设备的分辨率

第5节 响应式图像

5.1 通过媒体查询适配高DPI显示器

  • -webkit-min-device-pixel-ratio媒体查询会检查像素密度的简单比率,其中比率1相当于96DPI。这种情况下,在下载更高分辨率的图像之前,你要确保显示器的像素密度至少为192DPI。而min-resolution媒体查询则采用更直接的值192dpi。

    1
    @media screen (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) and (min-width: 30em){ /* High DPI 480px/16px */	#masthead{	}}

    heigh-dpi.png

    5.2 使用SVG

  • JPEG和全彩PNG文件更适合照片,而SVG最适合用于logo、线条艺术和图案等内容

  • 使用的两种方法

    • 标签使用

      1
      <img   src="img/logo.svg" />

      标签中使用SVG文件时,几乎没有理由在元素或srcset中使用它,除非在元素中将其用作一系列图像回退的一部分。

    • 内嵌使用

      1
      <svg xmlns="...." id="logo">    ....</svg>

      这种方式有优势也有劣势。优点是,内嵌SVG可以通过删除HTTP请求来帮助减少页面加载时间,前提是你的站点没有托管在HTTP/2服务器上。缺点是,这也使得资源在页面间的可缓存性降低。

5.3 在HTML中传输图像

5.3.1 max-width规则
  • 对所有img元素设置的全局max-width规则

    1
    img{    max-width:100%}

    这条简洁的规则有很多好处,其一是使任何元素都渲染为其自然宽度(除非超过容器)。超过容器宽度时,这条规则会将图像宽度限制为容器的宽度

5.3.2 srcset
  • 显示响应式图像的方法之一,是在标签中使用名为srcset的HTML5特性。标签的这个可选属性不是替换src属性,而是对其进行补充。

  • 使用srcset具体说明图像

    1
    <img src="image-small.jpg" srcset="image-medium.jpg 640w,image-large.jpg 1280w"/>

    srcset属性的格式是图像URL和图像宽度,由空格分隔。图像名称采用标签的src属性中常用的格式,宽度使用后缀w表示

  • srcset的优点是,它不需要媒体查询就可以工作。浏览器获取给定的信息,并根据视口的当前状态选择最适合的图像。

5.3.3 使用size控制粒度
  • 它接受一组媒体查询和宽度,媒体查询起作用时,它后面的宽度设置图像应显示的宽度。这些媒体查询和图像大小可以通过逗号分隔成多对使用

    1
    <img src="image-small.jpg"      srcset="image-medium.jpg 640w,image-large.jpg 1280w"     sizes="(min-width:704px) 50vw, 100vw" />

    size属性的内容有两个作用。在704像素和更宽的屏幕上,指示图像占据视口宽度的50%。要告诉浏览器这一点,可以使用视口宽度(vw)单位,即视口当前宽度的百分比。之后的下一个逗号分隔规则(不带媒体查询)是图像的默认宽度。

5.3.4 使用picture元素
  • 为不同的屏幕提供不同的裁剪和焦点的实践

  • 可以在中添加一些标签,从而定义更多图像供浏览器使用

    1
    <picture>    <source media="(min-width:704px)" srcset="img/amp-medium.jpg 384w" sizes="33.3vw"/>    <source srcset="img/amp-cropped-small.jpg 320w" sizes="75vw">    //浏览器不支持picture的回退操作    <img src="img/amp-small.jpg">  </picture>
  • 可以轻松使用元素应对高DPI显示器。这需要对标签上的srcset属性进行更多调整

    1
    <picture>    <source media="(min-width:704px)"             srcset="img/amp-medium.jpg 384w,                    img/amp-large.jpg 512w,                    "             sizes="33.3vw"/>    <source srcset="img/amp-cropped-small.jpg 1x,                    img/amp-cropped-medium.jpg 2x,                    "             sizes="75vw">    //浏览器不支持picture的回退操作    <img src="img/amp-small.jpg">  </picture>

    为了告知浏览器哪种图像应用于哪种类型的显示器,在srcset属性中使用x值代替宽度值。可以把它想象成一个简单的乘数,1x标记适合标准DPI屏幕的图像,2x或更高的倍数表示适合于更高DPI屏幕的图像。如果愿意,甚至可以使用3x或更高的倍数,因为5K显示器已经逐渐普及了。

5.3.5 使用Picturefill提供polyfill支持
  • 尽管srcset和都很有用,但它们的浏览器支持并不是通用的。值得庆幸的是,可以通过一个名为Picturefill的11KB小脚本,在不支持这些标签浏览器中使用它们。

  • https://scottjehl.github.io/picturefill/下载Picturefill并将其放入项目

  • 第一个<script>块用于无法识别元素的浏览器,并防止在Picturefill完成加载之前,浏览器在HTML中解析它们时出现问题。第二个块加载Picturefill库,但使用async属性,因而不会阻塞页面渲染

    1
    <script>document.createElement("picture")</script><script src="js/picturefill.min.js" async></script>
5.3.6 使用Modernizr选择性加载Picturefill
  • 使用Modernizr来避免在现代浏览器中加载11KB的Picturefill库,方法是首先检查浏览器是否需要它。

    1
    <script src="js/modernizr.custom.min.js"></script><script>	if(Modernizr.srcset === false || Modernizr.picture === false){        var picturefill = document.createElement("script")        picturefill.src = "js/picturefill"        document.body.appendChild(picturefill)    }</script>

第6节 图像处理

6.1 雪碧图

  • 图像雪碧图会组合图像以减少HTTP请求,这是一种连接。尽管你应该在HTTP/1上使用图像雪碧图来提高页面加载速度,但是应当避免在HTTP/2上使用它们。

  • 雪碧图就是把以往在整个网站中使用的单独的图像文件集合起来,组成一个图像文件。这些图像通常是图标等全局元素。

  • 使用

    • 安装包

      1
      npm install -g svg-sprite
    • 使用svg-sprite命令

      sprite.png

    • 使用生成的雪碧图,将生成的图片替换之前使用的即可

  • 创建包含特定于内容的图像雪碧图,会迫使用户下载可能不使用它的页面的内容。每个场景都是独特的,所以可以列出一个图像清单,然后创造最适合你的网站的雪碧图。

  • Grumpicon网站是一个基于Web的工具,它接受SVG文件,并生成带有回退选项的PNG版本的雪碧图

6.2缩小图像

6.2.1 优化JPEG图像
  • 使用imagemin

    1
    npm install imagemin imagemin-jpeg-recompress
  • 创建一个存放生成文件的文件夹

    1
    mkdir optimg
  • 编写优化Node程序

    1
    //reduce.jsvar imagemin = require('imagemin'),    jpegRecompress = require('imagemin-jpeg-recompress')imagemin(["img/*.jpg"],"optimg",{    plugins:[        jpegRecompress({            accurate:true,  //设置精确度优先于速度            max:70  //输出图像最大JPEG质量        })    ]})  //输出到optimg文件夹

    执行

    1
    node reduce.js

    最后将标签引用更改为指向optimg文件夹中的文件。imagemin-jpeg-recompress并不是唯一的JPEG优化库。

6.2.2 优化PNG图像
  • 使用以下命令下载imagemin-optipng插件:

    1
    npm install imagemin-optipng
  • 编写Node程序,其余同上

    1
    //reduce.jsvar imagemin = require('imagemin'),    jpegRecompress = require('imagemin-optipng')imagemin(["img/*.jpg"],"optimg",{    plugins:[        optipng()    ]})  //输出到optimg文件夹
6.2.3 优化SVG
  • 安装包

    1
    npm install -g svgo
  • 使用命令转换svg

    1
    svg  -o b.svg a.svg

    这个命令的格式很简单。它以-o参数开始,该参数是svgo写入优化后的输出的文件名称。之后是未优化的SVG文件的名称。

  • svgo程序功能强大,有很多选项。也许我们应该深入看看你是否可以进一步优化这个图像。键入svgo -h可以查看其他选项。值得留意的是-p参数,可以使用它来控制浮点数的精度。尝试将此值设置为1。不过,不要太仓促地宣布成功。应该观察输出,看看是否引入了任何异常。

6.3 使用WebP编码图像

  • 栅图像仅有的可用选项就是JPG、GIF和PNG格式。几乎再没有新的格式出现,直到几年前Google引入了WebP。WebP同时支持有损和无损格式编码。
  • Google的WebP格式是一个很好的例子。WebP很强大,它根据图像内容提供比等效格式更小的文件
6.3.1 使用imagemin编码有损WebP图像
  • 需要安装imagemin和imagemin-webp插件:

    1
    npm install imagemin imagemin-webp
  • 使用imagemin将JPEG图像编码为有损WebP图像,其余同上文

    1
    //reduce.jsvar imagemin = require('imagemin'),    jpegRecompress = require('imagemin-webp')imagemin(["img/*.jpg"],"optimg",{    plugins:[        webp({            quality:40  //将Webp编码器的质量设置为40,最大为100        })    ]})  //输出到optimg文件夹
6.3.2 使用imagemin编码无损WebP图像
  • 其余同上文

    1
    //reduce.jsvar imagemin = require('imagemin'),    jpegRecompress = require('imagemin-webp')imagemin(["img/*.jpg"],"optimg",{    plugins:[        webp({            lossless:true        })    ]})  //输出到optimg文件夹
6.3.3 支持度不高
  • 尽管WebP是一种很好的图像格式,你也可以从现在开始使用它,但它的支持并不像成熟的图像格式那么广泛。如果你的用户依赖于Firefox或Safari等浏览器

  • 你需要指定其他浏览器可以处理的回退。要在元素中创建一系列回退,可以在元素上使用type属性。type接受图像的文件类型作为srcset属性中指定的图像的参数。继续使用中的type属性来优先使用WebP图像,并在不支持WebP的浏览器中回退到JPEG图像。

    1
    <picture>	<source srcset="img/amp-small.webp" type="image/webp"/>    <img src="img/amp-small.jpg"/></picture>

6.4 懒加载图像

  • 为懒加载程序配置标记是任务中最省时的部分,但它至关重要。你需要一个阻止浏览器默认加载图像的模式。将srcset和src属性移动到data属性,这样图像就不会加载;为需要懒加载脚本处理的<img>元素添加一个类。

    lazypic.png

    <source><img>元素上的所有srcset和src属性更改为data-srcset和data-src属性。将图像URL存储在这些占位符属性中可以跟踪图像来源,同时防止它们加载,直到你希望加载为止。然后,在<img>标签上创建一个新的src属性,指向具有灰色背景的16像素×9像素占位符PNG。这通过引入占用同等空间的占位符,使布局的变化保持最小。最后一步是将lazy类添加到<img>标签。这就是在需要加载图像时懒加载程序脚本的目标元素。

  • 懒加载脚本lazyload.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
      (function (window, document) {
    "use strict";
    var lazyLoader = {
    lazyClass: "lazy",
    //html中,懒加载图像使用的类名
    images: null,
    //图像元素集合
    processing: false,
    //处理状态,用于限制执行
    throttle: 200,
    //节流时间
    buffer: 50,
    //视口缓冲大小,用于加载视口边缘附近图像
    init: function () {
    //开始懒加载
    lazyLoader.images = [].slice.call(document.getElementsByClassName(lazyLoader.lazyClass));
    //通过lazyClass属性定义的类名,获取所有元素
    lazyLoader.scanImages();
    //初始化时运行scanImages
    document.addEventListener("scroll", lazyLoader.scanImages);
    //滚动时运行scanImages
    document.addEventListener("touchmove", lazyLoader.scanImages);
    ////触摸屏幕时运行scanImages
    },
    destroy: function () {
    //页面删除懒加载行为
    document.removeEventListener("scroll", lazyLoader.scanImages);
    //移除行为
    document.removeEventListener("touchmove", lazyLoader.scanImages);
    //移除行为
    },
    scanImages: function () {
    if (document.getElementsByClassName(lazyLoader.lazyClass).length === 0) {
    //检查是否还有文件需要懒加载
    lazyLoader.destroy();
    //所有图像都已加载则析构加载程序
    return;
    }
    if (lazyLoader.processing === false) {
    //检查文档是否正在被检查图像
    lazyLoader.processing = true;
    //阻塞后续代码执行
    setTimeout(function () {
    //将代码块处理延迟指定时间
    for (var i in lazyLoader.images) {
    //循环集合中所有图像
    if (lazyLoader.images[i].className.indexOf("lazy") !== -1) {
    //检查图像是否在视口中
    if (lazyLoader.inViewport(lazyLoader.images[i])) {
    //检查元素是否包含lazy类
    lazyLoader.loadImage(lazyLoader.images[i]);
    //将当前元素传递给loadImage方法
    }
    }
    }
    lazyLoader.processing = false;
    //关闭标志位
    }, lazyLoader.throttle);
    //通过throttle属性指定超时时间
    }
    },
    inViewport: function (img) {
    //核心懒加载方法
    //寻找视口的位置和高度以及缓冲阈值
    var top = ((document.body.scrollTop || document.documentElement.scrollTop) + window.innerHeight) + lazyLoader.buffer;
    return img.offsetTop <= top;
    //检查给定的图像是否在视口中
    }, loadImage: function (img) {
    if (img.parentNode.tagName === "PICTURE") {
    //检查图像父节点是否为picture
    var sourceEl = img.parentNode.getElementsByTagName("source");
    //获取附近source元素
    for (var i = 0; i < sourceEl.length; i++) {
    //遍历source元素
    var sourceSrcset = sourceEl[i].getAttribute("data-srcset");
    //获取data-srcset属性用于加载图像
    if (sourceSrcset !== null) {
    //检查source元素是否存在srcset属性
    sourceEl[i].setAttribute("srcset", sourceSrcset);
    //设置srcset s
    ourceEl[i].removeAttribute("data-srcset");
    //删除data-srcset
    }
    }
    }
    //从img元素中获取data-src和data-srcset
    var imgSrc = img.getAttribute("data-src"),
    imgSrcset = img.getAttribute("data-srcset");
    //检查img元素上是否存在data-src
    if (imgSrc !== null) {
    //将img的src设置为data-src属性的值
    img.setAttribute("src", imgSrc);
    img.removeAttribute("data-src");
    }
    //同上
    if (imgSrcset !== null) {
    img.setAttribute("srcset", imgSrcset);
    img.removeAttribute("data-srcset");
    }
    //移除img元素的懒加载类名
    lazyLoader.removeClass(img, lazyLoader.lazyClass);
    },
    //移除类名中包含lazy的类名
    removeClass: function (img, className) {
    var classArr = img.className.split(" ");
    for (var i = 0; i < classArr.length; i++) {
    if (classArr[i] === className) {
    classArr.splice(i, 1);
    }
    }
    img.className = classArr.toString().replace(",", " ");
    }
    };
    //开始运行脚本
    document.onreadystatechange = lazyLoader.init;
    })(window, document);

    将脚本放入html中使用

  • 有些用户关闭了JavaScript或者无法使用JavaScript。方法是添加<noscript>标签,在src和srcset属性中显式设置图像源。

    1
    <noscript>	<picture>        <source ...>    </picture></noscript>

第7节 影响脚本加载行为

  • 通过修改<script>标签的async属性实现的。async(asynchronous的缩写)告诉浏览器加载脚本后立即执行该脚本且不会在下载时阻塞渲染,而不是按顺序加载每个脚本并等待它们依次执行。

    async.png

  • 使用async

    1
    <script src="js/jquery.js" async></script>
  • 使用注意,如果没有任何脚本具有依赖项,则可以自由使用async。但是当脚本具有依赖性时,事情就会变得棘手。解决此问题的一种方法是将依赖脚本组合起来,以便将这些依赖打包为单个资源。在本例中,可以按顺序组合jquery.min.js和behaviors.js。在命令行中运行此命令,将两个脚本合并为scripts.js:

第8节 使用 Service Worker 提升性能

  • 有时我们会离线,例如,在没有Wi-Fi的飞机上,或汽车、火车通过隧道的时候。这就是现实生活。这种情况发生时,我们已经习惯于无法浏览网站。但不一定非要这样,这就是ServiceWorker出现的原因。

第9节 微调资源传输的方法

9.1 服务器压缩资源

  • 为客户网站压缩资源时,通过npm下载的compression模块。这个模块使用gzip算法——最常用的压缩算法。可以通过传递选项来修改此模块应用的压缩级别。可以通过level选项指定0~9的数字修改压缩级别,其中0代表不压缩,9代表最大值

    1
    app.use(compression({    level:7}))

    将压缩级别设置为9并非总是最佳策略。level设置得越高,CPU压缩响应所需的时间就越多。压缩内容所花费的额外CPU时间可能会使问题复杂化,并使总体性能变差。我能给出的最好建议是:在有效载荷大小和压缩时间之间取得平衡。大多数情况下,默认压缩级别6是最适合的,但是你自己的测试才是最权威的信息源。

  • 针对压缩哪些类型的文件给出了两个建议:总是压缩文本文件类型(因为它们的压缩效果很好),以及避免压缩内部已经压缩的文件。你应该避免压缩大多数图像类型(SVG除外,SVG属于XML文件)和字体文件类型,如WOFF和WOFF2。在Node Web服务器上使用的compression模块不会尝试压缩所有内容。如果要压缩所有资源,必须通过filter选项传递函数来告诉它

    1
    app.use(compression({    filter:function(request,response){        return true;    }}))

    在我的测试中,我比较了所有压缩级别下JPEG、PNG和SVG图像的压缩比

    compression.png

    如你所见,PNG和JPEG根本不能压缩。SVG压缩得很好,因为它们是由可压缩的文本数据组成的。

  • gzip一直是首选的压缩方法,而且这种情况似乎不会很快改变。但一个有前途的新竞争者已经登场——Brotli。

    • 尽管Brotli在某些方面的性能与gzip相当,但它显示出了良好的前景,并在不断地发展。考虑到这一点,Brotli值得你考虑。但是查看Brotli性能之前,先看看如何在浏览器中检查Brotli支持情况。如果有Chrome 50或更高版本,请打开开发者工具,转到任一启用HTTPS的网站上的Network选项卡,查看任一资源的Accept-Encoding请求头的值。

      1
      accept-encoding:gzip,deflate,sdch,br

      如果浏览器支持Brotli,它会在Accept-Encoding请求头中将br令牌包含在接受的编码列表中。当支持它的服务器看到这个令牌时,就会用Brotli压缩的内容进行回复,否则它应该回退到下一个支持的编码方案。

9.2 缓存资源

9.2.1缓存Cache-Control
  • Cache-Control头部。这个头部几乎在每一个浏览器中都指示缓存行为。通过其max-age指令,该指令指定缓存资源的生命周期(以秒为单位)

    1
    Cache-Control:max-age = 3600

    当用户再次访问时,请求的资源对于max-age指令中指定的时间量(3600秒,或者更直观地说,一小时)之内的缓存是有效的。

9.2.2 服务器检查资源是否更改
  • 流行的方法是使用实体标记,简称ETag。ETag是根据文件内容生成的校验和。浏览器将这个值发送到服务器,服务器将通过验证该值来查看资源是否已更改。另一个方法是检查文件在服务器上最后修改的时间,并根据上次修改时间提供资源的副本。可以使用Cache-Control头部修改此行为。
  • max-age指令对于大多数网站来说都是适合的,但有时候你需要限制缓存行为或者完全取消它。使用no-cache、no-store、stale-while-revalidate控制资源重新验证
9.2.3 CDN
  • 可以在网站前使用CDN。CDN是一种代理服务,它位于你的网站前面,并优化内容向用户的传输。CDN将你的资源托管在它们的服务器网络上,因此CDN可以有效缓存你的内容。可以将两个Cache-Control指令(public和private)与max-age结合使用,它们能够帮助你控制CDN缓存内容的方式。

    1
    Cache-Control: public,max-age=86400

9.3 制定最佳缓存策略

  • 对资源进行分类时,最好的标准是资源更改的频率。例如,HTML文档可能经常更改,而CSS、JavaScript和图像等资源更改的可能性要小一些。

  • 展示了这些资源类型的细分,以及我为它们选择的缓存策略。

    cache.png

  • ❏ HTML文件或者输出HTML的服务器端语言(例如PHP或ASP.NET)可以受益于保守的缓存策略。你永远不会希望浏览器假定页面应该只从浏览器缓存中读取,而不去重新验证其新鲜度。

    • no-cache可以确保总是重新验证资源,如果资源已更改,则下载新的副本。如果文件的内容没有更改,则重新验证资源确实会减少服务器上的负载,但是no-cache不会激进地缓存HTML,以避免内容过时。
    • max-age为一小时,可确保在max-age到期后,无论发生什么情况,都获取资源的新副本。
    • 使用private指令告诉位于Web源服务器前面的任何CDN:该资源根本不应缓存在其服务器上,而应仅在用户和Web源服务器之间缓存。
  • CSS和JavaScript是重要的资源,但不需要如此积极地缓存。因此,你可以使用30天的max-age。因为你会从为你分发内容的CDN中受益,所以应该使用public指令允许CDN缓存资源。

  • 图像和其他媒体文件(如字体)几乎不会改变,而且这些往往是你要提供的最大的资源。因此,把max-age设置为较长的时间(比如一年)比较合适。

    • 与CSS和JavaScript文件一样,你会希望CDN能够缓存这些资源。因此此处自然也要使用public指令。
    • 因为这些资源不会经常变化,所以你希望有一个宽限期,在这个宽限期内可以接受某种程度的过时资源,因此,一天的stale-while-revalidate周期适合用来给浏览器异步验证资源的新鲜度。

9.4 实现缓存策略

  • 自定义http.js

    use-cache.png

  • 测试:不要重新加载页面,因为这将导致浏览器与服务器联系以重新验证资源。正确做法是导航到页面。要在已经打开的页面上执行此操作,请点击地址栏并按回车键。

    network-cache.png

9.5 使缓存资源失效

  • 使CSS和JavaScript资源失效。假设使用php时,强制CSS更新,其他语言也有替代方案

    update-style.png

  • 使图像和其他媒体文件失效。明智的选择可能是指向一个新的图像文件。

9.6 使用CDN

  • 可以将这个<script>标签的src属性更改为指向由MaxCDN免费提供的CDN托管版本的库:

    1
    <script src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
  • 以下是为你提供各种资源的简短的CDN列表。

    • cdnjs是一个托管了几乎所有流行的(或不那么流行的)库的CDN。它提供了干净的界面,使你能够搜索任何可以想到的常用CSS或JavaScript资源,例如广泛使用的MVC/MVVM框架、jQuery插件,或项目所依赖的任何其他东西。
    • jsDelivr是另一个类似于cdnjs的CDN。如果cdnjs没有提供你想要的内容,请尝试在这里搜索
    • Google CDN涵盖的库比cdnjs或jsDeliv少得多,但它确实提供了流行的库(如Angular和其他库)。在我的测试中,这是最快的CDN。
  • 建议

    • 另一个建议是:如果你使用的库(如Modernizr或Bootstrap)可以配置为提供该库功能的特定部分,请配置你自己的构建,而不要指向CDN上的整个库。有时候,配置一个较小的构建并将其托管在自己的服务器上,比从CDN引用完整的构建要快。理清你的需求,并比较哪种方法更好。
    • 如果你使用的库(如Modernizr或Bootstrap)可以配置为提供该库功能的特定部分,请配置你自己的构建,而不要指向CDN上的整个库。有时候,配置一个较小的构建并将其托管在自己的服务器上,比从CDN引用完整的构建要快。理清你的需求,并比较哪种方法更好。
  • CDN失效指定回退版本

    cdn-rollback.png

9.7 使用资源提示

  • 资源提示可用于加快网页加载速度、微调特定页面资源的传输,以及预渲染用户尚未访问的页面。

  • 在功能强大的浏览器中,prefetch告诉浏览器下载特定资源,并将其存储到浏览器缓存中。这个资源提示可以像请求那样,用于预取位于同一页面上的资源;或者你也可以对用户下一步可能访问的页进行猜测,并请求那个页面的资源。使用第二种方法时要特别小心,因为它可能会迫使用户下载不必要的资源。

  • preload资源提示与prefetch非常相似,只是它保证将下载指定的资源。script、style、font和image的值可以分别用于JavaScript、CSS、字体和图像。使用as属性描述请求的内容类型。此属性是完全可选的,但省略它是不利的,因为如果没有as,浏览器将下载该资源两次。

  • 使用

    1
    <link rel="preload" href="https://code.jquery.com/jquery-2.2.3.min.js" as="script">
  • 必须在preload和prefetch之间进行选择,请选择prefetch。如果浏览器支持没有那么重要,并且希望无论怎样请求都能够抢先加载内容,请选择preload。

第10节 HTTP/2必要性

  • HTTP/2 :解决HTTP1协议的三大问题
    • 队首阻塞、未压缩头部和缺少HTTPS的授权。