关于 React服务器端渲染(SSR)
来源:互联网 发布:统计局70城房价数据 编辑:程序博客网 时间:2024/05/01 11:40
最近经常听到其他主攻 Vue
项目的前端小组提到 SSR
这个名词,一直都不明白是什么东西,只以为是他们内部做的什么工具之类的东西,虽然有些好奇,但也没怎么在意,直到后来在某技术论坛闲逛的时候忽然也看到这个名词了,点进去后通篇看完才知道 ssr
是个什么东西。
SSR的概念
Server Slide Rendering
,缩写为 ssr
,即服务器端渲染,因为是后端出身,所以其实早就明白是怎么回事,只是没这个具体名词的概念罢了,这个词被频繁提起也是拜近年来前端飞速发展所赐,主要针对 SPA
应用,目的大概有以下几个:
- 解决单页面应用的
SEO
单页应用页面大部分主要的HTML
并不是服务器返回,服务器只是返回一大串的 脚本,页面上看到的大部分内容都是由脚本生成,对于一般网站影响不大,但是对于一些依赖搜索引擎带来流量的网站来说则是致命的,搜索引擎无法抓取页面相关内容,也就是用户搜不到此网站的相关信息,自然也就无流量可言。
- 解决渲染白屏
因为页面HTML
由服务器端返回的脚本生成,一般来说这种脚本的体积都不会太小,客户端下载需要时间,浏览器解析以生成页面元素也需要时间,这必然会导致页面的显示速度比传统服务器端渲染得要慢,很容易出现首页白屏的情况,甚至如果浏览器禁用了JS
,那么将直接导致页面连基本的元素都看不到。
Vue
和 React
是用来做单页应用最普遍的框架,因为我对 react
更熟悉,所以这里我只说下 React SSR
。
客户端部分
新建 React页面
首先,要有一个用于展示的 React
页面,例如:
// ./client/components/About/index.jsximport React, { Component } from 'react'import styles from './style.scss'import './style'export default class About extends Component { constructor() { super() this.state = { txtInfo: '' } } componentWillMount() { this.state.txtInfo = 'zhangsan' } componentDidMount() { this.getInfo() } render() { return ( <section className={styles['about-wrapper']}> <p className="title">About Page</p> <p className="txt-info">{this.state.txtInfo}</p> </section> ) } getInfo() { fetch('/api/user/getInfo', { credentials: 'include', headers: { 'Access-Control-Allow-Origin': '*', 'Content-Type': 'text/plain; application/json; charset=utf8' } }).then(res=>{ return res.json() }).then(data=> { this.setState({ txtInfo: data.name }) }) }}
这里的路由使用 react-router
,简便考虑,只有一个路由,创建路由:
// ./client/routes.jsexport default const routes = { childRoutes: [{ path: '/', component: require('./components/app.jsx'), indexRoute: { getComponent(nextState, callback) { require.ensure([], require => { callback(null, require('./components/About/index.jsx')) }, 'about') } }}
其中 ./components/app.jsx
的结构很简单,主要只有一个 render
方法:
render() { const {children, ...props} = this.props return ( <div> {React.Children.map(children, child => React.cloneElement(child, {...props}) )} </div> ) }
最主要的是入口组件 index.js
:
// ./client/index.jsimport React from 'react'import { render } from 'react-dom'import { Router, match, browserHistory } from 'react-router'import routes from './routes'match({ history: browserHistory, routes }, (error, redirectLocation, renderProps) => { render( <Router {...renderProps}/>, document.getElementById('root') )})
其中,有个 match
方法,这是 react-router
提供的方法,作用在于在渲染之前根据URL匹配路由组件,更多详情可看 这里
客户端就这些了,下面开始服务端。
服务端
服务端使用 koa
框架,安装配置什么的我就不多说了,不知道的可见 这里
// ./server/app.jsimport Koa from 'koa'const app = new Koa()export default app
配置服务端路由:
// ./server/routes/index.jsimport Router from 'koa-router'const router = new Router({prefix: '/api/user'})router.get('/getInfo', async(ctx, next)=> { ctx.body = { name: 'xiaoming', age: 18 }})export default router
配置了一个 /api/user/getInfo
的路由
但是,服务端只有服务端路由还不行,因为是服务器端渲染,所以还必须在服务端配置客户端路由,因为只有知道客户端的路由,服务器才知道该向客户端传送什么页面的 HTML
字符串,如下:
// ./server/clientRoutes.jsimport React from 'react'import { renderToString } from 'react-dom/server'import { match, RouterContext } from 'react-router'import routes from '../../client/routes'async function clientRoute(ctx, next) { let _renderProps match({ routes, location: ctx.url }, (error, redirectLocation, renderProps) => { _renderProps = renderProps }) if (_renderProps) { await ctx.render('index', { root: renderToString( <RouterContext {..._renderProps}/> ), info: { name: '小明' } }) } else { await next() }}export default clientRoute
除了 match
之外,这次又多了个 RouterContext
,此 API
也是属于 react-router
,它的作用是以同步的方式渲染路由组件,不然你想啊,一个 react
组件,有很多 API
钩子函数,若是在这些钩子函数还没执行完之前,服务器就把 HTML
渲染到客户端了,那肯定会缺斤少两啊,所以这个时候此 API
就派上了用场。
下面就只剩下启动服务渲染页面了。
这个稍微复杂一点,因为需要考虑到很多问题,比如jsx
语法的转码、css
样式文件的打包,HTML
的注入等,不仅需要考虑浏览器端,还要考虑 服务端,一个都不能少。
// 转码器 babelrequire('babel-polyfill')// react 的转码 hookrequire('babel-register')({ presets: ['es2015', 'react', 'stage-0'], plugins: ['add-module-exports']})// css 的转码 hookrequire('css-modules-require-hook')({ extensions: ['.scss'], preprocessCss: (data, filename) => require('node-sass').renderSync({ data, file: filename }).css, camelCase: true, generateScopedName: '[name]__[local]__[hash:base64:8]'})const webpack = require('webpack'), app = require('./app'), convert = require('koa-convert'), fs = require('fs'), path = require('path'), devMiddleware = require('koa-webpack-dev-middleware'), views = require('koa-views'), router = require('./routes'), clientRoute = require('./clientRoute'), config = require('../webpack.dev.config'), port = process.env.port || 3000 compiler = webpack(config)app.use(views(path.resolve(__dirname, '../views/dev'), { map: { html: 'ejs' } }))app.use(clientRoute)app.use(router.routes())app.use(router.allowedMethods())console.log(`Listening on port ${port}`)app.use(convert(devMiddleware(compiler, { noInfo: true, publicPath: config.output.publicPath})))app.listen(port)
基本上就是这样了,打开页面,是这个效果:
同时如果使用 Restlet Client
这样的工具请求页面,也能够看到返回的 HTML
字符串与浏览器实际渲染后的页面HTML
完全一致,这说明服务器端渲染的目的已经达到了。
有关项目
上面代码还有一些我都没贴出来,我也不想贴项目地址,因为没必要了。
如果是在一年前,关于 react
服务器端渲染还没什么标准,社区各路大神各显神通的话,那么现在再提起 react server slide rendering
的话,就没必要再自己吃力不讨好的瞎折腾了,你应该想起这个脚手架:Next.js
Next.js
是一个用于在服务端渲染 React
应用程序的简单框架,2016 年 10 月 25 日由 zeit.co 背后的团队发布。
React
服务端渲染SSR
应用框架,支持可选的服务端与客户端渲染功能,简单易用,安装这个框架会搭建一个基于React、Webpack
和Babel
的构建过程,也就是说脚手架已经预设了配置,开发人员不必在搭建Webpack
或Babel
配置上。
此项目算是众多 react server slide rendering
方案中最受欢迎的一个,如果现在考虑 react
服务端渲染,此方案算是最佳选择。
另外,不仅是 react
, vue
同样有类似对标的库:Nuxt.js,作用和功能几乎和 Next.js
一致,有意思的是,Nuxt.js
的发布时间仅在 Next.js
宣告发布后的几个小时内,算是同一天发布,如今在各自领域内的影响力不分伯仲。
- 关于 React服务器端渲染(SSR)
- React服务器端渲染(SSR)实例
- React服务器端渲染
- React-服务器端渲染
- React服务器端渲染
- React服务器端渲染入门教程参考
- 基于React服务器端渲染的博客系统
- 最新的React服务器端渲染入门教程
- React使用Next.js作服务器端渲染
- 关于react组件渲染两次的问题
- vue2 ssr 服务端渲染入门demo
- SSR
- SSR
- 自译: 如何使用服务器端渲染构建快速加载的React apps
- react demo1 (react内容渲染)
- React服务器渲染
- React服务器渲染
- React 避免重渲染
- mysql5.7使用前初始化(主要是更改密码)
- EL表达式
- 安装vmware时显示无法写入注册表怎么办
- 9-16NOIP模拟赛总结
- Spring MVC--18.json结果返回(@)
- 关于 React服务器端渲染(SSR)
- SpringCloud概述
- Nginx和Apache配置日志格式记录Cookie
- 为多态基类声明virtual析构函数
- 【生活】我的父母
- 中间变量缓存机制
- Python:神奇的pivot函数!(行列转置)
- Eclipse中的buildpath详解
- Java基础部分第七节