0%

是什么

  • 犹如一把利器,帮助前端攻城狮披荆斩棘拿下一个个需求。
  • 犹如一部电影,总是能带给前端研发惊喜提升工作幸福感。
  • 犹如一盏明灯,在繁杂的前端生态中指引方向。
  • 我理解它的本质是一种编程思维

编程思维

React 使用基于组件的声明式编程思维。

组件是抽象的概念,它可以表示视图、样式甚至是逻辑,网页通常由许多视图构建而成,任意网页均能分解成多个组件,组件可以分解成子组件。使用 React 简洁清晰得可预测得自顶而下得声明组件的关系、状态、行为逻辑,从而构建出用户界面。

做了什么

核心之一 ReactComponent & ReactElement & instances

React.createElement 高度类似于 document.createElement,输入类型(字符串或ReactComponent)、props、子 Element(s),输出 ReactElement 作为原子单元构成 Virtual DOM。

ReactElement 本质上是 Javascript Object, 其实与 HTMLElement 大同小异,它向开发者描述一个 Element 或 Element tree 的基本“面貌”。换句话说 ReactElement 等同于 light HTMLElement。

React 通过 ReactElement 的描述生成 instances 渲染至屏幕

核心之二 Virtual DOM & Reconciliation & Update

Virtual DOM 高度类似于 DOM,是一颗有序分层结构的树,描述多个 Elements 的联系,或相邻或嵌套或其他,若把联系当作线, Element 当作点,点和线构成“骨架”,点线越多构成的“骨架”越完整。

React 应用总是从任一特定状态过渡至另一个,并同时生成一颗新树。为降低开销提高应用性能,React 使用 Reconciliation 对比新/旧树差异从而决定哪些部分需要改变,在浏览器应用中,这些改变被翻译为 DOM 操作的集合,最后有序执行,完成一次 Update。

核心之三 React Fiber

React 团队花两年时间重新实现核心算法,该实现晦涩难懂。据核心研发人员介绍,React Fiber 的设计目标是增强对动画、布局、手势的适用性,其主要功能是增量渲染:能够将渲染工作分解成多块并分散到多个帧中。

值得一提的是 Fiber 架构重写了 reconciler,主要差异在于使用 keys 提升列表的渲染性能。

其他

React 抹平浏览器部分 Web APIs 的差异性并做了一些友好的封装比如监听器的语法,相比 DOM0 级事件 key 从小写改成驼峰,value 从传递字符串变成传递方法,封装禁止默认行为和阻止事件冒泡等等。

使用 React 的优势

终极目标是提升生产力

  • 可复用的组件,减少冗余代码块提高可维护性
  • 视图、样式、逻辑、状态都可抽象成组件,形成统一的编程思维,降低理解成本提高协作效率
  • 跨端能力
  • 实现 Virtual DOM,减少 DOM 操作的开销从而提高 Web 应用的性能
  • 相比 html + css + js,纯粹的 js 使开发者能够无所拘束的组织代码,充满想象空间

小结

React 构建用户界面,它不是“万金油”,它不处理 router、canvas、audio/video、Web RTC、fetch 等等 Web APIs,对于构建富交互 SPA/MPA 而言是不够的,我理解这是促使 React 社区蓬勃发展的原因之一。React 真香。

总结

Class API 唯一的优势是熟悉,但使用 Function 可提供给开发者更多裨益。受益于 React Hooks 但从根本上不同的是 Function-Based API 扎根于 Vue 自身的响应式系统。另外这些 APIs 解决了许多 React Hooks 上的使用问题。

React Hooks 使用问题有:

  • 在每一次 render 过程中,setup() function 只调用一次,而 React Hooks 会重复调用,前者减少 GC 压力

核心理念

  • 更优雅的逻辑复用(使用setup() function)

    优雅之余还能解决问题。对于 2.x 逻辑复用通常使用 mixin、HOC、Renderless components(通过作用域插槽),而使用上述存在三个问题分别是属性来源不清楚、命名空间冲突以及性能(HOC 和 Scoped slots 需要额外有状态的组件实例开销)。

  • 更好的代码组织

    根据功能粒度来组织代码,相比于 options API,代码更内聚。

  • 更好的类型推断

    function 天生是类型友好的,因为方法的 prototype 已经实现了完整的类型支持。

  • 缩小打包体积

    在标准的压缩规则下,函数与变量名可被缩短然而对象或类方法与属性不行。

穷游

主打旅游社区生态建设,定位旅游交友平台。很适合单身的朋友。而且适合半自助制作攻略的朋友。

  • 优势
  1. 对已录入的旅游城市有详细的景点热门排序与详情(基础信息、开放时间、地址、门票等)、美食排序与详情、购物排序与详情、活动排序与详情
  • 不足
  1. 酒店预订比马蜂窝还差,千万不要用。
  2. UI和功能似乎都是没马蜂窝的好呀

马蜂窝

适合不想被跟团游坑但没时间没经验做攻略的人,且有许多旅游相关贴心服务呦!

  • 优势
  1. 目的地多(比如泰国苏梅岛)
  2. 功能板块很多(比如攻略、去旅行、游记)
  3. 去旅行板块有许多实用服务(比如定制游、高铁游、邮轮游、周边游、境内外用车、签证、保险、随身WIFI与境外电话卡、交通卡)
  4. 富足驴友社区生态(比如vlog等)
  • 不足
  1. 酒店预订接入的平台比较二流比如同程艺龙、有鱼等
  2. 订机票服务不稳定且价格比去哪儿要高,实测

鱼游(内容少,服务少,功能少)

什么是向量

向量是由方向和长度构成的量。通过由箭头表示。

什么是span

The set of all possible vectors that you can reach with a linear combination of a given pair of vectors is called the span of those two vectors

释义

v向量与w向量全部线性组合构成的向量集合称为“张成的空间”

av + bw 其中a,b都在实数范围内变动

什么是基

The basis of a vector space is a set of linearly independent vectors that span the full space

向量空间的一个基是张成(铺开)该空间的一个线性无关向量集

什么是矩阵

矩阵每一列表示一个维度的向量从而描述了一组基向量。矩阵是一种基于基向量改变来描述向量空间线性变换的语言。

什么是线性无关?如何说明向量v,向量w,向量u线性无关

科学家推荐的理解是:存在且仅存在一组标量组合[0,0,0]使得三个向量的加和为0向量时,说明三个向量线性无关
适用于教学目的的解释是:不存在任何一组标量组合[a,b]使的两个向量的加和等于第三个向量,说明三个向量线性无关

什么是线性变换

总结来说,线性变换应当看作是“保持网格线平行且等距分布”的变换。线性变换有两个特征,其一是直线仍是直线,其二是原点仍是原点。

变换和函数差不多,两者都是input -> output,不过前者有一种运动的概念。

线性变换矩阵的空间几何意义

线性变换实质上变换的是向量空间的基向量,向量空间中的任意一点都可通过变换后的基向量矩阵计算得出。
基向量矩阵,也可以理解为变换矩阵,是指线性变换之后基向量(i帽,j帽)的落脚点,即基向量从[[1, 0], [0, 1]]线性变换[[0, -1], [-1, 0]]。

单块应用

所有功能都揉于一个容器中,可以简单有效的配合事务做到业务数据的ACID,但是内部相互之间依赖关系较复杂,耦合度较高,存在不易拆解、不易扩展、不灵活等弊端

微服务关键设计原则

  • 微服务是一系列根据业务流程拆分出来的业务单元
  • 它们是一系列包含了业务逻辑并能采用简单信道和协议与之进行通信的智能端点
  • 根据设计,微服务架构是去中心化的,旨在构建强壮,弹性的系统应用

关键好处

  • 弹性。系统处理变化的能力。
  • 可伸缩性。对某个微服务单独做cluster应付高负载强计算而不牵动其他模块。
  • 技术多样性。秉承高内聚,低耦合的原则,每个微服务对外暴露接口,但内部实现完全透明,也就是内部说可以用nodejs、erlang、golang等等语言实现。
  • 可替换性。指替换系统中某个模块而不影响系统的能力。有利于减少解决技术债务
  • 独立性。小而独立,分而治之。
  • 易于部署。微服务是自治的工作单元,可单独部署与升级。

SOA

面向服务架构,这也是一种软件设计原则。大体上,SOA与微服务架构是非常想想的。那么他们之间的区别是什么呢?

  • 微服务是细粒度的SOA组件,它们是关注点更窄的轻量级服务
  • 推崇执行标准不同。SOA未推崇,以J2EE技术栈中的ESB举例;而微服务推崇使用http
  • 领域模型。在微服务架构中,每个微服务通常自治数据库,并且隔离领域模型;而在SOA架构中各业务组件通常IO同一个大型数据库,并且业务组件之间共享领域模型。

模块化的基本原则(SOLID)

‘use strict’

  • 单一职责原则。尽可能的只处理某一范围的逻辑功能,如字符串操作、二次封装的http请求模块
  • 开放封闭原则。对功能扩展开放,对修改公用代码关闭
  • 理氏替换原则。
  • 接口分离原则。JS与C#、Java不同,它不是一门面向接口的语言。但是可通过module.exports变量将公用函数暴露给其他模块使用。
  • 依赖倒置原则(反转控制和依赖注入)。依赖倒置指模块间应依赖于抽象,反转控制指创建某个类实例的逻辑移交给某IoC容器控制,依赖注入指在IoC容器中对类实例配置所需依赖的操作。

服务器DevOps工具

  • chef. infrastructure automation
  • inspec. compliance automation
  • habitat. application automation

  • 适用群体

有一定前端知识的用户群体

  • MSE概述

结论是MSE提供了实现无插件且基于web的流媒体的能力。可以支持比如自适应码率,精确控制时间的H5直播和点播功能。业界比较出名的有DASH以及HLS协议,这两种协议都基于http协议,有较好的防火墙穿透功能(只要防火墙不拦截80与443端口流量,而一般来说都不会拦截),HLS对苹果设备极度友好而DASH跨平台兼容性更好,不过这两者劣势都是实时性不好通常延迟有好几秒之长,取而代之的一般是基于web技术有webRTC以及非web技术RTP。

  • MediaSource概述/含义

属于Media Source Extensions(MSE)标准中的一个接口,每一个MediaSource实例代表了一个媒体源数据应用于HTML媒体元素比如<video/><audio/>,通常附着于HTML媒体元素在用户代理中播放。

  • 本质

MediaSource = EventTarget + SourceBuffer + 其他属性比如说duration和readyState + 其他方法比如说isTypeSupported

  • 用处

高级的音视频媒体流播放方式代替传统URL类型

  • 用法

    import React, { Component } from “react”;
    import webmUrl from ‘./3.webm’;

    class VideoPlayer extends Component {
    videoDom;
    getUserMedia() {

    return navigator.mediaDevices.getUserMedia({ video: true, audio: true });

    }
    play = (url, mimeType = “webm”) => {

    let mimeCodec, mediaSource;
    if (mimeType === "webm") {
      mimeCodec = 'video/webm; codecs="vorbis, vp8"';
    }
    
    const sourceOpen = () => {
      // 新增mediaSource对象
      let sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
      fetch(url, {
        responseType: 'arraybuffer'
      }).then(data => data.arrayBuffer()).then(buffer => {
        sourceBuffer.addEventListener("updateend", () => {
          if (mediaSource.readyState === "open") {
            mediaSource.endOfStream();
          }
          this.videoDom.play();
        });
        sourceBuffer.appendBuffer(buffer);
      });
    };
    
    // 检查可用性
    if ("MediaSource" in window && MediaSource.isTypeSupported(mimeCodec)) {
      mediaSource = new MediaSource();
      this.videoDom.src = URL.createObjectURL(mediaSource);
      mediaSource.addEventListener("sourceopen", sourceOpen);
    } else {
      console.error("Unsupported MIME type or codec: ", mimeCodec);
    }

    };
    componentDidMount = () => {

    this.play(webmUrl);

    };
    render() {

    return (
      <div className="recorder-wrapper">
        <canvas style={ { width: 0, height: 0 }} />
        <video
          ref={dom => (this.videoDom = dom)}
          style={ { width: 400, height: 400 }}
        />
      </div>
    );

    }
    }

    export default VideoPlayer;

  • index.js:1509 Uncaught Error: The error you provided does not contain a stack trace.

    at B (index.js:1509)
    at G (index.js:1816)
    at index.js:1831
    at index.js:1850
    at index.js:1343

    B @ index.js:1509
    G @ index.js:1816
    (anonymous) @ index.js:1831
    (anonymous) @ index.js:1850
    (anonymous) @ index.js:1343
    stream-media.js:25 Uncaught (in promise) DOMException

根因是该媒体文件不兼容MSE标准(可能原因是容器格式不兼容也有可能是音视频编码器不兼容),请check mimeCodec和真实视频完全一致,要查看视频容器的源信息需要借助ffmpeg等三方工具。

  • Tips

ffmpeg -i test.webm

记录学习webgl踩坑

当gl.drawElements报警告时,请check未出现以下情况,如出现请先解决

  • 索引数组中的最大值 * 每个顶点所占浮点数个数(包含图元所需顶点数和Color)> 顶点数组长度

当gl.drawArrays报警告时,请check未出现以下情况,如出现请先解决

  • 第二个参数Count数 * 每个顶点所占浮点数个数(包含图元所需顶点数和Color) > 顶点数组长度

当gl.drawElements和gl.drawArrays都没报错,但仍没有画面时,请check

  • Color值从生成直到FragmentShader使用到该Color值前有没有做归一化或?换句话说就是可能被裁剪了。顶点值也是如此。
  • 如果是用gl.TRIANGLE画几何体,注意是否画的是正面(FRONT_FACE)即逆时针绘制。换句话说可能是gl.CULL_FACE。

其他注意点

  • attribute属性限制符只适用于顶点着色器而不适用于片元着色器
  • engine内部代码注意不要出现循环依赖,如出现需及时修改避免留坑

照相机

  • 正交照相机必须要使用aspect,否则渲染出来的图形会变形。

snowy框架使用注意点

  • 自定义geometry类中的positions属性必须归一化
  • indices一般都要UInt8Array类型并且必须和drawElements的第三个参数对齐
  • 光源颜色无需归一化且目前仅支持RGB,不支持HSL等

Common Checks

  • 坚持使用 transform 和 opacity 属性更改来实现动画。
  • 使用 will-change 或 translateZ 提升移动的元素。
  • 避免过度使用提升规则;各层都需要内存和管理开销。

Several Questions

  • 有多少layers?合理的数量是多少?每一个layer的原因。
  • 在不通电的多倍屏(如13寸MBP)的匿名模式窗口中打开查看Layers面板。每个layer渲染一帧耗时?确保所有layer加起来小于15ms。
  • 在做动画时,有多少个layer重新绘制?考虑减少不必要的layer重新绘制或者复杂的layer拆解。

Performance Targets

  • 每个layer力争4 - 5毫秒的时间(尤其针对于可能要做的Admin移动端来说尤为重要)。
  • 每个稍大(绘制时间超过1ms)layer都具有必要性,否则销毁。
  • 动画过程中,通过观察Layers和Animation面板确定每个layers重绘都是必要的。
  • 如果Layers面板中的layer绘制时间求和的结果在15ms以内,上述就都不必check了。
  • 在Performance面板中一定一定不要存在forced layout,如果有请消灭它。

Other Actions

  • 坚持仅合成器的属性和管理层计数,否则使用FLIP原则使得从开销更大的属性重新映射为变形和透明度的更改。

Refs

  • Layers面板使用方式查漏补缺
  • FLIP Principle
  • Inspect Your Animation
  • 降低绘制复杂度、减小绘制区域
  • 坚持仅合成器的属性和管理层计数

菜单栏收缩动画性能瓶颈分析案例

  • 动画属性不符合预期
  • 重绘制layers完全超乎预期
  • Antd Loading提升一个Layer而且占用内存超预期很多
  • 没必要的layer开销超预期很多
  • 同一个DOM却提升两个layer
  • 动画过程中,.basic-layout-container未提升新layer,且提升之后Layer出现闪动(似乎是layer销毁却又重新创建)
  • 降低绘制复杂度
  • 减小绘制区域(Antd Loading没必要随父元素展开,用绝对定位或者定高来限制绘制区域,水印亦是如此)

prepare

  1. Shadowsocks家族vpn软件,亲测RocketVPN不可用。因为命令行连接谷歌域名必须要建立https连接,并且会失败。解决方案是命令行翻墙。至少git和curl需要翻墙。
    • git config –global https.proxy localhost:1087
    • /.bashrc或者/.zshrc中设置curl全局代理。即尾行键入export https_proxy=http://localhost:1087
  2. 充足的时间。因为chromium在Google Git上有12G+,clone非常慢,fetch –tags比较慢,另外sync非常慢。
  3. 足够的HD空间。因为需要Xcode(解压后12G+),Chromium源码(12G+)。
  4. 需要保证(不知道怎么保证但就是要)。如果macOS版本和Xcode版本存在兼容性问题,会卡在gn gen out/Default(第8步)。
  5. Install Xcode, launch it, accept the license agreement, and run sudo xcode-select -s /path/to/Xcode.app to continue.

steps

官方教程不全,应该是编译最新版本且环境比较理想的情况下。因此整理一条在mac下编译M68版本且能跑通的操作序列。

*** 请务必确认终端已经科学上网。

  1. mkdir chromium && cd chromium
  2. fetch –nohooks chromium(后续再执行hooks)
  3. git fetch –tags
  4. git checkout -b release/68 68.0.3440.92
  5. cd ..
  6. gclient sync –with_branch_heads –jobs 16
  7. gclient runhooks (如果第6步提示Running hooks: 100% (64/64), done.则可省略此步骤)
  8. gn gen out/Default
  9. autoninja -C out/Default chrome

须确保每一条命令无Error。Warning可忽略。

Chromium Build教程传送门 前人踩坑,后人乘凉

我卡在macOS SDK(10.14.3)和Xcode(10.2 Beta3)版本不兼容,夭折。

what?

贝塞尔曲线(bezier curve),由线段和节点组成,节点是可拖动的支点,线段像可伸缩的皮筋。是计算机图形学中相当重要的参数曲线。

cubic-bezier curve 公式

$$B(t)=P_0(1-t)^3+3P_1t(1-t)^2+3P_2t^2(1-t)+P_3t^3, 0 \leq t \leq 1$$

Features

  1. 起始于 P0 结束于 Pn 的曲线,即所谓的端点插值法
  2. 曲线的起始点(结束点)相切于贝塞尔多边形的第一节(最后一节)
  3. 一条曲线可在任意点切割成两条或任意多条子曲线,每一条子曲线仍是贝塞尔曲线

升阶

n 次贝塞尔曲线可以转换成完全相同的 n+1 次贝塞尔曲线。

cubic-bezier 曲线在浏览器 timing-function 中的应用