zoukankan      html  css  js  c++  java
  • 前端性能优化总结

    页面重构 - 在不改变外部行为的前提下,简化结构,添加可读性,而在前端保持一致的行为(即不改变UI的情况下,对网站进行优化)

    1、布局

    2、浏览器兼容

    3、对移动平台的优化

    4、SEO优化(Search Engine Optimization,搜索引擎优化 -- 利用搜索引擎的规则提高网站在有关搜索引擎内的自然排名 --> 黑帽(black hat) | 白帽(white hat))

    方面:


    1、严格编码规范

    2、高内聚,低耦合

    3、代码弹性,增强代码的可扩展性

    4、增强用户体验

    5、压缩JS,CSS,Image等资源(通常有服务器来解决)

    6、采用CDN来加载资源

    7、图片预加载,懒加载 

    8、CSS样式:样式文件放在顶部,当需要设置的样式很多时设置className,而不是直接操作style,避免使用css expression即动态属性

    9、JS:脚本文件放在底部加上时间戳,少用全局变量

    10、DOM的优化:减少dom操作,减少table使用(table要等其中的内容全部完全下载之后才会显示出来,比div+css慢)

    11、减少http请求次数:CSS Sprites, JS、CSS源码压缩、图片大小控制合适;data缓存 ,网页Gzip,CDN托管,图片服务器

    12、HTTP服务器缓存

    13、尽量向前端优化,减少数据库操作,减少磁盘IO -- 在不影响功能和体验的情况下,能在浏览器执行的不要在服务端执行,能在缓存服务器上直接返回的不要到应用服务器,程序能直接取得的结果不要到外部取得,本机内能取得的数据不要到远程取,内存能取到的不要到磁盘取,缓存中有的不要去数据库查询。减少数据库操作指减少更新次数、缓存结果减少查询次数、将数据库执行的操作尽可能的让你的程序完成(例如join查询),减少磁盘IO指尽量不使用文件系统作为缓存、减少读写文件次数等。程序优化永远要优化慢的部分,换语言是无法“优化”的。

    资源加载顺序

    1、Layout和Paint

      当渲染对象被创建并添加到树中,它们并没有位置和大小,计算这些值的过程称为 layout 或 reflow。所以在元素的大小和位置发生变化时都会触发 layout

      浏览器针对Layout做了一定优化,如采用Dirty bit系统,只针对具有dirty标记的元素进行重新layout,即增量layout,且此过程是异步的;如果元素只是位置发生变化,其大小从缓存里读取,就不用再次计算。

      绘制阶段,遍历渲染树并调用渲染对象的paint方法将它们的内容显示在屏幕上,绘制使用UI基础组件。当元素的位置和大小没有变化,如改变背景颜色等等,只会进行重新paint。Paint也采用dirty机制进行增量Paint

    2、CSS阻塞

      CSS会阻塞渲染树的构建,不阻塞DOM构建,但是在CSSOM构建完成之前,页面不会开始渲染(一片空白),

      与js不一样,js虽然会阻塞后续DOM构建,但是前面已经就绪的内容会进行渲染。

      CSS虽然不阻塞DOM构建,但是会阻塞后面js的执行,从而间接阻塞完整DOM的构建,  

     针对性优化

    • 尽早加载css文件并生成CSSOM.
    • 不使用@import
    • 利用媒体查询,处理特定设备下的CSS,以减少不必要的阻塞. 

    3、JS阻塞

      JS默认也是会阻塞DOM和渲染树的构建。HTML解析器在遇到脚本文件时,默认为停下来去获取脚本(不考虑资源预加载优化),然后执行,期间阻塞DOM构建

    4、defer脚本

      声明为defer的脚本会延迟到DOM构建完成后(DOMInteractive事件),DOMContentLoadedwindow.onload事件之前执行(但依然会被浏览器的预加载策略提前下载)。只针对外联脚本有效。多个defer会按照先后顺序串行执行。  

    <script type="text/javascript" src="/js/script1.js" defer></script>
    <script defer>
        console.log('inserted');
    </script>

    5、async脚本

      声明 为异步的脚本会异步地下载和执行,会在window.onload事件之前执行,但是可能会在DOMContenLoaded事件前后执行。

    6、资源优先级

      样式和脚本的优先级是比图片更高的,因为这两个都具有阻塞性,浏览器让它们尽快下载下来。

      第一个图片资源会和css一起下载,但浏览器发现后面还有许多图片就会优先去下载脚本文件。

    浏览器优化策略

    1、DNS预解析 DNS-Prefetch

      通过 DNS 预解析来告诉浏览器未来我们可能从某个特定的 URL 获取资源,当浏览器真正使用到该域中的某个资源时就可以尽快地完成 DNS 解析。

    例如,我们将来可能从example.com获取图片或音频资源,那么可以在文档顶部的<head>标签中加入以下内容:
    
    <link rel="dns-prefetch" href="//example.com">

    2、预连接 Preconnect

      现代浏览器都试着预测网站将来需要哪些连接,然后预先建立 socket 连接,从而消除昂贵的 DNS 查找、TCP 握手和 TLS 往返开销。

      然而,浏览器还不够聪明,并不能准确预测每个网站的所有预链接目标。好在,在 Firefox 39 和 Chrome 46 中我们可以使用preconnect告诉浏览器我们需要进行哪些预连接

    <link rel="preconnect" href="http://example.com">

    3、预获取 Prefetching

      如果我们确定某个资源将来一定会被使用到,我们可以让浏览器预先请求该资源并放入浏览器缓存中。例如,一个图片和脚本或任何可以被浏览器缓存的资源:

    <link rel="prefetch" href="image.png">

    4、Subresources

      这是另一个预获取方式,这种方式指定的预获取资源具有最高的优先级,在所有prefetch项之前进行:

    <link rel="subresource" href="styles.css">

    5、预渲染 Prerender

      这类似于在一个隐藏的 tab 页中打开了某个链接 – 将下载所有资源、创建 DOM 结构、完成页面布局、应用 CSS 样式和执行 JavaScript 脚本等。

      当用户真正访问该链接时,隐藏的页面就切换为可见,使页面看起来就是瞬间加载完成一样。Google 搜索在其即时搜索页面中已经应用该技术多年了,微软也宣称将在 IE11 中支持该特性。

    <link rel="prerender" href="http://example.com">

    资源压缩

    1、代码压缩

      代码文本里边有许多对于运行没有作用的部分,如多余的空白,注释,我们在生产环境中可以将它们去掉来减少网络传输字节。  

      1)gulp-uglify压缩JS

    const gulp = require('gulp');
    const uglify = require('gulp-uglify');
    const babel = require('gulp-babel');
    const gutil = require('gulp-util');
    
    gulp.task('script', function() {
        gulp.src('src/*.js')
            .pipe(babel({
                presets: ['env']
            }))
            .pipe(uglify())
            .on('error', err=> {
                 gutil.log(gutil.colors.red('[Error]'), err.toString()); 
            })
            .pipe(gulp.dest('dist'))
    });

      2)sourcemap

    gulp.task('script', function() {
        gulp.src('src/*.js')
            .pipe(sourcemaps.init())
            .pipe(babel({
                presets: ['env']
            }))
            .pipe(uglify())
            .on('error', err=> {
                 gutil.log(gutil.colors.red('[Error]'), err.toString()); 
            })
            .pipe(sourcemaps.write('./maps'))
            .pipe(gulp.dest('dist'))
    });

    2、压缩css

      1)gulp-minify-css

    gulp.task('style',()=>{
        gulp.src('css/*.css')
            .pipe(minifyCSS())
            .pipe(gulp.dest('dist/css'))
    });

    3、Gzip

      gzip是很常用的Web资源压缩方案,以Node为例

    const gzip = require('zlib').createGzip();
    const fs = require('fs');
    const path = require('path');
    
    const inp = fs.createReadStream(path.join(__dirname,'./file/test.txt')); //830字节
    const outp = fs.createWriteStream(path.join(__dirname,'./file/test.txt.gzip')); //345字节
    
    inp.pipe(gzip).pipe(outp); 

    4、HTTP压缩

      首部字段

      为了选择要采用的压缩算法,浏览器和服务器之间会使用主动协商机制。

      客户端请求头:Accept-Encoding: xxx,xxx指明支持的压缩算法清单和优先级。

      服务端�响应头:Content-Encoding: xxx指明使用的压缩算法。 

    ****https://github.com/laoqiren/web-performance,如上所述均出自该地 

  • 相关阅读:
    每日一练ACM 2019.0417
    每日一练ACM 2019.0416
    每日一练ACM 2019.04.13
    每日一练ACM 2019.04.14
    创建线程的方法
    类和对象的概念
    接口的概念
    Mysql添加取消自增属性
    SpringMVC不支持PUT表单提交
    SSM框架整合报org.springframework.beans.factory.NoSuchBeanDefinitionException
  • 原文地址:https://www.cnblogs.com/slightFly/p/11881333.html
Copyright © 2011-2022 走看看