前端架构——从入门到微前端 读书笔记
最近,前端圈中出现一个一个热词”微前端“,作为一个前端菜鸟,也来赶赶集。
所以,我读了黄蜂达老师写的《前端架构——从入门到微前端》一书。
概要
这本书主要讲的是, 对于一个前端项目,在项目不断迭代的过程中,对整个项目的工作流、构建流,已经对一个项目的技术选型,已经后期的基础设施的建设进行了一个讲解。并且,在后面第九到第十章中,讲解了微前端。
最近今年里,前端成为软件行业中一个独立的职业,从小的创业公司到大的上市公司,都有自己的前端技术人员甚至是一个团队。在业务不断变化中,代码量越来越大,工程化成为必然的问题。这本书,对于目前前端的现状,以及前端的工程化进行的详细的讲述。但作为前端萌新 的,只能领略一二,在以后的项目中需要慢慢理解。下面是我读书后一些记录。
前端项目的构建,工作流,以及架构实施
因为要关注行情,了解市场的需求,我偶尔回去逛逛boss直聘等招聘网站。发现,现在的前端已经像过去一样,只会写样式、html或者切图。几乎每个招聘上都会有以下这样的要求:
掌握一门后端语言
有navtive开发经验更佳
了解前端工程化 会使用 webpack gulp这样的工具
……
如今的前端已经变成软件行业中重要的一部分。
所以,逃不开的就是,工程化,质量管理,架构等一系列问题。
1. 软件架构的一些基本常识
首先,一个架构我们要去考虑什么
系统间的关系,需要明确当前的系统与其他系统间的关系是调用关系还是依赖关系等
系统内的关系,系统内各个子系统的之间,接口是什么,他们是如何通信的
规范和原则,用于开发人员的沟通的基础,这是一个架构中必须包含的一项,可以是文档或者口头约束。
其次,在架构中要明确需求,及其利益相关人员或者部门,可能不同人员或者部门关注的点不用。例如:
产品或者业务负责人员关心的是能否按时上线已经,未来如何进程产品的迭代
项目经理确定项目计划和人选
开发人员,关心架构的演进和维护
测试人员,是否可以自动测试,或者将测试自动地集成到项目中
对于前端人员,我们还要明确,浏览器支持的范围以及,移动端可以支持的版本等。
常见的架构风格
- 分层风格
一个系统由多层构成,每个层有不同的模块
- MVC架构风格
这个风格强调职责分离,将软件系统分为三个基本部分: 模型(Model), 视图(View),控制器(Controller)。视图和模型通过控制器进行交互,保证用户界面与书模型是一致的。
- 发布-订阅风格
这种风格可以成为称作基于事件的架构风格。其最大的好处是代码上的解耦。在前端的开发过程中,为了解耦不同UI组件的依赖,会经常采用这种模式。
- 管道和过滤器
这是一种适合于处理数据流的架构模式,它将每个步骤都封装在一个过滤器组件中,数据通过相邻过滤器之间的管道传输。最典型的管道过滤器架构师UNIX shell的设计。 在类Unix系统中,使用’|‘作为管道符号,当我明年需要编写复杂的shell脚本来处理内容时,便会使用这个符号。例如’ ls-l|grep.jpg’,便会先执行ls-l命令,再将结果交由grep程序,查找以.jpg结尾的文件名。
前端架构的层次设计
下面是一个图(原图参考书籍:p:22)
2. 前端架构的实施过程
光有概念还不行,需要把它们转化为一套可以落地的理论。首先看下我们一个企业项目的进行周期
下图是一个项目的启动和实施周期(p:28)
了解了开发周期,就需要通过每个周期中不同的特点进行资源的调配。
例如:当我们进入业务回补期,我们当前要面对第一次deadline,这个时候虽然业务开发已经进入正轨,但是于是工作优先级,变成了业务第一,工作第二。
或者,当我们部署上线成功,并且正常进行业务迭代时,我们就需要考虑提升团队能力来获取更好的开发 效率等等。
3. 重要的工作——设计工作流和构建流
在我刚步入工作的时候,接触的项目是多页面应用,用jquery然后html5 ,就是手写文件,在浏览器上打开文件,没写一行CSS就需要手动刷新一下。当项目完成是,就交个后端,后端会用脚本拷贝到nginx相应 的目录下。
后来接触到vue,知道了有cli这么个东西。
到目前为止,市场上出现”云效“等软件。
在这个过程中,我几乎不知道对于一个前端来说什么是运维,或者构建流。
这本书中用了两大章的内容,来说工作流和构建流,下面我分开说一下。
工作流
工作流,就是在工作中可以使用一些脚本或者自己开发一些有用的工具,帮助我们减少重复的劳动,降低出错率。
在工作中,我们可以注意一下几个方面,
- 构建基础规范,包括一些基本是书写规范
前期,如果在团队比较小情况下,可以通过后头来约束。但是,当团队发展到一定规模,就需要通过文档,自动化(eslint等),以及代码评审来规范。
再这样的情况下,便于新人更快的融入到开发当中,以及可以约束同事产出更好的代码并且使得项目维护更加方便。
- 可以使用一些预编译器,来加快我们的开发效率,例如es6,es7等语法,或者typescript。对于css有sass,less等
- 统一的开发工具,统一的开发工具有利于,可以通过使用工具中的插件来提升开发效率,并且不需要学习。但我个人喜欢用不同的工具,目前用的最多的有vscode 以及webstrom 。并且两个工具各有优劣。例如,vscode更佳简单轻便有很多插件可以随时插拔,并且是free的 。但是,我再使用vscode的git相关插件中,总会出现一些问题。在这点webstrom会更好一些,我比较喜欢使用webstrom的git对比工具,每当有不该合并的代码混入时,我可以通过比对,轻松将代码分离开来。
- 值得注意的是项目中的文档
项目中的文档可以分为独立的文档,已经代码中的文档,两者相结合可以达到很好的效果。我认为,在开发新需求的同时,开发文档也应该是工作中不可缺少的一部分。通过文档可以让队友很好的理解你当初的设计思路,或者比如说,日后在重构的时候,可以很清楚代码的逻辑以及为什么要这么写。
除了单独的文档,还有注释,代码提交记录以及相应的描述都可以成为很好的文档。
- 测试
测试是很好保证代码质量的一个手段,通过写测试可以更好的理解代码和逻辑,并可以在适当的时候为重构或者修复bug时防止,其他功能被篡改。
测试从下往上主要有单元测试,组件测试,服务测试,e2e测试。
构建流
有了工作流之后,我们需要将我们,我们的源代码通过构建,发布到服务器上。
对于一个小的,不需要任何依赖项目,我们只需要将我们编写的js,css,html放在一个文件夹里,然后丢到服务器上。几乎,没有什么构建流可言。但,我们项目越来越复杂我们必须关注以下一些问题。
- 依赖管理工具
目前而言,我们主要使用npm,npm主要基于commenJS来实现。在构建的过程中,可能会通过其他形式来引入,因为,commenJs并是在nodejs中运行的包管理机制,它并不适合用于移动端。
这里有一个重要的问题,就是nodeJS跨平台的问题,有些nodeJS依赖包,为了优化性能,将一部分功能使用C++编写,而C++代码再node中运行的时候,需要编译。编译的过程会存在,操作系统或者,npm版本不兼容的问题。
- 构建的目标
根据场景不同,构建是一个复杂的话题,但基本项目离不开以下一些文件
a. 用于管理运行时(如路由懒加载)的runtime.js文件
b.样式相关的style.css
c. 解决JavaScript在不同浏览器兼容问题polyfills.js
d. 程序相关的main.js
在文件打包时,除了进行代码的编译、打包、还要对css,js等静态文件进行重命名等。
-
设计构建流
- 明确任务,就是需要做什么,例如npm build是打包,npm test是测试
- 步骤拆解,将任务拆解为一些步骤
- 展现形式,我们大多数是一个网站,但有些项目例如一个组件库,需要的是文档以及示例
- 插件,在构建的时候,一般会选用插件,使用插件能更高效,在选用插件的时候,确定构建的可行性
明确上述后,我们需要使用工具对其进行自动化
目前,常用的工具有glup grunt webpack等,不同的工具优劣不同,使用场景也不同。
对于,使用框架的项目,一般情况框架都提供的相应的cli,只需要进行简单的定制。
持续集成
对于构建好的目标文件,则需要进行部署。以下为三种部署方式:
- 持续部署,构建完成即部署,常见于测试环境
- 自动化部署,在持续部署的基础上稍微进行弱化,即需要人为的介入才能自动化部署
- 手动部署,即需要全程人为介入的部署流程
对于自动化部署,我们需要选取适当的工具,例如jenkins等帮助我们完成。同时,部署的时候需要,进行环境配置。例如将http请求从本地的mock Server指向后端服务等。
还有一件事情,就是我们需要写一些调试的代码,为了捕获难于察觉的bug,通常会有一些额外的开关来获取我们需要的调试数据。如:
- 在url中添加一些参数,在前端代码运行时去读取这些参数
- 对特定的账号进行权限处理,以获取调试功能。
多页面应用与单页面应用
我认为,假设你所拥有的工具只有一个锤子时, 把所有的事物都当做钉子来对待是很有吸引力的。
——锤子定律
1. 为什么不使用单页面应用
对一个前端工程师来说,拿到一个项目要去实现它,无非用两种方式
- 使用多页面,包括服务端使用模板引擎进行渲染,或者使用类似jquery的js库
- 使用单页面框架,目前流行的vue,react,angular
书中作者通过三个方面来阐述多页面应用的优势,分别是:构建成本,学习成本,后台渲染成本,架构的复杂性。
构建成本
对于一个多页面系统来说,几乎不需要什么构建,因为,不论是html代码或者后端通过jsp或者asp等动态产生的html代码都是可以直接在浏览器中运行的。
但是,单页面就没有那么顺利。目前的单页面系统中几乎都使用了虚拟dom技术,我们在开发中产出的是,vue的template模板语言,或者是jsx。但是它们在浏览器中运行的却是,可以返回一个对象的render函数,这个对象是一个虚拟dom的对象,经过一系列复杂的操作将其渲染为真实的dom。
所以,当将一个.vue文件或者.jsx文件变成render函数时,就产生了构建成本。即使目前已经有成熟的工具可以使用,例如vue-loader, 或者babel.js。但是,跟多页面比起来,这些”黑盒工具“(vue-loader,babel.js等)在一定程度上会带来一些成本,与维护的风险。
学习成本
就目前我们前端开发中常用的单页面框架(vue, react, angluar), 每一种框架都有详细的文档,以及强大的社区。特别是最近比较火的vue,我们在编写的时候,感觉就好像是编写原生的html代码,对于一个小团队或者团队的技术储备不够扎实的时候,直接是首选。
但是,使用久了就会发现,要构建一个复杂的项目,需要对其原理有一个深入的理解才可以,这个过程无形中增加了许多学习成本。
后台渲染成本
书中谈到这个,主要是说目前的一单页面框架在面对SEO(Search Engine Optimization)的情况,作为单页面系统,需要将dom渲染挪到服务端去,这样就增加看服务端渲染的成本。如果是,用原生的html开发的网站就不存在这个问题。
除此之外,使用多页面应用,还有个好处就是,在面对在对兼容性有要求的项目中体现出的优势,就是防止出现兼容问题时对”黑盒框架“的束手无策。
2. 多页面应用
3. 单页面应用
前端MV*原理
- M: model表示数据模型,返回一个数据对象,是展现给用户的信息的一个抽象。
- V:view展示层,这里表示呈现给用户的页面。
- *: 这里通常有两种,一种Controller,一种是VM(ViewModel)实际上是改进版的MVC。
在我们常用的三大框架(vue,react,angluar)中都是通过虚拟dom来优化直接使用浏览器dom操作api操作dom带来的性能低下的问题,所以有两层mv*,
- data->virtual dom: 这里vue中的是data函数返回的数据对象,react中是this.state,他们都是
- Virtual dom -> real dom:在虚拟dom与真实dom之间,通过一些逻辑进行关联,当虚拟dom发生改变时会同步到真实dom上去