服务器渲染,怎样使用React服务器端渲染
大家好,感谢邀请,今天来为大家分享一下服务器渲染的问题,以及和怎样使用React服务器端渲染的一些困惑,大家要是还不太明白的话,也没有关系,因为接下来将为大家分享,希望可以帮助到大家,解决大家的问题,下面就开始吧!
服务端渲染的好处
react.js在服务器端渲染好处:
提升性能是需要再浏览器端的性能提升还是服务端的性能提升,是两个概念,服务端渲染会给服务端造成一定的压力,减轻客户端的压力;好处:在整个页面级别的应用会使得浏览器在解析dom完成之后马上有东西可以渲染。再者就是对seo比较友好一些;
渲染的流程主要是:
准备数据,一般从数据库或外部API获得(一般要先 render React一次,去触发所需的API)
数据和React结合生成HTML Markup
除了把HMTL Markup输出外,还要把'State'输出,这要在客户端才能保留'State'
怎样使用React服务器端渲染
这次给大家带来怎样使用React服务器端渲染,使用React服务器端渲染的注意事项有哪些,下面就是实战案例,一起来看一下。
React提供了两个方法 renderToString和 renderToStaticMarkup用来将组件(Virtual DOM)输出成 HTML字符串,这是 React服务器端渲染的基础,它移除了服务器端对于浏览器环境的依赖,所以让服务器端渲染变成了一件有吸引力的事情。
服务器端渲染除了要解决对浏览器环境的依赖,还要解决两个问题:
前后端可以共享代码
前后端路由可以统一处理
React生态提供了很多选择方案,这里我们选用 Redux和 react-router来做说明。
Redux
Redux提供了一套类似 Flux的单向数据流,整个应用只维护一个 Store,以及面向函数式的特性让它对服务器端渲染支持很友好。
2分钟了解 Redux是如何运作的
关于 Store:
整个应用只有一个唯一的 Store
Store对应的状态树(State),由调用一个 reducer函数(root reducer)生成
状态树上的每个字段都可以进一步由不同的 reducer函数生成
Store包含了几个方法比如 dispatch, getState来处理数据流
Store的状态树只能由 dispatch(action)来触发更改
Redux的数据流:
action是一个包含{ type, payload}的对象
reducer函数通过 store.dispatch(action)触发
reducer函数接受(state, action)两个参数,返回一个新的 state
reducer函数判断 action.type然后处理对应的 action.payload数据来更新状态树
所以对于整个应用来说,一个 Store就对应一个 UI快照,服务器端渲染就简化成了在服务器端初始化 Store,将 Store传入应用的根组件,针对根组件调用 renderToString就将整个应用输出成包含了初始化数据的 HTML。
react-router
react-router通过一种声明式的方式匹配不同路由决定在页面上展示不同的组件,并且通过 props将路由信息传递给组件使用,所以只要路由变更,props就会变化,触发组件 re-render。
假设有一个很简单的应用,只有两个页面,一个列表页/list和一个详情页/item/:id,点击列表上的条目进入详情页。
可以这样定义路由,./routes.js
import React from'react';
import{ Route} from'react-router';
import{ List, Item} from'./components';
//无状态(stateless)组件,一个简单的容器,react-router会根据 route
//规则匹配到的组件作为 `props.children`传入
const Container=(props)=>{
return(
<p>{props.children}</p>
);
};
// route规则:
//- `/list`显示 `List`组件
//- `/item/:id`显示 `Item`组件
const routes=(
<Route path="/" component={Container}>
<Route path="list" component={List}/>
<Route path="item/:id" component={Item}/>
</Route>
);
export default routes;从这里开始,我们通过这个非常简单的应用来解释实现服务器端渲染前后端涉及的一些细节问题。
Reducer
Store是由 reducer产生的,所以 reducer实际上反映了 Store的状态树结构
./reducers/index.js
import listReducer from'./list';
import itemReducer from'./item';
export default function rootReducer(state={}, action){
return{
list: listReducer(state.list, action),
item: itemReducer(state.item, action)
};
}rootReducer的 state参数就是整个 Store的状态树,状态树下的每个字段对应也可以有自己的reducer,所以这里引入了 listReducer和 itemReducer,可以看到这两个 reducer的 state参数就只是整个状态树上对应的 list和 item字段。
具体到./reducers/list.js
const initialState= [];
export default function listReducer(state= initialState, action){
switch(action.type){
case'FETCH_LIST_SUCCESS': return [...action.payload];
default: return state;
}
}list就是一个包含 items的简单数组,可能类似这种结构:[{ id: 0, name:'first item'},{id: 1, name:'second item'}],从'FETCH_LIST_SUCCESS'的 action.payload获得。
然后是./reducers/item.js,处理获取到的 item数据
const initialState={};
export default function listReducer(state= initialState, action){
switch(action.type){
case'FETCH_ITEM_SUCCESS': return [...action.payload];
default: return state;
}
}Action
对应的应该要有两个 action来获取 list和 item,触发 reducer更改 Store,这里我们定义 fetchList和 fetchItem两个 action。
./actions/index.js
import fetch from'isomorphic-fetch';
export function fetchList(){
return(dispatch)=>{
return fetch('/api/list')
.then(res=> res.json())
.then(json=> dispatch({ type:'FETCH_LIST_SUCCESS', payload: json}));
}
}
export function fetchItem(id){
return(dispatch)=>{
if(!id) return Promise.resolve();
return fetch(`/api/item/${id}`)
.then(res=> res.json())
.then(json=> dispatch({ type:'FETCH_ITEM_SUCCESS', payload: json}));
}
}isomorphic-fetch是一个前后端通用的 Ajax实现,前后端要共享代码这点很重要。
另外因为涉及到异步请求,这里的 action用到了 thunk,也就是函数,redux通过 thunk-middleware来处理这类 action,把函数当作普通的 action dispatch就好了,比如 dispatch(fetchList())
Store
我们用一个独立的./store.js,配置(比如 Apply Middleware)生成 Store
import{ createStore} from'redux';
import rootReducer from'./reducers';
// Apply middleware here
//...
export default function configureStore(initialState){
const store= createStore(rootReducer, initialState);
return store;
}react-redux
接下来实现<List>,<Item>组件,然后把 redux和 react组件关联起来,具体细节参见 react-redux
./app.js
import React from'react';
import{ render} from'react-dom';
import{ Router} from'react-router';
import createBrowserHistory from'history/lib/createBrowserHistory';
import{ Provider} from'react-redux';
import routes from'./routes';
import configureStore from'./store';
// `INITIAL_STATE`来自服务器端渲染,下一部分细说
const initialState= window.INITIAL_STATE;
const store= configureStore(initialState);
const Root=(props)=>{
return(
<p>
<Provider store={store}>
<Router history={createBrowserHistory()}>
{routes}
</Router>
</Provider>
</p>
);
}
render(<Root/>, document.getElementById('root'));至此,客户端部分结束。
Server Rendering
接下来的服务器端就比较简单了,获取数据可以调用 action,routes在服务器端的处理参考 react-router server rendering,在服务器端用一个 match方法将拿到的 request url匹配到我们之前定义的 routes,解析成和客户端一致的 props对象传递给组件。
./server.js
import express from'express';
import React from'react';
import{ renderToString} from'react-dom/server';
import{ RoutingContext, match} from'react-router';
import{ Provider} from'react-redux';
import routes from'./routes';
import configureStore from'./store';
const app= express();
function renderFullPage(html, initialState){
return `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<p id="root">
<p>
${html}
</p>
</p>
<script>
window.INITIAL_STATE=${JSON.stringify(initialState)};
</script>
<script src="/static/bundle.js"></script>
</body>
</html>
`;
}
app.use((req, res)=>{
match({ routes, location: req.url},(err, redirectLocation, renderProps)=>{
if(err){
res.status(500).end(`Internal Server Error${err}`);
} else if(redirectLocation){
res.redirect(redirectLocation.pathname+ redirectLocation.search);
} else if(renderProps){
const store= configureStore();
const state= store.getState();
Promise.all([
store.dispatch(fetchList()),
store.dispatch(fetchItem(renderProps.params.id))
])
.then(()=>{
const html= renderToString(
<Provider store={store}>
<RoutingContext{...renderProps}/>
</Provider>
);
res.end(renderFullPage(html, store.getState()));
});
} else{
res.status(404).end('Not found');
}
});
});服务器端渲染部分可以直接通过共用客户端 store.dispatch(action)来统一获取 Store数据。另外注意 renderFullPage生成的页面 HTML在 React组件 mount的部分(<p id="root">),前后端的 HTML结构应该是一致的。然后要把 store的状态树写入一个全局变量(INITIAL_STATE),这样客户端初始化 render的时候能够校验服务器生成的 HTML结构,并且同步到初始化状态,然后整个页面被客户端接管。
最后关于页面内链接跳转如何处理?
react-router提供了一个<Link>组件用来替代<a>标签,它负责管理浏览器 history,从而不是每次点击链接都去请求服务器,然后可以通过绑定 onClick事件来作其他处理。
比如在/list页面,对于每一个 item都会用<Link>绑定一个 route url:/item/:id,并且绑定 onClick去触发 dispatch(fetchItem(id))获取数据,显示详情页内容。
相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!
推荐阅读:
怎样使用JS实现计算圆周率到小数点后100位
怎样使用vue axios给生产与发布环境配置接口地址
什么是渲染图
渲染图是摄影专业用语,是指通过调整光线、色彩、角度等参数,重新渲染衣服图片或者照片,以达到自己期望效果的一种修图手法。
它会将三维的光能传递处理转换为一个二维图像的过程。场景和实体用三维形式表示,更接近于现实世界,便于操纵和变换,而图形的显示设备大多是二维的光栅化显示器和点阵化打印机。
从三维实体场景的表示N--维光栅和点阵化的表示就是图像渲染——即光栅化。光栅显示器可以看作是一个象素矩阵,在光栅显示器上显示的任何一个图形,实际上都是一些具有一种或多种颜色和灰度象素的集合。
渲图是摄影专业用语,是指通过调整光线、色彩、角度等参数,重新渲染衣服图片或者照片,以达到自己期望效果的一种修图手法。
扩展资料
渲染图像流程
在图像渲染前,需要准备好三维几何模型信息,三维动画定义信息和材质信息。其中三维几何模型通过三维扫描,三维交互几何建模和三维模型库中获取;三维动画定义通过运动设计,运动捕捉,运动计算和动态变形中获取:
材质从扫描的照片,计算机计算出的图像和人画出的图画中获取。图像渲染中要完成的工作是:通过几何变换,投影变换,透视变换和窗口剪裁,再通过获取的材质与光影信息,生成图像。图像渲染结束后,会把图像信息输出到图像文件或视频文件,或者是显示设备的帧缓存器中完成图形生成。
参考资料来源百度百科-图像渲染
关于服务器渲染和怎样使用React服务器端渲染的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。