JavaScript开发中的性能优化

Posted on

最近工作比较清闲,5月又换了一个工作环境。总结下最近看的有关JavaScript性能的知识,并记下来供未来的自己参考。希望自己能不忘初心,继续成长!

使用requestAnimationFrame来更新动画

使用requestAnimationFrame把动画渲染交给浏览器,可以保证渲染保持在60FPS。应该避免使用setTimeout或者setInterval来实现动画,因为计时器和事件队列会消耗更多的资源,还会导致无用的页面重新绘制。

使用Web Workers来进行复杂的运算

可以把单纯的计算放在Web Workers中,这样不影响主页面的渲染和流畅,例如加密和矩阵变换的运算就可以完全放在Web Workers中来减少主线程的执行时间,避免浏览器渲染堵塞。

避免微优化JavaScript

举个最简单的例子,我曾经在一本书上看到过一个提升程序效率的例子。大致是这样的:

var array = [1, 2, 3, ... 100];

for( var i = 0; i < array.length; i++) {
  console.log(array[i]);
}

这里的array.length获取数组的长度,每次都要计算数组长度会消耗不少时间,优化之后的代码是这样的:

var array = [1, 2, 3, ... 100];
var len = array.length
for( var i =0; i < len; i++) {
  console.log(array[i]);
}

通过缓存数组的长度来保证只计算一次。这就是典型的微优化,说实话这段代码我一直在用,直到最近读了其他的书才发现,现在的JS解释器早就优化了对数组长度的计算。无论是读取一次还是一万次消耗的时间都没有太大差别。微优化应该是JS引擎需要做的事情,我们不应该在实际开发中在这方面耗费过多的时间。

滑动事件优化

当用户监听滑动事件并执行相关动画操作的时候,记得使用window.requestAnimationFrame来优化动画的执行。

function onScroll (evt) {
  // Prevent multiple rAF callbacks.
  if (scheduledAnimationFrame)
    return;

  scheduledAnimationFrame = true;
  requestAnimationFrame(readAndUpdatePage);
}

function readAndUpdatePage () {
  // do something
  requestAnimationFrame(readAndUpdatePage)
}

window.addEventListener('scroll', onScroll);

参考:

Debounce Your Input Handlers

Optimize JavaScript Execution

使用letsencrypt为自己的网站加密

Posted on

好吧,这次博客的更新稍微有点迟到了。因为自己各种忙着考驾照什么的,不过新的一年又要有新的开始了。最近买了VPS也就开始折腾起来了,讲讲如何用letsencrypt来给自己的网站颁发不要钱的证书,而且最近还支持通配符的二级域名了,想怎么开子网站都行!!!

dehydrated

浏览器的证书签名的步骤实在是很麻烦,所以有位热心的学生做了一个自动化脚本,可以自动生成脚本并且可以和其他脚本一起使用。达到一键签名证书。

letsencrypt-cloudflare-hook

我把自己的DNS服务托管到cloudflare上,还可以使用cloudflare提供免费的CDN服务。最重要的一点是cloudflare有API接口。利用这个接口就可以自动完成DNS-01 challenge。简单的来说,就是通过添加一条DNS记录来证明自己对这个域名的所有权,才能给这个域名颁发证书。

安装过程

知道了这两个工具之后,我们就可以开始配置证书了。具体的流程都写在项目的文档里面了。我这里主要是讲述下遇到的坑,首先我自己的服务器环境是CentOS7,使用的是默认的python2的环境。需要安装cryptography的库才能顺利完成编译。

sudo yum install gcc libffi-devel python-devel openssl-devel

其次,配置环境最好保存在dehydrated/config里,这样就没必要每次都设置环境变量。

echo "export [email protected]" >> config
echo "export CF_KEY=K9uX2HyUjeWg5AhAb" >> config
echo "export CF_DEBUG=true" >> config

CF_KEY就是cloudflare里面的Global API Key,替换一下就好了。因为我们要配置的域名包含所有的二级域名,所以需要新建一个dehydrated/domains.txt文件,并写入:

icehoney.me *.icehoney.me

这样就会对主域名和所有二级域名生效。

之后再执行命令,./dehydrated -c -t dns-01 -k 'hooks/cloudflare/hook.py'。如果没有问题就可以看到成功生成的日志。

参考:

dehydrated

letsencrypt-cloudflare-hook

Failed to install Python Cryptography package with PIP and setup.py Ask Question

浏览器的渲染性能

Posted on

不知不觉,2018年的春节也要来临了。今年只是元旦回家了,春节并不打算回家。回家曾经是一件美好的事情,不知从何时开始,却是那么的揪心。最近也有读很多关于性能优化和底层的前端知识。不想就此停滞,只能不断前进。

浏览器渲染

我们都知道,现在主流显示器的频率是60Hz,也就是1秒要刷新60次。这样才能保持画面的流畅,特别是玩游戏的时候,我们非常在意帧数。前端开发也是一样,所以我们每一项操作都最好在10毫秒之内完成,否则会产生所谓的卡吨现象,影响用户体验。

渲染过程

render pipeline

浏览器的渲染主要是分为5个步骤,我们需要了解这些知识才能编写性能更好的代码。

  1. JavaScript 我们经常使用JS来实现一些复杂的视觉效果,数据排序,DOM操作等等。
  2. 样式计算 此过程是根据样式匹配选择器来计算哪些元素应用哪些CSS规则的过程。不过浏览器会对常用的选择器进行性能优化,例如类选择器。
  3. 布局 在知道每个元素的应用规则之后,浏览器开始计算所需要的空间大小以及其处在屏幕的位置。网页的布局中,一个元素的变化会影响到其他元素的位置。例如Body的宽度变窄之后其子元素的宽度也都会发生变化。
  4. 绘制 绘制是填充像素的过程。它涉及绘出文本、颜色、图像、边框和阴影,基本上包括元素的每个可视部分。绘制一般是在多个表面(通常称为层)上完成的。
  5. 合成 由于页面的各部分可能被绘制到多层,由此它们需要按正确顺序绘制到屏幕上,以便正确渲染页面。对于与另一元素重叠的元素来说,这点特别重要,因为一个错误可能使一个元素错误地出现在另一个元素的上层。

JS / CSS > 样式 > 布局 > 绘制 > 合成

render pipeline

如果修改了元素的布局属性,也就是改变了元素的几何属性(例如宽度,高度)。那么浏览器就必须检查所有元素,然后重新排版页面。任何受影响的部分都要重新绘制,再重新合成。

JS / CSS > 样式 > 绘制 > 合成

render pipeline no layout

如果之修改了元素的绘制属性,例如背景图片或者文字颜色,并不会对其他元素的布局造成影响。浏览器会跳过布局,但仍然执行绘制。

JS / CSS > 样式 > 合成

render pipeline no layout

目前既不要绘制也不要布局的属性只有transform属性和opacity属性。所以在实现CSS动画的时候,优先使用这两个属性。

如何查询CSS属性触发上面3个流程的哪一个,可以去CSS Triggers 查询。

参考:

Rendering Performance