0、前注
- 面对读者类型:入门、初级、中级前端开发者
- 本文部分参考和引用了别人的技术博客等,所有引用来源文章均已直接在文章内部标注或在标题3引用部分注明。若原作者认为有侵权嫌疑,请短消息我,我会尽快修改;
- 本文目的仅以介绍技术为主,不负责深入解释。如感兴趣,可以查看引用的文章以及通过谷歌、百度查找相关内容;
- 部分内容通过ctrl+c、ctrl+v引用,未直接标注出处,请谅解;
- 文章以what、why、how作为结构,方便阅读者理解;
- 常见基础内容,例如h5、css3、es5、es6,github,vuejs、react、ng等,略去不提
- 由于前端技术极其繁杂,因此这里介绍的内容必然有所缺少,甚至错误,请指出,我会尽快修改。
- 作者:零零水,QQ:20004604
1、基础型
1.1、构建工具webpack
webpack是什么?
Webpack 是一个前端资源加载/打包工具,只需要相对简单的配置就可以提供前端工程化需要的各种功能,并且如果有需要它还可以被整合到其他比如 Grunt / Gulp 的工作流。
webpack的作用?
自动化,模块化,易用化。
例如
1、同时支持CommonJS和AMD模块
2、串联式模块加载器以及插件机制,让其具有更好的灵活性和扩展性,例如提供对CoffeeScript、ES6的支持;
3、基于配置或者智能分析打包成多个文件,实现公共模块或者按需加载;
4、支持对CSS,图片等资源进行打包,从而无需借助Grunt或Gulp;
5、开发时在内存中完成打包,性能更快,完全可以支持开发过程的实时打包需求;
6、对sourcemap有很好的支持,易于调试。
使用webpack的团队:
以BAT为首的一系列大厂团队、小公司项目组和个人开发者。
1.2、转码工具babel
babel官网
babel是什么?
Babel是一个转换编译器,它能将ES6转换成可以在浏览器中运行的代码。Babel由来自澳大利亚的开发者Sebastian McKenzie创建。他的目标是使Babel可以处理ES6的所有新语法,并为它内置了React JSX扩展及Flow类型注解支持。
babel有什么用?
Babel可以将ES6代码转为ES5代码,从而在现有环境执行。
这意味着,你可以现在就用ES6编写程序,而不用担心现有环境是否支持。下面是一个例子。
据codemix创始人Charles Pick介绍,Babel是所有ES6转换编译器中与ES6规范兼容度最高的,甚至超过了谷歌创建已久的Traceur编译器。Babel允许开发者使用ES6的所有新特性,而且不会影响与老版本浏览器的兼容性。此外,它还支持许多不同的构建&测试系统,使开发者很容易将它集成到自己的工具链中。
// 转码前
input.map(item => item + 1);
// 转码后
input.map(function (item) {
return item + 1;
});
上面的原始代码用了箭头函数,这个特性还没有得到广泛支持,Babel将其转为普通函数,就能在现有的JavaScript环境执行了。
babel优点
可以使用各种es6的新特性,而es6有很多语法糖,让开发更加轻松愉快。
babel如何转换代码的
https://github/lcxfs1991/blog/issues/9
1.3、异步组件
是什么?
以vuejs为例:
组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素, Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展。
在大型应用中,我们可能需要将应用拆分为多个小模块,按需从服务器下载。为了让事情更简单, Vue.js 允许将组件定义为一个工厂函数,动态地解析组件的定义。Vue.js 只在组件需要渲染时触发工厂函数,并且把结果缓存起来,用于后面的再次渲染。
为什么要使用异步组件?
1、模块化,方便开发和复用;
2、按需加载,首屏时间短;
3、减少服务器压力;
4、方便管理;
5、其他,太多了
如上图,假如是同步的,那么你需要加载的页面的大小为50+30+50+40+100=300KB,无论你访问哪个页面;
假如是异步的,当你访问组件1时,只需要加载80KB,然后你又访问了组件2,那么再额外加载50KB,当你继续访问到组件3时,才需要加载全部的组件内容。
怎么使用?
通常需要使用打包工具,比如webpack;
然后根据使用的框架,使用框架支持的异步组件的书写方式;
最后交给webpack去打包就行了。
1.4、CSS预处理器
是什么?
一句话总结:对CSS语法进行扩展增强,让CSS变成一门编程语言,方便面对大型网站的开发和使用。
全文:
CSS 预处理器定义了一种新的语言,其基本思想是,用一种专门的编程语言,为 CSS 增加了一些编程的特性,将 CSS 作为目标生成文件,然后开发者就只要使用这种语言进行编码工作。
通俗的说,“CSS 预处理器用一种专门的编程语言,进行 Web 页面样式设计,然后再编译成正常的 CSS 文件,以供项目使用。CSS 预处理器为 CSS 增加一些编程的特性,无需考虑浏览器的兼容性问题”,例如你可以在 CSS 中使用变量、简单的逻辑程序、函数(如右侧代码编辑器中就使用了变量$color)等等在编程语言中的一些基本特性,可以让你的 CSS 更加简洁、适应性更强、可读性更佳,更易于代码的维护等诸多好处。
为什么?
1、文件切分
页面越来越复杂,需要加载的 CSS 文件也越来越大,我们有必要把大文件切分开来,否则难以维护。传统的 CSS 文件切分方案基本上就是 CSS 原生的 @import 指令,或在 HTML 中加载多个 CSS 文件,这些方案通常不能满足性能要求。
CSS 预处理器扩展了 @import 指令的能力,通过编译环节将切分后的文件重新合并为一个大文件。这一方面解决了大文件不便维护的问题,另一方面也解决了一堆小文件在加载时的性能问题。
2、模块化
把文件切分的思路再向前推进一步,就是 “模块化”。一个大的 CSS 文件在合理切分之后,所产生的这些小文件的相互关系应该是一个树形结构。
树形的根结节一般称作 “入口文件”,树形的其它节点一般称作 “模块文件”。入口文件通常会依赖多个模块文件,各个模块文件也可能会依赖其它更末端的模块,从而构成整个树形。
3、选择符嵌套
选择符嵌套是文件内部的代码组织方式,它可以让一系列相关的规则呈现出层级关系。在以前,如果要达到这个目的,需要我们手工维护缩进关系,当上级选择符发生变化时,所有相关的下级选择符都要修改;此外,把每条规则写成一行也不易阅读,为单条声明写注释也很尴尬(只能插在声明之间了)。
在CSS 预处理语言中,嵌套语法可以很容易地表达出规则之间的层级关系,为单条声明写注释也很清晰易读。
4、变量
在变更出现之前,CSS 中的所有属性值都是 “幻数”。你不知道这个值是怎么来的、它的什么样的意义。有了变量之后,我们就可以给这些 “幻数” 起个名字了,便于记忆、阅读和理解。
接下来我们会发现,当某个特定的值在多处用到时,变量就是一种简单而有效的抽象方式,可以把这种重复消灭掉,让你的代码更加 DRY。
5、运算
光有变量还是不够的,我们还需要有运算。如果说变量让值有了意义,那么运算则可以让值和值建立关联。有些属性的值其实跟其它属性的值是紧密相关的,CSS 语法无法表达这层关系;而在预处理语言中,我们可以用变量和表达式来呈现这种关系。
6、函数
把常用的运算操作抽象出来,我们就得到了函数。
开发者可以自定义函数,预处理器自己也内置了大量的函数。最常用的内置函数应该就是颜色的运算函数了吧!有了它们,我们甚至都不需要打开 Photoshop 来调色,就可以得到某个颜色的同色系变种了。
怎么用?
内容较多,附一篇博客以供阅读:
浅谈 CSS 预处理器(二):如何快速上手?
1.5、编码规范
以ESLint为例
是什么?
ESLint 是一个插件化的 javascript 代码检测工具,它可以用于检查常见的 JavaScript 代码错误,也可以进行代码风格检查,这样我们就可以根据自己的喜好指定一套 ESLint 配置,然后应用到所编写的项目上,从而实现辅助编码规范的执行,有效控制项目代码的质量。
为什么?
JavaScript 是一门神奇的动态语言,它在带给我们编程的灵活性的同时也悄悄埋下了一些地雷。除了基本的语法错误能在程序一启动的时候被检测到之外,很多隐含的错误都是在运行的时候才突然地蹦出来。除非你的程序有着 100% 的测试覆盖率,否则说不定哪天就会因为一个xxx is undefined而导致程序崩溃,而为了避免这样的错误可能你只需要在提交代码的时候用工具静态分析一下,仅此而已。
怎么用?
ESLint中文官网
ESLint英文官网
这是一篇介绍怎么用的博文
1.6、协作工具
是什么?
有前后端写作工具,有协同开发的代码仓库,有任务分配工具,有项目文档,有文档工具。
这里随便举几个例子。
任务分配:trello/gitlab todo
代码仓库:gitlab
文档:gitlab wiki/trello
产品设计:sketch画图,inDesign写文档
为什么?
有效的协作工具可以提高开发效率,方便对接,以及日后维护。
开发的一个很大的问题就是当需求变更和日后维护的时候,比较难处理。
1.7、其他
1、图标可以使用svg sprite,介绍;
2、浏览器自动刷新,热加载,介绍;
3、编译中间语言,如 es6/7,介绍;
4、压缩图片,一定大小内使用base64,介绍;
5、根据文件内容生成哈希值,实现缓存控制,介绍,腾讯家的博客;
2、进阶型
2.1、版本管理
是什么?
这里指的是开发版本和上线版本的版本管理,而不是指gitlab这样的版本管理。
为什么?
方便管理项目,不管是发布更新内容,还是查看bug修复情况,通过版本管理可以轻松做到。
还可以有效针对bug进行解决,发现了某个bug,可以回退到没有bug的版本,确保线上先能正常工作。
然后再细细查看bug发生原因。
怎么做?
如何进行上线更新?
1、覆盖更新:在半夜没人访问时,统一进行更新(我们就是这么做的);
但这样存在一个问题,假如用户在晚上的时候也在访问这个页面,也就是只存在相对低峰期,而不是绝对低峰期(例如淘宝,肯定晚上也有人在访问),那么这种方案就不可行了,因为这必然存在一个问题:
1.1、先部署html,然而此时静态资源没部署,会发生显示结果错乱,或者出现逻辑错误;
1.2、先部署静态资源(比如css或js),html还没部署,那么依然会显示错乱,或者出现逻辑错误;
解决办法如下:
2、采用非覆盖更新:加入版本号
方法一:
a.b.c
//a = 大版本的改版,全新UI,架构变化都可以用这个数字
//b = 小改版,功能或者功能包升级,新功能上线等
//c = 小优化,修正bug或者功能性修补,或者小功能的提升
<link ……xxx.css?v=1.0.0"/>或
<link ……xxx1.0.0.css"/>
方法二:
//计算哈希值,然后例如
<link ……xxx.css?v=0abc12"/>
然后先更新静态资源,再更新页面,也就是新版本的入口文件;
这种方式与上面的区别在于:
2.1、静态资源(css、js或图片),并非覆盖旧有资源的,而是采取新增方式,因此线上会同时存在2个版本,例如v1.0.0和v1.0.1;
2.2、部署静态资源后,由于页面还没部署,因此用户依旧访问的是v1.0.0版本的静态资源;
2.3、然后再部署页面,页面中指向的入口改变,因此用户访问v1.0.1版本的页面时,自然也将其导向v1.0.1版本的静态资源;
优点:
1、在使用CDN资源时,这种方法更为靠谱;
2、可以有效解决一直有人在访问网站时所导致的错乱问题;
3、方便版本回滚。
然后给几个更详细的扩展内容:
前端版本更新时的发布
大公司怎么开发和部署前端代码
静态资源版本更新与缓存
2.2、Flow
是什么?
flow,facebook出品的javascript静态类型检查器,github上star数高达11615
Flow官网
为什么?
众所周知,js是一门弱类型的语言,类型转换往往隐含在各种业务代码中,同时也埋下了不少的坑。比如以下代码
// return string
function getEnvVersion(){
return '1.1.1';
}
// '1.1.1' > 0 => false, so nothing happen
// but you don't know that
if(getEnvVersion() > 0){
// doSthAwesome();
}
function size(obj){
return obj.length;
}
// uncaught error
size(null);
类似的情况数不胜数,通过jshint工具做一些编码规范可以规避一些问题,但由于js过于灵活,还是有许多无法检查到的隐患。
怎么做?
通过引入flow,手动指定变量的类型,以保证变量的类型与预期一致,假如和预期的不一致,那么flow就会报错。
例如以下代码:
//flow-examples/src/primitives.js
//在文件的头部加入,用注释加入 `@flow` 声明,这样flow.js才会检查这个文件。
//@flow
//在声明变量时,在变量名加入 `:[Type]` 来表明变量的类型,其它类型同理。
//这个语法非常像flash的ActionScript,咦?好像暴露了什么。
var num:number = 1;
var str:string = 'a';
//当然,也可以不加类型,这样就跟原来的js一样了。
var variable = 'zz';
这里就表示num变量的类型是number,而str变量的类型是string,假如类型不符,那么就会报错;
如何检测
flow.js 中定义了的5种最简单的类型,(warning:都是小写),其中void对应js中的undefined
boolean
number
string
null
void
还有复杂类型的:
Object
Array
函数
自定义Class
这几个类型比较复杂,而且可以相互嵌套。但flow依然能检查出来,在flow.js中对这几种类型有非常多的检查语法。
由于flow使用的是jsx语法,因此实际使用时,还需要通过babel来编译成浏览器能正常跑的版本。
flow的优点:
1、flow.js对工程的侵入性很小,无需大量的额外工作就能使用起来;
2、flow.js是一种基本保障,确保检查无误才能运行。
2.3、单元测试
是什么?
wiki关于单元测试的条目
知乎上一些关于单元测试的回答
前端单元测试,百度百科
简单通俗的来讲,测试你的每一个函数,能不能正常跑起来。
假如你每一个函数都能正常运行起来,那么说明你整个系统都可以正常的运行起来(从代码上来讲如此)。
另外,前端由于是GUI类型,因此以api为测试准则的并不能完全确保和预期效果相同(但也可以减少很多错误的发生)。
为什么?
1、确认某段代码或模块或接口是否适合使用;
2、在实际使用过程中会伴随着一大批的附带操作大量增加测试时间,并且无法保证其测试覆盖率;
3、更高效更稳定的确认其是否可用。
4、随着项目规模的增加,函数、方法、变量都在递增,尤其是进度的不足,来自产品经理的压力,还有QA所带来的各种Bug报告会让原本整洁的代码变得一片混乱。此时单元测试将是一根救命稻草,它是一个衡量标准,告诉开发人员这么做是否将改变结果;
怎么做?
首先它是一个检验,所以应该只有pass或fail两种情况。而检验的对象应该是某个接口或模块,所以应该调用它获得一个结果。检验这个结果就是单元测试的基本动作,就拿一个除法函数来做例子:
//为了节省篇幅,这个例子极为简单,并且没有考虑到b为0的情况
//更详细内容请查看引用10
function division (a, b) {
return a / b;
}
var result = division(4, 2);
if (result === 2) {
alert('pass');
} else {
alert('fail');
}
TDD需要遵循如下规则:
1、写一个单元测试去描述程序的一个方面。
2、运行它应该会失败,因为程序还缺少这个特性。
3、为这个程序添加一些尽可能简单的代码保证测试通过。
4、重构这部分代码,直到代码没有重复、代码责任清晰并且结构简单。
5、持续重复这样做,积累代码。
关于GUI的测试方法:
当前国内外学者针对GUI测试用例生成的问题已经提出了若干种方法,可以分为五类:
1、录制/回放技术;
2、基于有限状态自动机生成测试用例;
3、基于UML生成GUI测试用例;
4、利用人工智能方法生成测试用例;
5、基于事件流图生成测试用例;
6、于活动流图生成测试用例
2.4、PWA
是什么?
PWA是我在参加饿了么前端交流分享会所了解到的。
Progressive Web App是一个利用现代浏览器的能力来达到类似APP的用户体验的技术,由Google实现,让浏览器打开的网址像APP一样运行在手机上。让Web App和Native App之间的差距更小。
他主要效果是让网页有如原生app一样的体验,在访问页面后,可以通过选择将页面添加到桌面上,然后直接通过点击桌面上的按钮来访问。
为什么?
1、下载原生APP需要流量,PWA少很多;
2、原生APP升级版本麻烦,PWA直接在服务器端升级即可;
3、速度上提升体验,并且没网也可以用;
4、厂商支持程度在提升;
5、谷歌提出的(谷歌提出的东西都好用啊);
缺陷:
1、苹果目前尚不可用;
2、需要使用谷歌的service work;
3、可能存在被墙的问题;
4、可能会发生P0事故(也就是说比较严重的,不使用不会);
解决办法:
1、增设开关;
2、灰度/降级方案;
3、监控系统;
4、数据统计(比较使用前和使用后);
怎么做?
附链接,有兴趣的可以直接看链接:
PWA官网(英文)
示例、指南、工具、文章、视频
PWA在饿了么的实践经验
2.5、Mock.js
是什么?
Mock.js官网
生成随机数据,拦截Ajax请求,方便前后端分离开发。
为什么?
1、前后端分离:让前端攻城师独立于后端进行开发;
2、开发无侵入:不需要修改既有代码,就可以拦截 Ajax 请求,返回模拟的响应数据;
3、数据类型丰富:支持生成随机的文本、数字、布尔值、日期、邮箱、链接、图片、颜色等;
4、增加单元测试的真实性:通过随机数据,模拟各种场景;
5、用法简单:符合直觉的接口;
6、方便扩展:支持支持扩展更多数据类型,支持自定义函数和正则;
7、支持多:无论是原生,还是jquery,还是ng,或者通过nodejs,都可以很方便的使用
怎么做?
官网说明链接
一个我觉得比较直观的说明博客
2.6、错误捕获
是什么?
简单来说,就是定位错误出现的位置,方便开发人员调试。
进阶一些,可以捕捉用户在触发错误之前,做了什么事情,比如点击了什么,输入了什么之类,方便复现。
为什么?
在复杂的网络环境和浏览器环境下,自测、QA测试以及 Code Review 都是不够的,如果对页面稳定性和准确性要求较高,就必须有一套完善的代码异常监控体系
如果没有错误捕获,那么就只能开发人员根据错误发生时的描述,去猜bug出现在哪里,这显然是低效率的,特别是某些操作很难复现,那就更麻烦了。
怎么做?
简单来说,常见的有两种方式:
1、try…catch方式;
2、window.onerror方式;
处理方式:
1、沉默模式:什么都不做。
2、基础:
通过以上方式,可以捕获到错误,然后将这些错误存起来,通过ajax发送给服务器端保存成log;
3、进阶:
存储用户每一步的操作,然后在捕获到错误时,将保存的这些操作和错误信息,一起打包以ajax的方式发送给服务器;
给一个错误捕获函数:
/**
* @param {String} errorMessage 错误信息
* @param {String} scriptURI 出错的文件
* @param {Long} lineNumber 出错代码的行号
* @param {Long} columnNumber 出错代码的列号
* @param {Object} errorObj 错误的详细信息,Anything
*/
window.onerror = function (errorMessage, scriptURI, lineNumber, columnNumber, errorObj) {
var info = "错误信息:" + errorMessage + "</br>" +
"出错文件:" + scriptURI + "</br> " +
"出错行号:" + lineNumber + "</br>" +
"出错列号:" + columnNumber + "</br>" +
"错误详情:" + errorObj + "</br></br>";
document.querySelector("#a").innerHTML = info;
}
//输出内容
错误信息:Uncaught TypeError: a.a is not a function
出错文件:file:///C:/Users/hasee/Desktop/1.html
出错行号:29
出错列号:7
错误详情:TypeError: a.a is not a function
有兴趣的可以阅读以下内容作为参考:
如何自动捕获前端的异常
前端代码异常日志收集与监控
2.7、前端性能监控
是什么?
用于监控前端效果,以确保用户体验,避免bug的发生,找到优化的地方。
为什么?
1、不做性能监控,怎么知道用户体验如何;
2、不做性能监控,怎么知道潜在的bug在哪里;
3、不做性能监控,怎么优化业务;
4、不做性能监控,前端的优化如何被体现出来;
怎么做?
一般关注的指标有以下几个:
白屏时间;
首屏时间;
用户可交互时间;
总下载时间;
DNS解析时间;
TCP连接时间;
HTTP请求时间;
HTTP响应时间;
简单粗暴的来说,将以上这些指标统计出来,然后汇总到一起,以图形化界面显示出来,让开发、产品、运营可以一目了然的发现问题在哪里。
具体效果参考如下图片(引自下方参考文章):
给一些参考文章:
7天打造前端性能监控系统
你是如何搭建 Web 前端性能监控系统的?钟国英的回答
3、引用出处
已在上文中给出引用链接的,不在此列表中。
1、http://www.infoq/cn/articles/react-and-webpack
2、http://www.ruanyifeng/blog/2016/01/babel.html
3、http://www.infoq/cn/news/2015/05/ES6-TypeScript
4、http://www.imooc/code/5993
5、https://github/cssmagic/blog/issues/73
6、http://morning.work/page/maintainable-nodejs/getting-started-with-eslint.html
7、https://lluvio.github.io/blog/front-end-architecture.html
8、http://www.alloyteam/2015/07/flow-a-static-type-checker-for-javascript-from-facebook/
9、https://segmentfault/a/1190000006983211
10、https://segmentfault/a/1190000000317146
更多推荐
那些年,大厂在用的技术(前端)
发布评论