# 编译

代码变成可执行文件

# CI

持续集成:当代码仓库代码发生变更,就会自动对代码进行测试和构建,反馈运行结果。

# CD

持续交付:也会被解释成持续部署,持续交付是在持续集成的基础上,可以将集成后的代码依次部署到测试环境、预发布环境、生产环境中

# 构建

先编译这个,还是先编译那个(即编译的安排),叫做构建 (opens new window)(build)。

# 测试驱动开发

在开发之前先写测试文件

# 测试

那些项目适合自动化测试?

  1. 公共类库的开发
  2. 中长期项目的迭代/重构
  3. 引用了不可控的第三方依赖

# 单元测试

单元测试是最容易实现的:代码中多个组件共用的工具类库、多个组件共用的子组件等。

通常情况下,在公共函数/组件中一定要有单元测试来保证代码能够正常工作。单元测试也应该是项目中数量最多、覆盖率最高的。

目标比较流行的库:

  1. jest
  2. mocha

# 集成测试

成测试通常被应用在:耦合度较高的函数/组件、经过二次封装的函数/组件、多个函数/组件组合而成的函数/组件等。

集成测试的目的在于,测试经过单元测试后的各个模块组合在一起是否能正常工作。会对组合之后的代码整体暴露在外接口进行测试,查看组合后的代码工作是否符合预期。

# UI测试

UI 测试(UI Test)只是对于前端的测试,是脱离真实后端环境的,仅仅只是将前端放在真实环境中运行,而后端和数据都应该使用 Mock 的。

# e2e测试

端到端测试(E2E Test)则是将整个应用放到真实的环境中运行,包括数据在内也是需要使用真实的。

# 组件测试

# 自动化测试

#

# env

环境,比如env文件就是环境变量文件,用于服务端进程。

# Dapp

去中心化应用,Dapp不一定需要在区块链网络上运行。普通的前端页面运作方式:前端 > API > 数据库,Dapp的网站:前端 > 智能合约 > 区块链

# DevOps

开发、运维

# monorepo

monorepo(monolithic repository),与multirepo相对,分别是单代码仓库与多代码仓库(one-repository-per-module)

# 优点

# 缺点

# 工作流

# 配置文件

eslint、babel、tsconfig等配置文件都放在根目录。子包如果有需要,可以通过extend引用:

{
  "extends": "../../.eslintrc",
}

# scripty

统一命令脚本,通过将scripts定义在文件中,这样达到了复用脚本的目的和像写代码一样写脚本。

目录结构:

├── package.json
├── .eslintrc
├── scirpts/ # 这里存放所有的脚本
│   │   ├── packages/ # 包级别脚本
│   │   │   ├── build.sh
│   │   │   └── test.sh
│   └───└── workspaces/ # 全局脚本
│           ├── build.sh
│           └── test.sh
└── packages/
    │   ├── tsconfig.settings.json
    │   ├── .babelrc
    ├── @mono/project_1/
    │   ├── index.js
    │   ├── .eslintrc
    │   ├── .babelrc
    │   ├── tsconfig.json
    │   └── package.json
    └── @mono/project_2/
        ├── index.js
        ├── .eslintrc
        ├── .babelrc
        ├── tsconfig.json
        └── package.json

子项目的package.json

{
  ...
  "scripts": {
    "test": "scripty",
    "lint": "scripty",
    "build": "scripty"
  },
  "scripty": {
    "path": "../../scripts/packages" // 注意这里我们指定了 scripty 的路径
  },
  ...
}

# 导入远程仓库

lerna import只会导入本地的项目,并且不支持导入项目的分支和标签。使用tomono来解决这个问题

# SSR

Server Side Rendering服务端渲染。

什么是SSR友好?以vue3为例子

  1. 服务端响应性。服务端渲染是不需要响应性的,所以剥离响应性可以提供更好的性能

  2. 生命周期钩子。某些副作用,比如setInterval,应该被放在生命周期钩子中执行,否则它会一直存在

  3. 访问平台特有api。不要没有限制的使用平台特有api,比如node internal package和window

  4. 跨请求状态污染,服务端共用状态问题,需要做区分

  5. 激活异常。预渲染的 HTML 的 DOM 结构不符合客户端应用的期望,就会出现激活异常。在大多数场景中,这是由于浏览器原生的 HTML 解析行为试图纠正 HTML 字符串中的非法结构,比如<p><div>hi</div><p>会被渲染成<p></p><div>hi</div><p></p>当 。Vue 遇到激活异常时,它将尝试自动恢复并调整预渲染的 DOM 以匹配客户端的状态。这将导致一些渲染性能的损失,因为不正确的节点被丢弃,新的节点被加载,

  6. 自定义指令。大多数的自定义指令都包含了对DOM的直接操作,所以会在ssr时被忽略,可以使用 getSSRProps 指令钩子:

    const myDirective = {
      mounted(el, binding) {
        // 客户端实现:
        // 直接更新 DOM
        el.id = binding.value
      },
      getSSRProps(binding) {
        // 服务端实现:
        // 返回需要渲染的 prop
        // getSSRProps 只接收一个 binding 参数
        return {
          id: binding.value
        }
      }
    }
    

# 缺点

  1. 需要一直占用服务,占用服务器资源
  2. 多个服务器时加载速度与cdn相比,比较慢。
  3. 较高的学习成本
  4. 部分生命周期不可用。

# 优点

  1. 更好的seo
  2. 更快的首屏渲染

# SSG

Static Site Generation,静态网站生成,也称为预渲染

# 缺点

1.渲染大量页面时比较耗时

# 优点

  1. 当有大量静态内容时,使用服务去生成相同的内容是很浪费的行为。使用ssg可以预先把静态内容生成,其他动态内容由客户端渲染,这样就减轻了服务端渲染的负担。
  2. seo友好
  3. 用户始终通过cdn加载页面核心内容,加载速度快
  4. 由于每次都是全站渲染,所以网站的版本可以很好的与 Git 的版本对应上,甚至可以做到原子化发布和回滚。

# ISR

Incremental Site Rendering,增量式的网站渲染,用于解决SSG全量预渲染的问题。

1、关键性的页面(如网站首页、热点数据等)预渲染为静态页面,缓存至 CDN,保证最佳的访问性能;

2、非关键性的页面(如流量很少的老旧内容)先响应 fallback 内容,然后浏览器渲染(CSR)为实际数据;同时对页面进行异步预渲染,之后缓存至 CDN,提升后续用户访问的性能。

# 缺点

  1. 对于没有预渲染的页面,用户首次访问将会看到一个 fallback 页面,此时服务端才开始渲染页面,直到渲染完毕。这就导致用户体验上的不一致
  2. 对于已经被预渲染的页面,用户直接从 CDN 加载,但这些页面可能是已经过期的,甚至过期很久的,只有在用户刷新一次,第二次访问之后,才能看到新的数据。对于电商这样的场景而言,是不可接受的(比如商品已经卖完了,但用户看到的过期数据上显示还有)。

# 优点

  1. 减少打包时间

# DPR

Distributed Persistent Rendering,分布式的持续渲染。DPR 本质上讲,是对 ISR 的模型做了几处改动,并且搭配上 CDN 的能力:

  1. 去除了 fallback 行为,而是直接用 On-demand Builder (opens new window)(按需构建器)来响应未经过预渲染的页面,然后将结果缓存至 CDN;
  2. 数据页面过期时,不再响应过期的缓存页面,而是 CDN 回源到 Builder 上,渲染出最新的数据;
  3. 每次发布新版本时,自动清除 CDN 的缓存数据。

# 缺点

  1. 新页面的访问可能会触发 On-demand Builder 同步渲染,导致当次请求的响应时间比较长;
  2. 比较难防御 DoS 攻击,因为攻击者可能会大量访问新页面,导致 Builder 被大量并行地运行,这里需要平台方实现 Builder 的归一化和串行运行。

# lowcode

通过配置文件来编写页面或者拖拽方式完成页面的编写,结构推荐:

  1. label,文本
  2. props,底层组件属性
  3. type,组件类型
  4. on,组件事件

# 搭建方案

1 . 拆分显示组件和编辑的组件的逻辑,比如单独设置viewedit选项来处理数据。

# 中台

多个项目共用部分提取成中台,具体介绍:https://juejin.cn/post/6844903957693726727#comment

# 参考

  1. 新一代Web建站技术栈的演进:SSR、SSG、ISR、DPR都在做什么? (opens new window)