概述
这几天我读了 前端架构:从入门到微前端,感觉收获挺大的,把读书笔记发出来,供以后开发时参考,相信对其他人也有用。
我的书单
读书笔记
1.对于只使用后端 API 的前端来看,后端看上去像只做 CRUD。然而,后端并不像看上去那么简单。从架构层面考虑,后端是要事先高并发和高可用的。在多数情况下,数据库是后端最大的瓶颈,存储的时候要考虑原子性、一致性、隔离性和持久性,使用的时候要考虑通过分表、存储、主从同步来提高性能和并发量,在这个过程中还要考虑备份、迁移、查询速度、效率等问题。此外,在代码实现上还有一系列的复杂问题:使用消息队列来解耦依赖,使用微服务来拆分单体应用。
2.规范、原则、模式、架构,是我们在前端架构中需要关注的内容。
3.架构的步骤如下:
1.收集利益相关者的需求
2.与相应的技术人员讨论,了解架构上的潜在限制
3.寻找潜在的可行性技术方案
4.整理出功能列表中的功能需求和跨功能需求
5.找出会严重影响开发的风险点
6.和技术委员会、利益相关者反复确认方案
7.对架构设计进行概念证明
8.细化架构的部分实施细节
9.结合技术和业务,进行需求排期
(在这个过程中,最重要的还是收集相关的架构需求)
4.在设计架构的过程中,各个组织、开发人员、架构师都拥有自己的关注点。在大部分的项目中,都会拥有相似的一些关注点,也因此它们会来自于其他项目的经验。不同的项目因为自身的需求,对于各种特性的优先级考虑往往是不一样的。有的项目认为安全更重要,由安全带来的用户体验下降的问题是可以允许的;而有的项目认为用户体验更重要,也便能忍受其影响到的其他特性。
5.在开发人员和运维人员部门分离的组织里,往往会在内部限制某些语言,如选定 Java 等语言,限制其他语言的使用。如果选定的是其他语言,如 Javascript + Node.js,那么运维人员便难以维护,需要进行培训或者招聘新的运维人员。
6.在日常的开发中,常见的架构风格有:1.分层风格。2.MVC架构风格。3.发布-订阅风格。4.管理和过滤器。
7.MVC架构风格在涉及图形用户界面时,往往都有它的身影,如前端应用、移动端应用等。
8.发布-订阅风格带来的最大好处是,代码上的解耦。
9.架构的设计原则:1.不多也不少。2.演进式。3.持续性。
10.采用敏捷模式是为了应对用户需求的不断变化,而需求的变化,则可能会和早期确认的方向不一致,与最初设计的架构不匹配。
11.瀑布模式采用的是完全计划式设计,即在编码前,由顶层至底层进行的一系列架构设计,包含了各个模块、服务、函数和接口。而演进式架构,则是预先设计好重要的部分如模块功能划分、领域划分等粗粒度,随后在编码的过程中,再进行函数和接口的设计和实现。
12.一旦前端应用需要从后端获取数据,就意味着前端应用在运行时是动态地渲染内容的,这便是 Model-UI 层解耦。
13.随着前端单页面应用的流行,前端进入了一个新的时代,要考虑的内容也越来越多:1.api管理。2.大前端。3.组件化。
14.MVC 满足不了开发人员的需求,于是采用了组件化架构。而组件化 + MV*也无法应对大型的前端应用,微前端便又出现在我们的面前,它解决了以下问题:1.跨框架。2.应用拆分。3.遗留系统迁移。
15.前后端分离架构其实是一个笼统的概念,它是指前后端分离如何实施的技术决策。它包含了一系列的决策、用户鉴权、API接口管理与设计、API 文档管理、Mock Server使用、BFF(服务于前端的后端)、是否需要服务端渲染等。
16.应用级架构有:1.脚手架。2.模式库。3.设计系统。
17.代码级的规范与原则包含下面内容:1.开发流程。2.代码质量及改善。3.规范而非默契。
18.优秀的软件开发人员,带有强烈的工匠精神,当遇到问题时,便会想着如何去解决它。
19.技术负责人日常要做的事情有以下几方面:1.适当地平衡业务的进度与技术方案。2.解决重要、复杂的技术问题。3.帮助团队的其他成员成长。4.从全局考虑整个项目的技术和业务问题。
20.在项目实施的过程中,有三个要素:1.保证项目在开发过程中的质量。2.提升人员的能力。3.确保功能和应用上线。
21.概念验证(PoC)是对某些想法的一个较短而不完整的实现,以证明其可行性。
22.当我们开始一个项目的时候,进入的是迭代1的开发,那么迭代0呢?我们可以将其视为在所有迭代之前的准备工作。
23.为了有针对性地规范代码,并帮助其他成员了解代码,一个相应的举措便是编写相应的项目示例代码。
24.先进的架构,并不一定会为业务带来价值;先进的技术,也并不一定会为业务带来价值。
25.整个分享结束,掌握得最好的人,便是那个做技术分享的人。
26.不论怎样,程序员作为一个“匠人”,总得有点“追求”,要不断地提高自己的水平。
27.1.0时期,迭代0就是选定一个前端框架。2.0时期,迭代0应该是选定前端框架 + 完整的构建脚本和构建系统。3.0时期,迭代0应该是选定前端框架 + 完整的构建脚本和构建系统 + 流程规范化。
28.为了降低开发成本,我们还需要拥有一些前端应用脚手架、自己的开发工具或者协作工具。于是,工作的重心便从业务转向了构建工具。
29.常规代码检视,即团队成员聚在一起,听其他成员讲述自己最近(通常是今天)写的代码。一个完整的代码检视是从讲述相关的业务功能、技术功能开始的,而非打开IDE直接讲代码的实现;阻塞式代码检视,通常是提交一个 pull request,即要求其他人把代码拉倒主分支,这就要求项目中的其他开发者来帮助我们检视代码。
30.在 Node.js 领域里,可以使用 cnpmjs 来搭建自己的私有化包服务器。
31.本地的依赖包是指:把应用的依赖放在本地,它通过包管理工具来支持 file 协议并引入依赖,即在 package.json 中通过 "aofe:" "file:aofe"
的形式来引入依赖。
32.尽管前端部署很简单,还是适当的考虑“回滚机制、蓝绿部署、灰度发布”等因素。并在应用部署后,使用 UI 自动化测试来测试部分功能是否正常,以及测试对应的后端服务连接。
33.功能开关是一种强大的技术,允许团队在不更改代码的情况下修改系统行为。
34.在学习编程的初级阶段里,经常会掉入一个陷阱:一旦学会一个新的框架,就会在我们的大部分项目中使用这个框架。即所谓的“锤子定律”:
我认为,假设你所拥有的工具只有一个锤子时,你把所有的事物当做钉子来对待时很有吸引力的。
35.对于面向 Google 的网站而言,它可以提供更好的 Javascript 渲染支持,可以直接抓取 Javascript 渲染的应用。然而,对于国内的开发者而言,多数时候我们要面对百度、搜狗等搜索引擎,它们对 Javascript 渲染页面的支持并不是很好。
36.为了提供更好的用户体验,一些代码逻辑会重复地在前后端出现,比如表单的校验。对于一个长的或者复杂的表单,在用户填写的过程中,应该实时提示用户哪些字段出错。而不是在用户提交表单后才告诉用户哪里有错。
37.多页面应用往往是一些轻量级的前端应用,多数时候会被划定为“前端页面”——往往只需要编写页面样式,和编写一些 Javascript 就能完成工作。常见的这类应用有:
1.门户类、资讯类、数据展示类应用
2.弱交互应用
3.面向资源受限的设备应用
38.我们选择 MVC 框架,多数是因为我们需要其中一些特性,比如:
1.模板引擎,动态生成、创建页面
2.双向绑定,实时修改数据
3.前端路由,路由变化映射到对应的逻辑上
...
39.基于 Javascript 的模板引擎的表现形式是,将模板转移为 Javascript,在执行的过程中,再动态更新所需要的 DOM 节点。它和基于字符串的模板引擎的区别主要在于第三点,是否全局替换 DOM 节点。
40.双向绑定是指:
1.视图的变化能实时地让数据模型变化
2.当数据发生变化时,对应的视图上的值也发生变化,此时需要更新视图的值
41.路由的 hash 具有以下一些特点:
1.hash值得概念不会导致页面重新加载
2.hash值由浏览器控制,不会发送到服务器端
3.hash值的改变会记录在浏览器的访问历史中,因此可以在浏览器中前进和后退
42.前端MV*框架的原理就是通过观察和订阅来进行联动操作,以自动触发各种逻辑函数。
43.框架选型的考虑因素:
1.团队成员能否快速掌握该框架?
2.框架的生态是否丰富?是否拥有我们所需要的功能组件?
3.不同的框架对于不同浏览器的支持程度如何?
4.框架的后期维护成本和难度怎样?
5.能否以最小的代价迁移现有的应用?
44.react和vue相对于 angular 来说是小而美的框架,这些框架和 angular 相比的主要问题是:维护成本太高。
45.除了在编写应用时不需要对 DOM 进行直接操作、提高了应用的性能,React还有一个重要的思想即组件化。
46.创建组件库的步骤如下:
1.寻找一个现成的组件库。
2.构建出组件库的基础设施。从步骤1的组件库中删除所有的组件,修改项目名等。
3.编写一两个测试组件,引入项目中进行测试
4.持续不断地更新组件库
47.组件的发展过程如下:
1.风格指南,早起侧重视觉,对设计的文字、颜色、LOGO、ICON等设计做出规范,产出物一般称为Guideline,Guideline通常是UI规范
2.模式库,即UI组件库,侧重于前端开发,产出物一般称为组件库UI框架,比如Bootstrap库
3.设计系统,结合了风格指南和模式库,并附加了一些业务特别元素,进一步完善了组件化到页面模板相关的内容
48.基础的UI组件如何摆放成一个页面,它们摆放的位置和相互关系就是一个UI系统特有的模式
49.在Web应用中,通常对颜色有如下区分:
1.主题色,又称为品牌色,用于体现产品的特性及宣传时使用。
2.功能色,用来展示数据和状态,以及提醒用户
3.中性色,用于常规的页面显示和过渡,通常是浅色和深色的变种,如白色和灰色
(在一些设计系统中,会提供相应的颜色模板)
50.在早起的Windows系统里,某些字没有13px大小的字体,因而多数采用的是偶数。这种奇怪的习惯也被保留到今天。
51.Grid设计有很多别称:网格设计系统等。它其实是使用百分比进行布局的。
52.Grid布局可以轻松应对左右布局的页面,但是对于上下布局的页面来说,Grid布局基本很难实现,所以有了 flex 布局。Flex 布局也叫做弹性盒子布局。
53.组件的质量和数量是通过两种方式来提升的:需求、新的Bug。
54.组件的二次封装不外乎两种模式:
1.中介者模式。用一个中介者来封装一系列的对象交互,它提供了与原有组件一致的属性、输入和输出。
2.装饰者模式。在不改变原类文件及不使用继承的情况下,动态地将责任附加到对象上,从而实现动态拓展一个对象的功能,如果某个组件的属性、输入、输出不符合API规范,那么我们就创建一个新的接口,来保证它符合规范。
55.风格指南通过创建统一的风格、规范的样式、合适的元素大小来规范化设计;模式库通过创建统一的组件、组合的组件命名、统一的使用方式来规范化组件的使用。但是这些模式、规范等,并没有明确地标明出来,在不同的设计人员的心里,可能有不同的规则、原则,而没有统一。所以就催生出了设计系统。
56.设计系统包含如下指南:
1.动作
2.无障碍
3.内容原则
4.信息架构
57.设计系统分为设计原则和设计模式。设计原则比如:亲密性、对齐、对比、重复、直截了当、简化交互、足不出户、提供邀请、巧用过渡、即时反映。设计模式比如:色彩、数据录入、数据展示、空状态、布局、加载、本地化、字体、搜索、导航、消息、标记和风格等。
58.出于简洁考虑,有的应用的 header 会显得非常简单,隐藏一些不常用的功能。而有的设计,则会将 header 设计成带动画和过渡的,当我们打开页面的时候,看到的是完整的 header;而当我们往下滚动一段距离的时候,看到的是简洁的、修改的 header。
59.一说到前后端分离,人们最大的痛楚莫过于对 API 的管理和维护。
60.作为一个专业的前端开发人员,考虑后端接口对于前端的合理性,也是日常工作的一部分。
61.与普通的Mock Server相比,DSL(领域特定语言)形式的 Mock Server 的最大特点是用配置代替代码。
62.BFF 的使用场景如下:
1.应对多端应用
2.聚合后端微服务
3.代理第三方API
4.遗留系统的微服务化改造
63.API Gateway 与 BFF 最大的区别在于,API Gateway 只拥有一个 API 入口。
64.GraphQL 让前端能够编写查询语句,获取自己需要的数据。
65.如果业务一直在变动,或者需要对外提供 API,选择 GraphQL 更合适。
66.康威定律:设计系统的组织,其产生的设计和架构等价于组织间的沟通结构。
67.微前端架构可以采用以下几种方式进行:
1.路由分发式。通过 HTTP 的反向代理功能,将请求路由到对应的应用上。
2.前端微服务化。在不同的框架之上设计通信和加载机制,以在一个页面内加载对应的应用。
3.微应用。通过软件功能的方式,在部署构建环境中,把多个独立的应用组合成一个单体应用。
4.微件化。开发一个新的构建系统,将部分业务功能构建成一个独立的 chunk 代码,使用时只需要远程加载即可。
5.前端容器化。将 iframe 作为容器来容纳其他前端应用。
6.应用组件化。借助于 Web Components 技术,来构建跨框架的前端应用。
68.在微前端设计初期,构建基础设施要做如下几件事情:
1.组件与模式库
2.应用通信机制
3.数据共享机制
4.专用的构建系统(可选)
69.普通的父子级通信可以做到以下几方面:
1.通过PostMessage在父子窗口之间进行通信。
2.通过parent.window寻找父窗口,再发出全局的自定义事件
3.当其他应用加载时,将消息发送给父窗口,由父窗口发出自定义事件
4.当其他应用未加载时,先将消息传递给父窗口,再由父窗口进行储存,提供一个获取通信的机制。
70.常见的数据交互方式,有以下几种:
1.URI 参数传递
2.使用 LocalStorage 共享数据
3.其他客户端储存,如 IndexDB、Web SQL 等
4.服务端储存客户端状态,可以采用 JSON 格式储存
71.设计的过程就是识别、度量模块内的联系,再将相关的行为聚集在一起,把不相关的行为放在别处。在实践的过程中,主要基于单一职责和关注点分离两个原则来实现。
72.在开发能力完备的情况下,架构走向不合理的原因是 KPI,由 KPI 导向的系统架构设计,必然会出现一定的不合理性。从这种角度看,架构是不是最好的不重要,重要的是大家都满意——只有领导满意,才可以多涨工资;只有被团队采用,才可以向外宣传,吸引新成员。
73.业务层的耦合直接影响了技术上的耦合,这个困境导致了技术架构在不断变化。所以我们需要一个专家,这里的专家并非单纯指技术方面的专家,而是技术专家 + 业务专家,他可以是一个懂业务的技术专家,或者是一个懂技术的业务专家。
74.微前端的路由分发难点在于:原先我们只是将路由分发到应用的组件执行,现在则需要根据路由来找到对应的应用,再由应用分发到对应的组件上。
75.iframe 的通信机制:直接在每个应用中创建 postMessage 事件并监听,并不是一个友好的事情。其本身对于应用的侵入性太强,因此通过 iframeEl.contentWindow 去获取 iframe 元素的 window 对象是一个更简化的做法。
76.微应用化是指,在开发时应用都是以单一、微小应用的形式存在的,而在运行时则通过构建系统合并这些应用,组合成一个新的应用。它有2个缺点:1.所有应用的依赖需要统一。2.高度依赖于持续集成(必须需要每30分钟构建一次)。
77.微服务的基座一般包含以下功能:
1.管理其他子应用
2.负责应用间的通信
3.设计路由的响应机制
4.支持嵌入常规及iframe模式
78.微件化是指,每个业务团队编写自己的业务代码,并将编译好的代码部署到指定的服务器上。
79.web components 主要由如下四项技术组成:
1.Custom Elements(自定义元素),允许开发者创建自定义元素
2.shadow dom(影子DOM)
3.html templates(html模板)
4.html imports,用于引入自定义组件
80.在编写应用的过程中,我们学会如何使用某个框架、语言,在演进架构的过程中,我们学会如何去做应用。前者是一个开发人员的基线,后者则是一个开发人员成长的机会。对于前端开发人员来说,我们会更关注架构的成长,因为它会为自己带来更多的成长。
81.一般的版号格式是:主版本号、次版本号、修订号,其版本号递增的规则如下:
1.主版本号:当你做了不兼容的 API 修改
2.次版本号:当你做了向下兼容的功能性新增
3.修订号:当你做了向下兼容的问题修正
82.在复杂的前端处理逻辑中,采用 reactive.js 或者 rambda 来解决问题。
83.当我们要解决大量的浮点计算的问题时,需要引入如 bignumber.js 这样的库。
84.怎样的重写才能带来业务价值:
1.更少功能完成时间
2.更好的用户体验
3.提升应用的性能
85.以下项目需要重写:
1.过时的依赖或技术
2.出现表达力更好的技术
3.旧代码无法维护
86.如何让一个我们觉得“烂”的系统慢慢变好?旧的系统给我们带来一系列深入的思考,我们会思考平时哪里做的不好,应该怎么做才能让系统变得更好?如果能不断地在新旧系统之间切换,那么我们就能理解好的架构的意思,好的设计的初衷。并且,只有经历过遗留系统,才能让自己真正地成长。