美文网首页
常见页面优化方法

常见页面优化方法

作者: 薯条你哪里跑 | 来源:发表于2022-10-07 14:52 被阅读0次

    dns

    在请求任何资源前,浏览器需要知道你的目标服务器ip是什么,此时会将目标资源的域名通过dns解析出相应的ip,再进行链接获取;
    日常应该很难体验到dns解析带来的阻塞,但是在弱网情况下dns解析就会有明显的延迟了,我们可以通过在link标签上添加dns-prefetch来进行预解析,预解析是在页面加载的同时进行的所以不会带来体验负担,解析之后的ip会存储到操作系统的缓存中相比于从路由器中获取缓存要快得多。

    1. 可以在html头部写link标签来实现
    <link rel="dns-prefetch" href="https://baidu.com" crossorigin>
    
    1. 也可以通过在消息头中设置link实现
    Link: <https://baidu.com/>; rel=dns-prefetch
    

    https协议时搭配dns-precontent食用更加,dns-precontent会提前建立TCP链接并且进行TLS握手,进一步减少延迟;

    <link rel="preconnect" href="https://baidu.com" crossorigin>
    <link rel="dns-prefetch" href="https://baidu.com">
    

    注意不要滥用,过度使用会加大DNS解析开销造成网络负担;

    另外要注意资源域名的收敛(当dns解析开销大的弱网情况下进行收敛)与发散(浏览器有并发请求数限制,发散后可以提高并发请求能力);

    CSS

    在浏览器绘制页面的流程中会将html形成的dom树和css形成的CSSOM树合并之后进行下一步的渲染,所以生成CSSOM树的速度也是会影响页面渲染的原因之一;

    1. 可以将多媒体查询css进行拆分,形成单独的文件,并且利用media属性帮助浏览器识别;
    // 大于480宽时会下载此mobile.css 但是不会阻塞渲染;
    <link rel="stylesheet" href="mobile.css" media="screen and (max-width: 480px)"> 
    
    1. 通过gpu来计算动画。
      浏览器针对动画进行了优化,会将一些属性和标签进行优化使其动画转换属性在gpu中完成提升性能;包括 3D transforms (transform: translateZ(), rotate3d()等),animating transform 和 opacity, position: fixedwill-change,和filter。一些元素,例如 <video>, <canvas><iframe>。tip: 在做动画时不考虑兼容性情况下最好使用will-change代替translate3d()或translateZ(),translate3d()或translateZ()可能会使transform动画延迟几百毫秒。但是不能滥用will-change,除非是真的不行了;
    //如果你试图将will-change和动画同时使用,它将不会给你带来优化。
    //因此,建议在父元素上使用will-change,在子元素上使用动画
    .animate-element-parent {
        will-change: opacity;
    }
    
    .animate-element {
        transition: opacity .2s linear
    }
    
    1. font-display 属性定义了浏览器如何加载和显示字体文件,允许文本在字体加载或加载失败时显示回退字体。可以通过依靠折中无样式文本闪现使文本可见替代白屏来提高性能(不过经过测试发现默认行为都是block了,目前应该没有这种情况)。
    @font-face {
      font-family: someFont;
      src: url(/path/to/fonts/someFont.woff) format('woff');
      font-weight: 400;
      font-style: normal;
      font-display: fallback;
    }
    
    

    font-display有以下几个属性:auto、block、swap、fallback、optional,可自行理解差异;font-display可以解决由于字体没加载出来而导致的布局混乱的问题。

    1. content-visibility属性
    • visible: 默认值, 可见的
    • hidden: 隐藏, 此时内容不可选中, 不可聚焦. 类似于display: none
    • auto: 自动. 对于用户可见区域的元素,浏览器正常渲染内容,对于不可见的区域元素, 浏览器会跳过内容的绘制

    实例常见的ssr列表页看下渲染时间,每页40条数据的样子;

    <ul>
        <li class="item-container"><img src=""/>。。。。</li>
    </ul>
    
    每一条数据 多测几次基本都在22-25之间
    之后在item-container加上content-visibility;
    .item-container{
      content-visibility: auto;
    }
    
    多测几次基本都在18-20之间

    渲染时间大大减少;特别适合长列表,但是就是兼容性不咋好,所以建议搭配其他策略一起;


    image.png
    1. css写的时候层级最好不要太深
    2. css内外分离,将不重要或非首屏进行异步加载
    3. 体验相关在点击跳转锚点时,设置该属性就会丝滑滚动到锚点而不是生硬直接跳转到
    html {
        scroll-behavior:smooth;
    }
    
    高糊录屏= =

    JS

    js的加载会阻塞html的渲染这个想必大家都知道,这就是我们都会把js放到body底部的原因;另外将较大的js文件进行拆分,拆成主流程js及其他辅助功能js,适度减小js包体可优化页面加载时间;

    1. script标签上添加type=module,此时的脚本会被视为js模块,并且默认会被延迟加载(默认defer异步加载)。
    2. 可在script标签上添加deferasync。没有这两个标签的话浏览器会立即加载并执行脚本会阻塞html的渲染。scrpit带有deferasync 属性中的任意一个,都会使得scrpit下载和html解析并行进行,不会阻塞html解析;唯一的区别是:defer是在html解析完成后在DOMContentLoaded触发前执行且是顺序执行;但async是下载完成后立即执行是乱序执行;
    蓝色是加载,红色表示执行,绿色表示html解析
    1. 获取设置dom样式时做到读写分离,这样做是为了减少重绘和重排次数;
      当我们频繁设置dom样式时浏览器会有优化策略,合并之后在进行重排/重绘。
    const el = document.getElementById('test');
    el.style.padding = '5px';
    el.style.borderLeft = '1px';
    el.style.borderRight = '2px';   // 只会进行一次重绘
    

    但是当我们要获取dom的布局信息(offsetLeft等)时为了保持数据准确会立刻进行重排/重绘;

    const el = document.getElementById('test');
    el.style.padding = '5px'; // 重排重绘
    console.log(el.offsetLeft)   // 重排
    el.style.borderLeft = '1px'; // 重排重绘
    console.log(el.offsetTop)  // 重排
    el.style.borderRight = '2px';  // 重排重绘
    console.log(el.offsetWidth)  // 重排
    
    const el = document.getElementById('test');
    el.style.padding = '5px';
    el.style.borderLeft = '1px';
    el.style.borderRight = '2px';    // 以上一次重排重绘
    console.log(el.offsetWidth) 
    console.log(el.offsetLeft) 
    console.log(el.offsetTop) 
    
    
    1. 插入dom时可先使用createElementFragment创建文档碎片,将要新建的dom构建好后一次性插入dom中。

    img iframe

    1. 可以使用属性loading=lazy进行懒加载,但是有一定兼容性问题;(有些坑可以度娘展开看看)
    'loading' in HTMLImageElement.prototype // 可判断浏览器支持与否
    
    <img src="image.jpg" alt="..." loading="lazy">
    <iframe src="video-player.html" title="..." loading="lazy"></iframe>
    
    lazy示例,可以看到滚动才会加载

    可以通过原生apiIntersectionObserver来实现

    let options = {
       //指定根 (root) 元素,用于检查目标的可见性。必须是目标元素的父级元素。如果未指定或者为null,则默认为浏览器视窗
      root: document.querySelector('#scrollArea'),
      // 根 (root) 元素的外边距。
      // 类似于margin属性。如果有指定 root 参数,则 rootMargin 也可以使用百分比来取值。该属性值是用作 root 元素和 target 发生交集时候的计算交集的区域范围,使用该属性可以控制 root 元素每一边的收缩或者扩张。默认值为 0
      rootMargin: '0px',
    // 可以是单一的 number 也可以是 number 数组,target 元素和 root 元素相交程度达到该值的时候 IntersectionObserver 注册的回调函数将会被执行。如果你只是想要探测当 target 元素的在 root 元素中的可见性超过 50% 的时候,你可以指定该属性值为 0.5。如果你想要 target 元素在 root 元素的可见程度每多 25% 就执行一次回调,那么你可以指定一个数组 [0, 0.25, 0.5, 0.75, 1]。默认值是 0 (意味着只要有一个 target 像素出现在 root 元素中,回调函数将会被执行)。该值为 1.0 含义是当 target 完全出现在 root 元素中时候 回调才会被执行。
      threshold: 1.0
    }
    
    let observer = new IntersectionObserver(callback, options);
    

    阈值为 1.0 意味着目标元素完全出现在 root 选项指定的元素中可见时,回调函数将会被执行。

    1. 图片加载不出导致碎图
      常见场景在写image时会显示默认图,之后快到可视区域后才进行加载真正的图片;
    //  通过IntersectionObserver监听是否快到可视区域之后将真实图替换到src属性
    <img  class="img"   src="默认图.png" lazy_src="真实图">
    
    new InVisible({
        isVisible: 'data-loaded',
        targetKey: 'lazy_src',
        callBack: (cur) => {
            let defaultSrc = cur.getAttribute('src');
            let src = cur.getAttribute('lazy_src');
            cur.src = src;
          // 替换之后监听onerror以免碎图
            const fnType = cur.addEventListener ? 'addEventListener' : 'attachEvent';
            cur[fnType]("error", () => {cur.src = defaultSrc;});
        }
    })
    

    只有默认图不是很语义化,img有个特殊的特性,她的伪元素在error的时候才会生效,正常情况下不会生效,利用这一特性我们可以通过css解决碎图和语义化的问题;

    图片正常时伪元素并不生效
    .img::after{
        position: absolute;
        content: " ";
        background: url("默认图.png") no-repeat;
        left: 0;
        top: 0;
        height: 100%;
        width: 100%;
        background-size: cover;
       
    }
    .img::before{
        position: absolute;
        z-index:1;
        bottom: 0;
        left: 0;
        background: rgba(0,0,0,0.5);
      // 可以使用attr动态设置  eg: attr(tittle)
        content: "前海人寿金融中心楼盘图片"; 
        width: 100%;
        text-align: center;
        color: #fff;
    }
    
    修改图片url至错误地址,伪元素生效 支持率也还不错

    以上

    相关文章

      网友评论

          本文标题:常见页面优化方法

          本文链接:https://www.haomeiwen.com/subject/hwhsnrtx.html