一、工程化的目标
我的理解:用软件工程思维来解决贯穿项目中种种低效的问题,使项目开发流程规范化,为前端开发赋能。(刀耕火种->自动化)
实践立足当下。核心:规范化(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、浏览器渲染的全过程(拿到资源后浏览器渲染的每个环节)