现代前端技术解析:前端项目与技术实践

前端项目与技术实践

前端开发规范

HTML规范

head内容

​ head中必须定义title、keyword、description,保证基本的SEO页面关键字和内容描述。移动端页面head要添加viewport控制页面不缩放,有利于提高页面渲染性能。建议在页面加上基本的社交RICH化消息,保证网页地址分享后能够显示缩放图、图标和描述等。

<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta itemprop="name" content="页面标题">
<meta name="description" itemprop="description" content="页面内容描述">
<meta itemprop="image" content="http://xxx.com/logo.png">

img的alt属性

元素上加alt属性,用利于页面搜索引擎优化,对于盲人用户和图像加载失败的提示很实用(支持无障碍阅读)

<img src="banner.jpg" alt="宣传图片">

label的for属性

label的for属性或者将对应控件放在label标签内部,这样在点击label时,同时会关联到对应的input或textarea上选中,增加了输入的响应区域。

<label for="blue">蓝色label><input type="radio" id="blue" name="color" value="#00f">
<label><input type="radio" name="color" value="#f00">红色label>

css规范

  • 书写CSS样式不能用id选择器,因为id选择器很难复用;
  • 如果属性值为0,不需要为0加单位;
  • 先写元素的布局属性position、display、float、overflow等,再写元素的内容属性color、font、text-align等
  • 多种浏览器兼容,先写私有属性、后写标准属性

    .ui-news {
        -webkit-box-shadow: 1px 1px 5px;
        -moz-box-shadow: 1px 1px 5px;
        -ms-box-shadow: 1px 1px 5px;
        -o-box-shadow: 1px 1px 5px;
        box-shadow: 1px 1px 5px;
    }

JavaScript规范

条件判断

不要直接使用undefined进行变量判断。

// 不推荐
if(name == undefined) {return false;}
// 推荐
if(typeof person === 'undefined') {return false;}

数组拷贝

let ary = [1, {a: 2}];
let ary2 = [...ary];
let ary3 = {};
Object.assign(ary3, ary);
ary[1].a = 3;
ary2[1].a; // 3
ary3[1].a; // 3

注意:都是浅拷贝!!

数组遍历使用for…of,对象遍历使用for…in

let ary = ['a', 'b', 'c'];
let obj = { a: 1, b: 2};
for(let item of ary) {
  console.log(item);
}
for(let key in obj) {
  console.log(`${key}, ${obj[key]}`)
}

前端防御性编程规范

防御性编程是指通过检测任何可能存在的逻辑异常问题的代码实现,提高脚本执行过程健壮性的一种编程手段。

// 不推荐
t = data.userInfo.name;
// 推荐
t = data && data.userInfo && data.userInfo.name || 'ligang';

通过&&或者||进行检测,这也是函数式编程所提倡的!

前端组件规范

所谓的组件通常是指采用代码管理中的分治思想,将复杂的项目代码结构拆分成多个独立、简单、解耦合的结构或文件的形式进行分开管理,达到让项目代码和模块更加清晰的目的,而组件规范则是我们进行拆分、组织、管理项目代码方法的一种约定。不同的是,开发规范关注文件内部代码级别的一致性,组件规范则更关注项目中业务功能模块内容组织的一致性。任何一个独立的功能模块之间都应该是无耦合并能和其他模块很好对接和组合!

UI组件规范

(1)UI层风格统一化,相同功能的模块在相同场景下结构层和表现层应该一致;(2)增加UI层复用性;(3)更符合用户的体验习惯;(4)增加了开发规范的统一性。

模块化规范

JavaScript文件之间互相依赖引用的一种通用语法约定,即按照一定规范写JavaScript,方便被其他JavaScript文件引用。主要包括AMD(Asynchronous Module Definition,异步模块定义)、CMD(Common Module Definition,通用模块定义)、CommonJS、import/export等。参考:前端模块系统

项目组件化设计规范

为了实现对复杂的项目进行管理,我们通常使用组件,目前实现组件化的方案也越来越多:Web Component组件化、MVVM框架组件化(通常,将页面中的模块按照元素来划分,并将模块相关的描述语法、CSS样式、执行脚本放在同一个文件里进行引用)、基于Virtual DOM框架的组件化、直接基于目录管理的组件化等。

自动化构建

自动化构建时基于项目代码文件级的分析处理。

这里写图片描述

注意,为了保证首屏加载的资源最小化,非首屏内容希望通过JavaScript来异步渲染,这就需要构建工具能将非首屏的组件打包成异步资源,以按需或异步的方式加载。在开发中,我们通常不希望关注异步与同步组件的区别,所以通过将异步组件放在异步的目录里进行单独打包或者加入特殊的标识。

以require的引用方式为例,了解一下JavaScript组件模块文件的依赖分析过程:

  1. 从入口模块开始分析require函数调用依赖;
  2. 根据依赖生成JavaScript AST(Abstract Syntax Tree,抽象语法树,将JavaScript代码映射成一个树形结构的JSON对象树)
  3. 根据AST找到每个模块的模块名;
  4. 得到每个模块的依赖关系,生成一个依赖字典;
  5. 根据模块化引用机制包装每个模块,传入依赖字典以及import或require函数,生成执行的JavaScript代码。

前端性能优化

用户获取页面数据或执行某个页面动作的一个实时性指标,一般以用户希望获取数据的操作到用户实际获得数据的时间间隔来衡量。用户的等待延迟可分为两部分:可控等待延时(资源大小、HTTP数量等)和不可控等待延时(鼠标点击延时、CPU计算延时、ISP网络传输延时等)

performance Timing API

用于记录页面加载和解析过程中关键时间点的机制,它可以详细记录每个页面资源从开始加载到解析完成这一过程中具体操作发生的时间点。(图片引自:https://w3c.github.io/navigation-timing/

现代前端技术解析:前端项目与技术实践_第1张图片

// 加载时间耗时(整体)
performance.timing.loadEventEnd - performance.timing.navigationStart;
// 针对单个资源
let p = performance.getEntriesByName("https://www.baidu.com/");
p[0].responseEnd - p[0].requestStart; //204.175 Request请求耗时
p[0].domComplete - p[0].domInteractive; // 490.56999999999994 解析DOM树耗时
p[0].loadEventEnd - p[0].loadEventStart; // 35.955000000000155 Load事件消耗

现代前端技术解析:前端项目与技术实践_第2张图片

参考资料:https://www.w3.org/TR/2017/CR-resource-timing-1-20170330/

Profile工具

Profile用来测试页面脚本运行时系统内存和CPU资源占用情况的API,可以获得如下几个信息:

  • 分析页面脚本执行过程中最消耗资源的操作;
  • 记录页面脚本执行过程中JavaScript对象消耗的内存与堆栈的使用情况;
  • 检测页面脚本执行过程中CPU占用情况。
console.profile();
document.querySelector('#content').innerHTML = '棒棒';
calc();
function calc() {
  let result = null;
  for(let i = 0; i < 100000; i++) {
    result += i;
  }
  return result;
}
console.profileEnd();

现代前端技术解析:前端项目与技术实践_第3张图片

资源加载时序图

通过时序图可以确保文件加载顺序的情况,查看是否存在十分耗时的阻塞页面展示的资源加载。

现代前端技术解析:前端项目与技术实践_第4张图片

桌面浏览器前端优化策略

  • 避免页面中空的href和src:浏览器在渲染的过程中仍会将href属性或src属性中的空内容进行加载,直至失败,这样会阻塞页面中其他资源的下载进程;
  • 为HTML指定Cache-Control或Expires:在页面Cache-Control或Expires头部有效时,浏览器将直接从缓存中读取内容,不向服务器发送请求;
  • 减少页面重定向:一次重定向大约需要600毫秒的时间开销;
  • 将静态资源分域存放来增加并行下载数:同一时刻向同一域名请求文件的并行下载数是有限的,因此可以使用多个域名的主机来存放不同的静态资源,同时可以隔离Cookie,减少了请求头大小
  • 使用CDN Combo下载传输内容:复用HTTP连接,将多个文件请求打包成一个文件的形式来返回,以减少HTTP请求数;

    <script src="//cdn.xxx.com/path/a.js,b.js,c.js">script>
  • 缩小favicon.ico并缓存:一般Web应用的favicon.ico是很少改变的;
  • 推荐使用异步JavaScript资源:使用async时,加载和渲染后续文档元素的过程和main.js的加载和执行是并行的;使用defer时,加载后续文档元素的过程和面.js的加载是并行的,但是main.js的执行要在页面所有元素解析完成之后才开始执行;

    <script src="main.js" defer>script>
    <script src="main.js" async>script>
  • 避免使用CSS import引用加载CSS:因为这样会增加CSS资源加载的关键路径长度,代用@import的CSS样式需要在CSS文件串行解析到@import时才会加载另外的CSS文件,大大延后CSS渲染完成的时间;
  • CSS放到中,JavaScript放到文档底部:这样可以尽早完成页面渲染,同时防止JavaScript的加载和解析执行对页面渲染造成阻塞;
  • 尽量避免使用