笔记四:浅析前端工程化、动画、性能优化

236 阅读4分钟

一、工程化的目标

我的理解:用软件工程思维来解决贯穿项目中种种低效的问题,使项目开发流程规范化,为前端开发赋能。(刀耕火种->自动化)

实践立足当下。核心:规范化(babel)、模块化(ESM、CommonJS)、组件化、自动化(webpack)。

二、模块化

我们一般逻辑相关的代码放在同一个文件中,当做一个模块。只需关注模块内逻辑的实现,无需考虑变量污染等问题,模块之间可互相调用。

1、CSS的模块化

(1)为DOM节点定制属性(参考Vue的scoped)

(2)CSS IN JS(新的CSS规范似乎有借鉴类似的思想?)

(3)借助预编译手段使样式成为脚本中的变量。

(4)BEM(按照相关规则严格遵守,借助stylus、less…)

2、JS的模块化

(1)CommonJS规范

(2)ESM规范

(3)AMD\CMD规范

三、组件化

个人理解:模块、组件、函数的解耦,在于功能粒度的分割。

1、组件设计规则

(1)UI为主

页面上的一个UI块可以封装成个组件。 比如页面的头部header,封装成个Header组件后,我希望它的脚本、样式和模版可以放在个文件夹中, 到时候便于维护。侧重UI进行封装的组件:代码结构清晰,组件内的模块就近放置,方便进行修改和维护。这种组件具备高内聚,低耦合的特性,但普适性不高。

(2)逻辑为主

某一个功能逻辑也可以封装成个组件。 比如AutoComplete组件,封装成一个组件后,我希望它的脚本、样式和模版可以放在-一个文件夹中,可以一处封装,多处任意使用。侧重逻辑进行封装的组件:除了具备上述优点外,还具有很高的普适性,更方便组件重用。

组件内可以包含组件,比如偏UI的组件往往都是 包含有偏逻辑的组件。

四、自动化(核心)

1、初始化(各种脚手架工具)

2、自动构建(webpack、gulp)

3、自动测试(jest)

4、自动部署

五、webpack实践推荐


六、前端动画制作方式

1、JS手段(可以制作的动画种类多,更可控;缺点开发成本较高)

(1)定时器制作

(2)requestAnimationFrame

方法一:依靠增量。

//普适性差
        let rotationValue = 0;
        requestAnimationFrame(function update() {
            //实时改变CSS属性值
            block.style.transform = rotate(`${rotationValue++}deg`);
            requestAnimationFrame(update);
        });

方法二:依靠时间

let startTime = null;
        //一个周期
        const T = 2000;
        requestAnimationFrame(function update() {
            //初始化情况
            if (!startTime) startTime = Date.now();
            //计算p度
            const p = (Date.now() - startTime) / T;
            block.style.transform = rotate(`${360 * p}deg`);
            requestAnimationFrame(update);
        });

方法一改进:基于增量的OOP封装

// 基本封装戳类
        class Ticker {
            //传入上下文和更新函数
            tick(update, context) {
                let count = 0;
                requestAnimationFrame(function next() {
                    if (update(context, ++count) !== false) {
                        requestAnimationFrame(next);
                    }
                });
            }
        }
        //逐帧更新函数
        function update({ target }, count) {
            target.style.transform = `rotate( ${count++}deg)`;
        }
        //使用
        const ticker = new Ticker();
        ticker.tick(update, { target: block });

方法二改进:基于时间的OOP封装

//时间戳类封装
        class Ticker {
            tick(update, context) {
                let count = 0;
                let startTime = Date.now();
                requestAnimationFrame(function next() {
                    count++;
                    const time = Date.now() - startTime;
                    if (update(context, { count, time }) !== false) {
                        requestAnimationFrame(next);
                    }
                });
            }
        }
        //利用时间进行更新
        function update({ target }, { time }) {
            target.style.transform = `rotate(${360 * time / 2000}deg)`;
        }
        const ticker = new Ticker();
        ticker.tick(update, { target: block });

待实践:timing类封装、匀速运动、自由落体运动、摩擦运动、平抛旋转、贝塞尔曲线

方法三:草案方法(Web AnimationAPI):和CSS动画有些相似,主要是通过定义关键帧来实现,但兼容性不好。

七、性能优化的RAIL模型


响应、流畅、闲置、加载。

八、用户对延迟的心智反应


九、考虑预算时间


十、浏览器的渲染场景


开发者要关注回流和重绘操作。

十一、补充考虑渲染树的构建

通过DOM 树和CSSOM 树,浏览器就可以通过二者构建渲染树了。浏览器会先从 DOM 树的根节点开始遍历每个可见节点,然后对每个可见节点找到适配的CSS样式规则并应用。具体的规则有以下几点需要注意:

1、Render Tree和DOM Tree并不完全对应(meta、script、link等不参与渲染)。

2、请注意 visibility: hidden 与 display: none 是不一样的。前者隐藏元素,但元素仍占据着布局空间(即将其渲染成一个空框),而后者(display: none) 将元素从渲染树中完全移除,元素既不可见,也不是布局的组成部分。

最终二者会合成为render树。

十二、针对渲染树构建部分的性能优化

1、在引入顺序上,CSS 资源先于 JavaScript 资源。样式文件应当在 head 标签中,而脚本文件在 body 结束前,这样可以防止阻塞的方式。

2、尽量减少在 JavaScript 中进行DOM操作。

3、简化并优化CSS选择器,尽量将嵌套层减少到最小。

十三、待亲自实践思考的部分

Performance

十四、性能优化的方向

1、加载过程:资源效率优化、图片、字体、渲染路径优化。

2、渲染过程:JS执行优化、避免大型的复杂布局(昂贵)、渲染层合并

十五、总体优化方向的思考

总体来说可以围绕

1、资源本身大小的压缩优化(想办法减少资源的体积)

2、网络请求的全过程(从url地址栏输入发送请求开始到返回响应包的每个环节)

3、浏览器渲染的全过程(拿到资源后浏览器渲染的每个环节)