前段优化学习

网络优化

  1. CDN的缓存与回源机制解析
  • CDN指的是将源网站的资源缓存到分别在不同地理位置的服务器上,这些服务器存储着数据的副本,因此服务器可以根据哪些服务器与用户距离最近来满足数据的获取。CDN提供快速服务,较少受高流量影响。

  • CDN往往被用来存放静态资源。静态资源本身具有访问频率高,承接流量大的特点,因此静态资源加载速度始终是前端性能的一个非常关键的指标。

  • 首先CDN服务器域名和业务服务器域名不一致。因为同一域名下的所有请求都会携带Cookies,但若我们只想请求一张图片或一个CSS文件,此时每次携带cookies开销会非常大,并且cookies中储存的信息目前并不需要,因此把静态资源和主页面置于不同的域名下,完美地避免了不必要的cookies的出现。

  1. 前端需要注意哪些SEO
  1. 合理的title,description,keywords:搜索对这三项的权重逐渐减小,title值强调重点即可,重要关键词出现不要超过两次,而且要靠前。description把页面的内容高度概括,长度合适,不可过分堆砌关键词,不同页面的description有所不同。keywords列举出重要关键词即可。
  2. 语义化的html代码,让搜索引擎容易理解网页。
  3. 重要内容html代码放在最前面,因为搜索引擎抓取html顺序是从上至下的,有的搜索引擎对抓取长度有限制,保证重要内容一定会被抓取。
  4. 重要内容不要用js输出,因为爬虫不会执行js获取内容。
  5. 少用iframe,搜索引擎不会抓取iframe中的内容
  6. 非装饰性图片必须加alt。
  7. 提高网站速度:网站速度是搜索引擎排序的一个重要指标。
  1. webpack中的优化

有哪些方式可以减少webpack的打包时间?

优化Loader

对于Loader来说,影响打包效率的首当其冲必属Babel了,因为babel会将代码转为字符串生成抽象语法树,然后抽象语法树转变最后再生成新的代码,项目越大转换代码越多,效率就越低。
首先可以减少Loader的文件搜索范围:在配置文件中用include属性设置在哪个文件夹下查找,用exclude属性设置不查找的路径。

还可以将babel编译过的文件缓存起来,下次只需要编译更改过的代码文件即可,这样可以大幅度的加快打包时间。

  • HappyPack

webpack打包过程中也是单线程的,特别是在执行loader的时候,长时间编译的任务很多,这样就会导致等待的情况。

HappyPack可以将loader的同步执行转换为并行的,这样就能充分利用系统资源来加快打包效率了。
DllPlugin

DllPlugin可以将特定的类库提前打包然后引入,这种方式可以极大的减少打包类库的次数,只有当类库更新版本才有需要重新打包,并且也实现了将公共代码抽离成单独文件的优化方案。

有哪些方式可以让webpack打出来的包更小?

  • 减小打包后的文件体积:

当我们将页面所有内容打包进一个JS文件的话,虽然将多个请求合并了,但这样也加载了很多并不需要的代码,耗费了更长时间。为了能够将首页更快地呈现给用户,我们肯定希望首页能加载的文件体积越小越好,这时候我们就可以使用按需加载,将每个路由页面单独打包成一个文件。

  • Tree Shaking

Tree Shaking可以实现删除项目中未被引用的代码,比如某个变量并没有被引入到任何文件中,没有在项目中使用的话,就不会被打包到文件中。

  • Scope Hoisting

scope hoisting会分析出模块之间的依赖关系,尽可能的把打包出来的模块合并到一个函数中。
加快打包速度

  1. 编写高性能的JavaScript

1. 为什么要将js放在body尾部?

  • JS引擎是独立于渲染引擎存在的。js代码在文档的何处插入,就在何处执行。当html解析器遇到一个script标签时,就会暂停渲染,将控制权交给js引擎,js引擎对内联的js代码会直接执行,对外部js文件还要先获取到脚本再进行执行。等js引擎运行完毕浏览器又会把控制权还给渲染引擎,继续CSSOM和DOM的构建。
    • 如果js放在header中,浏览器会阻塞并等待js加载完毕并执行。
    • 如果js在body尾部,浏览器会进行一次提前渲染,从而提前首屏出现时间。

2. 非核心代码的异步加载?

  • 动态脚本加载:使用js创建一个script标签然后插入到页面中

  • defer属性:整个html解析完之后才执行,如果是多个就按照顺序执行

  • async属性:加载完之后立即执行,如果是多个,执行和加载顺序无关。

  • 使用节流与防抖

  • 懒加载

  1. 浏览器渲染(回流和重绘)

浏览器的解析过程:

  1. 解析HTML构建DOM树,并行请求CSS/image/js

  2. CSS文件下载完毕,开始构建CSSOM树

  3. CSSOM树构建完成后,和DOM一起生成渲染树

  4. 布局(layout):计算出每个节点在屏幕中的位置

  5. 显示(painting):页面渲染到屏幕上

html 加载时发生了什么

  1. 在页面加载时,浏览器把获取到的HTML代码解析成1个DOM树,DOM树里包含了所有HTML标签,包括display:none隐藏,还有用JS动态添加的元素等。
  2. 浏览器把所有样式(用户定义的CSS和用户代理)解析成样式结构体
  3. DOM Tree 和样式结构体组合后构建render tree,render tree类似于DOM tree,但区别很大,因为render tree能识别样式,render tree中每个NODE都有自己的style,而且render tree不包含隐藏的节点(比如display:none的节点,还有head节点),因为这些节点不会用于呈现,而且不会影响呈现的,所以就不会包含到 render tree中。我自己简单的理解就是DOM Tree和我们写的CSS结合在一起之后,渲染出了render tree

DOM树和渲染树(render tree)的区别:

  • DOM树与HTML标签是一一对应的,包括head和隐藏标签

  • 渲染树不包括head和隐藏元素,每个节点都有对应的css属性

css会阻塞DOM解析吗?

  • 对于一个HTML文档来说,不管是内联还是外联的CSS,都会阻碍后序的DOM渲染,但不会阻塞后序的DOM解析。

  • 当css文件放在head标签中时,虽然css解析也会阻塞后序dom的渲染,但是在解析css的同时也在解析dom,所以等到css解析完毕就会逐步的渲染页面了。

重绘和回流(重排)的区别和关系?

  • 重绘:当渲染树中的元素外观(颜色)发生改变时,不影响布局时产生重绘。完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程成为重绘。

  • 回流:当渲染树中的元素的布局(尺寸,位置,隐藏\状态改变)发生改变时产生回流,渲染树需要重新构建。页面第一次加载时会产生回流。在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树。

  • 注意:JS获取布局属性值(例如:offsetLeft、scrollTop、getComputedStyle等)也会引起回流,因为浏览器需要通过回流计算最新值

  • 回流一定引起重绘,而重绘不一定引起回流

什么时候回触发回流:

DOM结构中的各元素都有自己的盒子,这些都需要浏览器根据各种样式来计算并根据结果将它们放置在页面的对应位置上 这个过程叫回流

  • 添加或删除可见的DOM元素

  • 元素位置改变

  • 元素的尺寸改变(包括内外边距、边框厚度、宽度、高度等属性的改变)

  • 内容改变

  • 页面渲染器初始化

  • 浏览器窗口尺寸改变

如何最小化重绘和回流?

  • 需要对DOM元素进行复杂的操作时,可以先隐藏(display:none),操作完成后再显示
  • 需要创建多个DOM节点时,使用DocumentFragment创建完成之后将节点不断的添加到DocumentFragment中,然后一次性的加入到documenet,或者使用字符串拼接方式构建好对应html后再使用innerHTML来修改页面
  • 将布局属性赋值给变量,这样不用每次需要的时候都重新计算一次布局属性,例如将var left = elem.offsetLeft,这样多次使用left只会产生一次回流
    4. 避免使用table布局,因为table元素一旦触发回流就会导致table里所有的其他元素回流
    5. 避免使用css表达式,因为每次调用都会重新计算值,包括加载页面
    6. 尽量使用css属性简写 用border代替border-width border-style border-color
    7. 批量修改样式 例如用elem.className代替elem.style.xxx

transform会产生回流吗?

  • 不会
  • transform可以操作一些动画、位移效果。
  • 但变换改变的只是元素的视觉渲染,那是在元素的布局计算后起作用的,因此在布局层面没有影响。

浏览器的优化

  • 所以我们能得知回流比重绘的代价要更高,回流的花销跟render tree有多少节点需要重新构建有关系
  • 因为这些机制的存在,所以浏览器会帮助我们优化这些操作,浏览器会维护1个队列,把所有会引起回流、重绘的操作放入这个队列,等队列中的操作到了一定的数量或者到了一定的时间间隔,浏览器就会flush队列,进行一个批处理。这样就会让多次的回流、重绘变成一次回流重绘。

自己的优化

  • 但是靠浏览器不如靠自己,我们可以改变一些写法减少回流和重绘
  • 比如改变样式的时候,不去改变他们每个的样式,而是直接改变className 就要用到cssText 但是要注意有一个问题,会把原有的cssText清掉,比如原来的style中有’display:none;’,那么执行完上面的JS后,display就被删掉了。
  • 为了解决这个问题,可以采用cssText累加的方法,但是IE不支持累加,前面添一个分号可以解决。
  • 还有添加节点的时候比如要添加一个div里面有三个子元素p,如果添加div再在里面添加三次p,这样就触发很多次回流和重绘,我们可以用cloneNode(true or false) 来避免,一次把要添加的都克隆好再appened就好了。
  1. 网络优化
  1. 雅虎军规

网络部分:

  • 尽量减少HTTP请求数:合并文件、雪碧图(精灵图)、使用小图base64
  • 减少DNS查询:开启DNS预解析。html源码在下载完成后,会解析页面的包含链接的标签,提前查询对应的域名。对于访问过的页面,浏览器会记录一份域名列表,当再次打开时,会在html下载的同时去解析DNS
  • 使用CDN内容分发网络静态资源服务器
  • 避免重定向
  • 杜绝404状态码

缓存:

  • 配置ETag,是服务器和浏览器用来决定浏览器缓存中组件与源服务器中的组件是否匹配的一种机制。
  • 添上Expires和Cache-Control HTTP头部
  • 使用外链的方式引入JS和CSS

内容部分

  • 按需加载组件
  • 预加载组件
  • 减少DOM元素的数量
  • 尽量少用iframe
  • 压缩JavaScript和CSS(代码层面)

CSS部分

  • 避免使用CSS表达式
  • 尽量选择link标签
  • 避免使用滤镜
  • 把样式表放在顶部

JS部分

  • 把脚本放在底部
  • 去除重复脚本
  • 减少DOM访问

图片部分

  • 选用合适的图片格式
  • 雪碧图中间少留空白
  • 不要用HTML缩放图片,用小图的时候去加载小图。
  • 用小的可缓存的favicon.ico

cookies

  • 清除不必要的cookies,cookies尽可能的小,设置好合适的有效期。
  • 把静态资源放在不含cookie的域下,当浏览器发送对静态图像的请求时,cookie也会一起发送,而服务器根本不需要这些cookie。

移动端

  • 保证所有组件都小于25k
  • 把组件打包到一个复合文档里
  • 服务器端
  • 开启Gzip压缩
  • 对Ajax用get请求
  • 尽早清空缓存区
  • 使用CDN(内容分发网络)

你可能感兴趣的:(前段优化学习)