xinglie / xinglie.github.io

blog
https://xinglie.github.io
153 stars 22 forks source link

编译与运行时性能优化 #85

Open xinglie opened 3 years ago

xinglie commented 3 years ago

性能优化是一个很大的话题,这里只谈个人经历、实施过的优化方式。

在上一篇极致的性能里所聊的更多是解决问题方案的优化,这里我们讨论一些其它在项目中常见的写法以及改进方案

减少对象创建

假如我们有这样的代码

import Magix from 'magix';

export default Magix.View.extend({
    init() {
        window.addEventListener('scroll', e => {

        }, {
            passive: true
        });
    }
});

我们应该把AddEventListenerOptions对象提升到外部,防止每个view对象在创建时,反复创建AddEventListenerOptions对象,如下

import Magix from 'magix';
let scrollOptions = {
    passive: true
};
export default Magix.View.extend({
    init() {
        window.addEventListener('scroll', e => {

        }, scrollOptions);
    }
});

同样的,有些开发者喜欢在函数内容再创建一个函数来用于处理复杂的数据,如

import Magix from 'magix';
export default Magix.View.extend({
    render() {
        let processString = str => {
            return ('00' + str).slice(-3);
        };
        let list = this.get<string[]>('list');
        for (let i = list.length; i--;) {
            list[i] = processString(list[i]);
        }
    }
});

同样的,我们需要把函数提取到外部,防止render方法被调用时,processString反复被创建

import Magix from 'magix';
let processString = str => {
    return ('00' + str).slice(-3);
};
export default Magix.View.extend({
    render() {
        let list = this.get<string[]>('list');
        for (let i = list.length; i--;) {
            list[i] = processString(list[i]);
        }
    }
});

当然,有时候在创建内部函数时,所遇的情境可能会更加复杂些,但无论何时应该在脑海里保持:减少这种对象的反复创建,只有在无法避免时才创建。

缓存结果

这其实是一个老生常谈的话题了,这里主要提一下编译器做的事情

<div custom-attr="{{=attrOfCustom()}}??"></div>

我们调用方法获取自定义属性的值,而只在有值时才会输出custom-attr,开发者写的这样的代码经过magix-composer编译后的结果如下

let $temp_var;
$vnode_0.push($createVNode('div', { 'custom-attr': ($temp_var = (attrOfCustom())) != null && $temp_var, }));

可以看到我们的编译器会使用一个变量来保存方法调用的值,并在后续使用,防止方法被反复调用。 对象亦如此

<div custom-attr="{{=long.object.read.expr}}??"></div>

编译后为

let $temp_var;
$vnode_0.push($createVNode('div', { 'custom-attr': ($temp_var = (long.object.read.expr)) != null && $temp_var, }));

模板编译与优化这篇中,更详细的聊了编译器如何把模板编译为更优质的js代码,以及如何进行的相关优化。