前端基础建设和架构30讲

前端基础建设与架构 30 讲

 

一、前端架构30讲

 

1. 开篇

前端学习路线 https://roadmap.sh/frontend
如何打造一个顺滑的工程化流程,为研发效率助理,如何建设可靠的基础设施,为业务保驾
vue.js完整版和运行版的区别?问的是编译器原理。
制定工程化方法,实现构建和发布流程,设计应用中公共方法和底层架构。

 

前端挑战1
前端挑战1

 

 

前端挑战2
前端挑战2

 

 

内容体系
内容体系

 

 

第一部分工具
第一部分工具

 

 

第二部分开发和架构生态
第二部分开发和架构生态

 

 

第三部分案例核心源码原理和设计模式
第三部分案例核心源码原理和设计模式

 

 

第四部分实战造轮子
第四部分实战造轮子

 

 

最后部分Nodejs全栈
最后部分Nodejs全栈

 

 

2. 导读

 

2-1. 演进方向

 

演进流程
演进流程

 

 

2-1-1. ajax-2005年实现前后端分离。

 

2-1-2. MVVM模式:双向绑定或自动渲染更新;

MVC:主要是通过view或者用户直接控制controller;简化数据和视图的依赖,解决数据频繁更新的问题,虚拟Dom理念。

![MVC模式](./images/1654230630085.png)
 

2-1-3. mvvm与mvc最大的区别:

MVVM实现了view与model的自动同步,也就是model属性改变的时候, 我们不需要再自己手动操作dom元素去改变view的显示,而是改变属性后该属性对应的view层会自动改变。
最终发展处三个前端框架:vue,angle,reactor

 

2-1-4. nodejs崛起实现BFF层

 

BFF层优点
BFF层优点

 

**同构方案实现SSR架构;**此时前端工程师就要关系服务器的运维,部署,发布,监控

 

2-1-5. 为了解放运维工作 Servless理念及平台出现

 

演进过程中的核心技术方案
演进过程中的核心技术方案

 

 

2-1-6. 现代化架构方案特点

 

现代架构特点
现代架构特点

 

 

2-2. 渲染方案的演进(CSR->ssr->NSR->ESR)

 

2-2-1. CSR

 

CSRl执行图
CSRl执行图

 

  1. 实现前后端分离
  2. TTFB时间最小,但是FCP/FMP时间不理想

 

浏览器加载图
浏览器加载图

 

 

2-2-2. SSR

 

SSR执行图
SSR执行图

 

 

SSR渲染时序图不需要客户端再取获取数据
SSR渲染时序图不需要客户端再取获取数据

 

SSR和CSR结合基于hydration(注水)的方案

hydration:同构应用中数据的获取和消费需要保留状态;在服务端返回html字符串的时候讲数据JSON.stringify一并返回叫dehydrate(脱水),客户端就不需要再请求数据可以直接使用,这个过程叫注水。

 
2-2-2-1. 流失SSR和渐进式SSR

 

流失和渐进式ssr
流失和渐进式ssr

 

 

2-2-3. NSR:通过Native渲染生成HTML并缓存在客户端

优点:将服务器的渲染工作放在了一个个独立的移动设备中,并借助离线存储技术实现了页面的预加载,同时又不会增加额外的服务器压力。

 

2-2-4. ESR:边缘渲染

边缘计算:在靠近物或者源头的一侧,采用网络,计算,存储,应用核心为一体的开放平台,就近提供最近端服务。应用服务在边缘测发起,产生更快的网络服务响应,应用在更快的实时,应用智能,隐私保护等需求。而云端扔可以访问边缘的数据。
在CDN上缓存页面的静态部分,在用户访问页面时可以快速返回用户静态内容,在CDN节点上发起动态内容请求,在动态内容获取之后利用流的方式,继续返回给用户。

 

3. npm机制和私服原理(JS报管理工具原理分析)

 

3-1. 包管理问题

 

npm管理的问题
npm管理的问题

 

 

3-1-1. 安装机制

 

安装机制
安装机制

 

 

3-1-2. npm缓存机制

 

缓存机制
缓存机制

 

 

3-1-3. npm link 本地调试和包可用性验证

 

npm link
npm link

 

 

3-1-4. npx的作用

npx commandname 会自动地在项目的 node_modules 文件夹中找到命令的正确引用,而无需知道确切的路径,也不需要在全局和用户路径中安装软件包。

 

3-2. npm多远镜像和私服部署原理

 

私服原理
私服原理

 

 

3-2-1. npm配置优先级

 

npm配置的优先级
npm配置的优先级

 

 

4. Yarn理念破解依赖管理困境(nodejs是packge-lock.json,yarn是yarn.lock;synp工具可以后者转前者)

依赖的“嵌套地狱“:项目依赖树的层级非常深,不利于调试和排查问题,依赖树的不同分支里,可能存在同样版本的相同依赖。

这些包就是js代码包。

 

yarn的包获取流程及解析流程
yarn的包获取流程及解析流程

 

 

5. CI环境上的npm优化和工程化问题

 

6. 横向对比主流构建工具,了解构建工具设计考量

 

npm ci比npm install稳定快速
npm ci比npm install稳定快速

 

 

np配置文件和依赖讲解
np配置文件和依赖讲解

 

 

7. 横向对比构建工具

 

构建工具的评测指标
构建工具的评测指标

 

 

8. vite实现:从源码分析触发,构建bundlele工程

vite在开发环境下并没有打包和构建过程,是vue坐着尤雨溪产出。

 

vite原理和流程
vite原理和流程

 

 

9. core-j及垫片理念,设计一个polyfill(垫片/补丁)

polyfill:用社区上提供的一段代码,在不兼容某些新特性的浏览器上,使用该新特性。

方案1.手动打补丁
目前流行方案:babel-polyfill结合@babel/preset-env+userBuiltins(entry)+preset-env targets方案。

如果环境需要但是某个业务不需要polyfills可以使用@babel/preset-env+userBuiltins(usage)+preset-env targets
方案2.在线打补丁。

 

polyfills代码
polyfills代码

 

 

10. 梳理混乱的Babel(工具链),不再被编译报错困扰

 

babel插件能力
babel插件能力

 

 

11. 探索前端工具链生态,制定统一标准的babel-preet

 

babel-preet从一个公共库发生错误场景分析怎么处理公共库问题
babel-preet从一个公共库发生错误场景分析怎么处理公共库问题

 

 

12. 才能够0到1构建一个标准的公共库

UMD规范

 

构建的各个入口关系主要是浏览器和nodejs的不同决定用不同的入口
构建的各个入口关系主要是浏览器和nodejs的不同决定用不同的入口

 

 

13. 代码拆分和按需加载:缩减bundle ize

 

代码拆分和按循序加载
代码拆分和按循序加载

 

 

14. Tree Shaking摇树):溢出JS上下文未引用的代码

 

摇树流程和代码案例
摇树流程和代码案例

 

 

15. 如何理解AST实现和编译原理(AST Explore,acorn解析)

 

AST介绍和案例代码
AST介绍和案例代码

 

 

16. 工程化思维实现应用主题切换

 

主题切换案例
主题切换案例

 

 

17. 解析Webpack源码,实现自己的构建工具

 

打包器的实现过程
打包器的实现过程

 

 

18. 从编译到运行,跨端解析小程序多端方案

多端方案就是使用一种DSL 实现“write once,run everywhere”

 

小程序多端方案
小程序多端方案

 

 

19. 原生跨平台技术:移动端跨平台到Flutter的技术变革

 

Flutter的原理和体系
Flutter的原理和体系

 

 

20. 学习axio:封装一个结构清晰的Fetch库(请求库)

 

请求的问题和两种规范
请求的问题和两种规范

 

 

20-1. 请求库功能点:

  • 自定义headers添加
  • 统一断网/弱网处理
  • 接口缓存处理
  • 接口统一错误提示
  • 接口统一数据处理
  • 统一数据层结合
  • 统一请求埋点

 

功能设计和抽象粒度分析
功能设计和抽象粒度分析

 

 

20-2. axios设计之美

  • 在浏览器端,使用XMLHttpRequest发送请求
  • 支持Node.js端发送请求
  • 支持PromiseAPI,s使用Promise风格语法
  • 支持请求和响应拦截
  • 支持自定义修改请求和返回内容
  • 支持请求取消
  • 默认支持XSRF防御

拦截器思想:分层开发时借助拦截行为,注入自定义能力功能
适配器思想:可以支持浏览器和node.js不同请求方式。
代码案例

安全思想:在请求中携带cookie值。

 

20-3. 知识脑图

 

axios知识脑图
axios知识脑图

 

思考:axios如何取消一个请求?
ajax取消请求的方式有两种:一种是通过设置时间,超时自动断开,另一种我们可以调用XMLHttpRequest对象上的abort方法;而axios是通过cancelToken方法

 

21. 对比Koa和Redux:分析前端中的中间件理念

代码设计:聚焦中间件和插件化理念。
使用compose组合各个中间件逻辑(更像拦截器的各个拦截逻辑)。
koa是洋葱模型,express插件不是是基于回调的线性机制,不仅容易实现拦截处理逻辑。

Redux实现了一个compose方法完成了中间件的注册和串联。

 

中间件调用流程洋葱模型
中间件调用流程洋葱模型

 

 

22. 如何理解软件开发灵活性和高定制性

ES.next的proxy代理模式
装饰者模式:在不改变原2对象的基础上,对其对象进行包装和扩展,使原对象能够应对更加复杂的需求
AOP切面编程

面向对象,函数式思想相互对立互相补充;
纯函数:不能修改外部变量,不能调用Math.radom()方法以及发送异步请求等。
高阶函数:接受函数做参,返回另外一个函数;
curry化函数;反curry化。

 

设计模式函数式-对象编程知识脑图
设计模式函数式-对象编程知识脑图

 

 

23. 如何理解前端中面向对象的思想

javascript的new其实是为了模仿java,掩盖了javascript的原型继承思想。

 

23-1. new 关键字

  1. 创建一个空对象,这个对象将会作为执行new 构造函数之后,返回的对象实例。
  2. 讲上面创建的空对象的原型(proto),指向构造函数的prototype属性。
  3. 将这个空对象赋值给构造函数内部的this,并执行构造函数逻辑。
  4. 根据构造函数执行逻辑,返回第一步创建的的对象或者构造函数的显示返回值。
 

23-2. 类继承和原型继承的区别

  • 传统的面向对象语言的类继承,引发问题:
  • 紧耦合问题
  • 脆弱基类问题
  • 层级僵化问题
  • 必然重复性问题
  • 大猩猩-香蕉问题

 

类继承和原型继承的区别对比图
类继承和原型继承的区别对比图

 

 

23-3. 前端的面向对象脑图

 

前端面向对象知识图
前端面向对象知识图

 

 

24. 如何利用javascript实现经典数据结构

 

24-1. 8类数据结构

  • 数组
  • 堆栈
  • 队列
  • 链表Linked Lists
  • 图Graphs
  • 字典树Trie
  • 散列表(hash表)

基于数组连续存储特性:可以实现堆栈,队列
基于链表指向性:可以实现树,图
字典树和散列表使用查询比较广泛。

 

24-2. 图的bfs(广度优先)和dfs(深度优先算法)

  • bfs在于队列
  • dfs在于递归
 

25. 剖析前端中数据结构应用场景

 

25-1. 栈的应用场景

历史记录,undo/redo;线程调用栈;进制转换,括号匹配,栈混洗表达式求职等。
react context特性;

 

25-2. 队列的应用场景

宏任务/微任务;消息队列;
http1.1队头阻塞,因为同一个域名所有请求都是一个http连接,队头无响应阻塞。http2采用而金拇指分帧和多路复用,实现并行请求和响应解决。

 

25-3. 链表应用

刚开始使用stack reconciler调度算法。
局限性:每次递归都会在栈中添加一个同步帧,因此无法将遍历过程拆为粒度更小的工作单元,也就无法暂停组件的更新,并在未来某段时间恢复更新。
react核心算法Fiber实现就是链表,Fiber就是一个对象通过parent,children,sibling维护一个树形关系。Fiber模型就规避了stact的递归无法更新组件的局限。

 

25-4. 字典树

典型例子AutoComplete(自动填充)搜索,分类,ip地址检索,电话号码检索;一种搜索树(前缀树)插入和查询就是o(k),可就是字符串长度,消耗内存,空间换时间。

 

数据结构应用场景
数据结构应用场景

 

 

26. npm scripts:打造一体化的构建和部署流程

 

npm scripts和npm命令的关系
npm scripts和npm命令的关系

原理其实就是npm run调用系统 shell;脚本可以串行或并行执行。

 

 

26-1. lucas-scripts

npm scripts插件集合,通过Monorepo风格的项目,借助npm抽象“自己常用的”npm scripts脚本,以在多个项目中达到复用的目的。(tools without config 思想)

 

工具配置中问题及解决思路
工具配置中问题及解决思路

 

 

27. 自动化代码检查:剖析Lint工具和工程化接入&优化方案

 

27-1. prettier和Lint

  • pretty:代码美化风格
  • ESLint: code Linting 基于静态分析代码原理,找出代码反模式的过程,多数编程语言都有Linter,他们往往被继承在编译阶段,完成coding Linting的任务;javascript不具备先天编译流程往往会在运行时暴露错误,ESLint允许开发者在执行前发现代码错误或不合理的写法。
 

27-1-1. ESLint(.eslintrc文件配置)

  • 所有规则都插件化
  • 所有规则都可插拔(随时开关)
  • 所有设计都透明化
  • 使用Espree进行javascript解析
  • 使用AST分析语法

 

prettier和Lint区别和文件说明
prettier和Lint区别和文件说明

 

 

27-2. husky和lint-staged

husky就是git的一个钩子,在git进行到某一时段时,可以交给开发者完成某些特定的操作。
在整个项目上运行Lint会很慢,一般会对更改的文件进行检查,此时用到lint-statged

代码是非串行的,ESLint通过5个事件控制检测范围和粒度,是多条规则串联执行,核心原理就是事件驱动。

  • onCodePathStart
  • onCodePathEnd
  • onCodePathSementStart
  • onCodePathSementEnd
  • onCodePathSementLoop
 

27-3. 代码检查工具知识脑图

 

代码检查工具体系
代码检查工具体系

 

 

28. 如何设计一个前端+移动端离线包方案(NSR)

 

离线包方案介绍
离线包方案介绍

 

 

28-1. 离线包方案体系

 

离线包方案脑图
离线包方案脑图

 

 

29. 如何设计一个“万能”项目脚手架

脚手架:为了保证各施工过程顺利进行而搭设的工作平台,为了完成新项目的启动和搭建,能够帮助开发提示效率和开发体验。

  • vue/react 框架类脚手架
  • webpack等构建配置类脚手架
  • 混合脚手架
 

29-1. 命令行工具(原理和实现)

 

命令行工具nodejs开发实现
命令行工具nodejs开发实现

 

 

29-1-1. 命令行到万能脚手架

 

脚手架能力
脚手架能力

 

 

命令行工具到脚手架的案例脑图
命令行工具到脚手架的案例脑图

 

 

30. 同构渲染架构:实现一个SSR应用

同构应用时调用一个renderToString(React中)类似的API。
assets/bundle.js CSR架构下浏览器端脚本
assets/Client.js SSR架构下浏览器端脚本,衔接SSR部分
src/ 包含所有源码,Babel将会编译该文件内代码到views/目录;低版本node.js不支持esm规范所以执行:“babel”:"babel src -d views"

 

30-1. 实现一个建议SSR应用项目目录说明

  • src/components 中放react组件
  • src/redux/中放redux相关代码
  • assets/和media/中存放样式文件及图片
  • src/server.js和src/template.js是node.js环境相关文件。

 

csr和ssr客户端代码区别
csr和ssr客户端代码区别

 

同构实现了客户端和服务端代码统一,只需要编写一种组件,就能生成适用于服务端和客户端的组件案例。

 

30-1-1. 大部分情况下:服务端代码和客户端代码需要单独处理:

  1. 服务端根据请求路径,匹配页面组件;客户端通过浏览器地址匹配页面(如客户端通过window.location,而服务端没有window组件
  2. 打包差别(服务端不需要打包依赖的node模块和第三方模块,因为这些依赖已经安装在环境中了,可以直接引用)需要在webpack配置target:node并借助webpack-node-externals插件解决第三方依赖打包的问题
  3. 请求认证问题:某个请求依赖cookie表明用户信息,比如我的学习计划列表,这种情况服务端请求不同于客户端,不会有浏览器添加cookie以及其他header信息;解决服务端保留客户端页面请求信息,并在api请求时携带并透传这个信息。
  4. 样式问题:style-loader:不能使用,因为webpack loader会在编译时讲样式模块载入到HTML header中,服务端编译时不存在style-loader就会报错,通过使用iso-morphic-style-loader来实现,原理把css文件转换为对象,获取所有样式利用context api,在渲染页面组件时获取所有react组件的样式信息最终插入HTML字符串中。

 

同构的知识脑图
同构的知识脑图

 

 

31. 设计性能守卫系统:完善CICD流程

 

31-1. 如果页面渲染前有一个loading动画(监控指标):

LCP(larget contentful paint) 衡量页面加载体验,标示视口内可见的最大内容元素的渲染时间。
FCP:以loading动画出现的时间为准。
FID(First input delay):衡量可交互性,表示用户和页面进行首次交互操作所花费的时间,比TTI更加提前。
CLS(Cumulative Layout Shift):衡量视觉稳定性,表示页面的整个生命周期中,发生的每个意外的样式移动的所有单独布局更改得分的总和。

 

31-2. 监控守卫

 

31-2-1. 真实用户监控(RealUserMonitoring RUM)

基于真实用户访问应用情况,在应用生命周期内计算产出性能指标,并进行上报。一般搭配稳定的SDK,会给用户带来额外流量消耗,影响用户访问性能。

 

31-2-2. 合成监控(Synthetic Mointoring,SYN)

一种实验室数据,指在某个模拟场景中,通过工具搭配规则和性能审计条目,得到一个合成的监控报告,缺点,数据量小,模拟条件配置复杂,无法完全反应真实场景。
CD/CD pipeline就是合成守卫方案

 
31-2-2-1. Lighthouse原理介绍
  • Chrome DevTools
  • Chrome 插件
  • Node Cli
  • Node module

 

Lighthouse原理
Lighthouse原理

 

  • lighthouse会与浏览器建立连接并通过CDP与浏览器进行交互;
  • 通过lighthouse,我们可以自定义审计项并得到审计结果。
 
31-2-2-2. 性能守卫系统Pert-patronus

 

pert-partronus
pert-partronus

主要有以下指标:
FCP,Total Blocking Time;First CPU idle;TTI;Speed Index;LCP;

 

 
31-2-2-2-1. 真实反映用户情况考虑不确定因素和波动因素
  • 页面不确定性
  • 用户侧网络情况不确定
  • 终端设备不确定
  • 页面服务器不稳定性(小概率)
  • 性能体检服务的稳定性:在同一台机器上,如果不确定有其他应用服务,会影响性能体检服务的稳定性和一致性,不过预计影响不大,可以通过模拟网络环境和cpu能力,来保证性能体检服务的稳定和一致性。

 

优化方案
优化方案

 

 
31-2-2-2-2. 如何解决有“用户态”页面鉴权问题

对于有登录状态的页面,提供以下几种方案进行登录状态的性能服务:

  • 通过Puppeteer page.cookie,测试时通过script实现登录
  • 通过请求服务时,传递参数解决登录态问题

 

cicd性能监控体系
cicd性能监控体系

 

 

32. 实践打造网管:改造企业BFF(网关)方案

企业级BFF网管,微服务,Serverles概念,并实现代码;
BFF服务于前端的后端 逻辑分层:作为适配器能够更好地为前端服务,而传统业务后端只需要关注自己的微服务。

 

BFF特点
BFF特点

 

BFF痛点:

  • 需要解决谁来开发的分工问题
  • 链路复杂
  • 资源浪费

BFF数据处理:

  • 数据聚合和裁剪
  • 序列化格式转换
  • 协议转换
  • Node.js调用RPC

BFF 流量处理:

  • 请求分发能力,代理能力
  • 可用性保障

可以有良好的限速,隔离,熔断降级,负载均衡和缓存能力。

BFF网关层的原则:

  • BFF层不需要完成全部的校验逻辑,部分业务校验应该留在微服务中完成
  • BFF需要完成必要的减产,比如请求头检查和必要的数据消毒
  • 合理使用Content-Security-Policy
  • 使用Https/HSTS
  • 设置监控报警以及调用链追踪能力
  • 关注依赖包安全问题

 

权限和校验设计
权限和校验设计

 

 

32-1. 实现一个lucas-gateway(BFF)

如何设计一个扩展性良好的BFF层?以灵活支持上述需要考量的问题

  • 插件化:如logger等也可以接受第三方插件
  • 中间件化:sso,限流熔断等策略。

fork了jkybernees的fast-gateway:设计

  • fast-proxy(基本反代理)
  • @polka/send-type(中间件)
  • http-cache-middleware(缓存)
  • restana(Hooks)

负载均衡:proxyHandler支持req,res,req.url,proxy,proxyOpts等参数。

 

BFF网管方案体系
BFF网管方案体系

 

Serverless:无服务器架构,它的弹性伸缩,按需使用,无运维是未来的方向。

Serverless+BFF=SFF

 

33. 实现高可用:使用Puppeteer生成性能最优的海报系统

以Puppeteer代表的Headless浏览器:Puppeteer是一个node库,他提供了一整套高级API,通过devtools协议控制谷歌内核浏览器,正如其翻译“操纵木偶的人”一样可以通过该库直接控制浏览器,模拟大部分用户操作进行UI测试或者作为爬虫访问页面来搜集数据。
1.7.0版本分Puppeteer和Puppeteer-core两个模块;后者默认不会下载chrome,同时会忽略所有puppeteer_* 环境变量

 

puppeteer应用场景
puppeteer应用场景

 

符合27讲的同构渲染架构,最大好处是不需要对项目代码进行任何调整,却能获取到SSR应用的数据

 

优化角度
优化角度

 

  • 和JEST结合通过断言能力实现一个端到端测试系统
  • 和Lighthouse结合实现简单性能守卫。
 

33-1. Puppeteer实现海报Node.js服务

 

海报服务链路
海报服务链路

 

 

代码流程和线程池优化
代码流程和线程池优化

 

 

puppeteer体系
puppeteer体系

 

 

34. 结束语2 项目基建和架构,个人ji价值和方向

 

34-1. 基建和架构

 

项目基建架构如何写好库
项目基建架构如何写好库

 

 

库开发预期和处理
库开发预期和处理

 

 

34-2. 价值和方向

 

34-2-1. 遇见的问你提

  • 看不见的“黑天鹅”
    新技术的爆发,技术的更新换代:对于菜鸟来说弯道超车,对于有经验的是颠覆和变革,核心价值是逻辑,分析,数据,算法等抽象能力。

  • 被我们视而不见的“灰犀牛”:职业进阶

探索生命的种种可能!!

posted @ 2022-06-04 09:59  编程未来  阅读(988)  评论(0编辑  收藏  举报