从功能上看,React 16 规划中有 4 个关键特性:
其中,Concurrent Mode(之前叫Async Rendering)无疑是最值得期待的东西,或将引领变革(合作式调度机制可能泛化成为浏览器能力)
单从形式上看,Hooks 是对函数式组件的增强,使之能与类组件平起平坐,甚至(期望)取而代之。实质意义在于进一步将更多的函数式思想引入到前端领域,比如 Effect、Monad 等。算是在提出v = f(d)的 UI 层函数式思路之后,在这条路上的进一步探索
Suspense 在Code Splitting场景已经露过面了,主要贡献在于用户体验与开发体验上。Data Fetching 的场景类似,在提升开发体验(统一数据请求及缓存方式)的同时,兼顾用户体验(显示 Loading)。而 SSR 场景下的 Suspense 能力则与前两种不同,考虑更多的是页面加载性能与用户体验之间的平衡,期望通过服务端渲染与客户端渲染的配合(Hydration),让页面尽快达到真正可用的状态
Modernizing React DOM 则是一项针对 React DOM(6 年)历史遗留问题的重构计划,代号 React Fire,旨在简化实现并看齐现代浏览器 DOM 机制,比如去掉事件系统这层不必要的抽象,因为现代浏览器环境下不再需要这些 2013 年的 polyfill 了
Concurrent Mode 意味着非阻塞式渲染:
Concurrent Mode lets React apps be more responsive by rendering component trees without blocking the main thread.
P.S.Concurrent Mode 之前叫做 async mode,改名是为了突出与其它异步渲染技术不同,有优先级调度的概念,类似于分时操作系统并发执行多道程序的能力
对于计算密集(CPU-bound)型任务而言,Concurrent Mode 带来的非阻塞式渲染能力,能在渲染大组件树的同时,保证应用的交互响应能力(不至于卡死),是React 愿景中很大的一块
具体的,Concurrent Mode 下允许中断耗时的渲染流程,让主线程有机会从中解放出来处理更高优的事情:
It is opt-in and allows React to interrupt a long-running render (for example, rendering a new feed story) to handle a high-priority event (for example, text input or hover).
还能配合 Suspense 跳过不必要的 Loading 状态(网络足够快的话,不用再闪个 Loading):
Concurrent Mode also improves the user experience of Suspense by skipping unnecessary loading states on fast connections.
并且,Concurrent Mode 特性所依赖的合作式调度机制,将来可能会由浏览器提供原生实现(已经在与 Chrome 团队合作了)
P.S.关于调度器的更多信息,见cooperative scheduling
React & React DOM 16.x(未发布)
Hooks 让函数式组件也能拥有状态、生命周期等 Class 组件特性(如 state, lifecycle, context, ref 等等):
Hooks let you use features like state and lifecycle from function components.
此外,还提供了一种跨组件复用状态逻辑的能力,不必再与组件树结构嵌套关系强耦合:
Hooks let you use features like state and lifecycle from function components. They also let you reuse stateful logic between components without introducing extra nesting in your tree.
例如:
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
这就是函数式组件的“状态”,context、ref、组件实例变量等都以类似的 Hook 方式提供了支持,因此函数式组件拥有了与 Class 组件几乎相同的表达力
更进一步地,Hooks 被寄予厚望,期望成为 React 组件的基本形式(作为 Class 组件的替代选项):
In the longer term, we expect Hooks to be the primary way people write React components. Our goal is for Hooks to cover all use cases for classes as soon as possible.
但是,大费周章地增强函数式组件不只是为了多一种选项,主要作用在于:
收益体现在 2 方面:
P.S.注意,提出 Hooks 不是为了废弃掉 Class,但在 Hooks 广泛应用之后,可能会把 Class 支持拆分到单独的 package 里,以减少 bundle 体积:
Hooks don’t deprecate classes. However, if Hooks are successful, it is possible that in a future major release class support might move to a separate package, reducing the default bundle size of React.
React & React DOM v16.8.0
Suspense 就是让 UI 挂起等待别的东西,基本机制是挂起渲染并显示个降级效果(suspending rendering and showing a fallback):
Suspense refers to React’s new ability to “suspend” rendering while components are waiting for something, and display a loading indicator.
2 个目标:
Our longer term vision for Suspense involves letting it handle data fetching too (and integrate with libraries like Apollo). In addition to a convenient programming model, Suspense also provides better user experience in Concurrent Mode.
通过React.lazy
懒加载组件,从而实现组件(树)粒度的代码拆分。例如:
// This component is loaded dynamically
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<React.Suspense fallback={<Spinner />}>
<div>
<OtherComponent />
</div>
</React.Suspense>
);
}
P.S.关于 React 代码拆分的更多信息,见React Suspense
React & React DOM v16.6.0
类似于 Code Splitting,也希望为数据请求的场景提供一种方便的通用方案:
We’d like to provide officially supported ways to use it for data fetching too.
例如让 UI 等待数据回来,在此期间通过React.Suspense
显示 Loading:
// React Cache for simple data fetching (not final API)
import {unstable_createResource} from 'react-cache';
// Tell React Cache how to fetch your data
const TodoResource = unstable_createResource(fetchTodo);
function Todo(props) {
// Suspends until the data is in the cache
const todo = TodoResource.read(props.id);
return <li>{todo.title}</li>;
}
function App() {
return (
// Same Suspense component you already use for code splitting
// would be able to handle data fetching too.
<React.Suspense fallback={<Spinner />}>
<ul>
{/* Siblings fetch in parallel */}
<Todo id="1" />
<Todo id="2" />
</ul>
</React.Suspense>
);
}
最终愿景是由网络库来提供上层封装,让大多数数据请求都走 Suspense
react-cache对 Suspense for Data Fetching 设想提供了实验性的实现
目前尚处于非常不稳定的阶段(甚至缺少缓存过期之类的基础特性),暂时不建议使用。主要原因在于:
但最终会形成一套规范,其它网络库(如Apollo)遵守规范说明即可接入 Suspense 支持:
We’ll provide a reference implementation of a basic “React Cache” that’s compatible with Suspense, but you can also write your own. Data fetching libraries like Apollo and Relay will be able to integrate with Suspense by following a simple specification that we’ll document.
React & React DOM 16.x(未发布)
Suspense 同样能够配合 SSR,前后端合璧提升页面加载体验
具体的,渐进加载,并分块渲染页面内容,同时结合 Suspense 特性提升加载中的视觉体验:
We started designing a new server renderer that supports Suspense (including waiting for asynchronous data on the server without double rendering) and progressively loading and hydrating page content in chunks for best user experience.
P.S.其中 double rendering 是指前后端渲染结果不一致时(比如前端渲染依赖数据请求),为保证状态一致,需要丢弃后端渲染结果,前端再次渲染该组件,具体见[Hydration](https://reactjs.org/docs/react-dom.html#hydrate
目前相关消息很少,但确定SSR 大幅重构是 2019 年的重点目标:
The new server renderer is going to be our major focus in 2019, but it’s too early to say anything about its release schedule.
不确定
名为 React Fire 的计划,想要简化实现(Simplifying)并与现代浏览器 DOM 看齐(Modernizing)
目前还在探索阶段,具体计划及进度见React Fire: Modernizing React DOM
不确定