当前位置: 首页 > Web前端 > HTML

React 服务端渲染如此轻松 从零开始构建前后端应用

时间:2023-04-02 23:02:41 HTML

React服务端渲染是如此容易从头开始构建前端和后端应用程序。事实上,早些时候,在Facebook组织的ReactConf2017上,他到场并分享了将近40分钟。但是两次分享带来的demo都是黑客新闻。观察Next.js很久了,从1.x版本一直看到今天的3.x,最后决定写一篇入门级的新手引导文章。而本文试图用一个全新的例子来让大家了解Next.js是如何配合React来实现服务端渲染的。“Reactuniversal”是社区中描述基于React构建Web应用程序并使用“服务器端渲染”的词。或许很多人对“同构”这个词比较熟悉,但其实这两个词所表达的概念是相似的。今天的文章显然不是关于这两个词的。我们将尝试使用最新版本的Next.js构建一个简单的服务器端渲染React应用程序。最终的项目地址可以在这里查看。为什么要开发通用应用程序?React应用程序实现了一个虚拟DOM来抽象真实的DOM。这样的设计迅速引领了前端开发的浪潮。但是“凡事都是有代价的”,虚拟DOM也带来了一些弊端,比如在前后端分离的开发模式下,SEO成了问题;还有就是首屏加载时间变长,各种加载死人。耐心。如下截图所示:使用Next.js实现UniversalUniversal应用架构可以简单片面的理解为应用会在客户端和服务端同时渲染。这取代了完全客户端渲染(前后端分离)模式。在React场景下,我们可以使用React自带的renderToString来完成服务端的初始渲染。但是如果我们每次都手动完成这些过程,手动去实现服务器的繁琐配置,难免让人头疼。Next.js的出现就是为你解决这个恼人的问题。我们先来了解一下它的一些原理和思想:除了Next之外不需要多余的配置和安装(比如webpack,babel);使用Glamour处理样式;自动编译打包;热更新;方便的静态资源管理;成熟灵活的路由配置,包括路由级预取;Demo:其实更多的Next.js设计理念我不想细说,读者可以在其官网找到丰富的内容。接下来,我将使用FootballDataAPI简单地开发一个基于Next.js的应用程序,该应用程序将显示英超联赛的实时排名。它还包括简单的路由开发和页面跳转。我相信所有的开发者都讨厌长期安装和各种依赖和插件配置。别着急,Next.js作为一个独立的npm包已经最大程度的为你完成了很多耗时枯燥的工作。我们首先需要安装:#启动一个新项目npminit#安装Next.jsnpminstallnext--save安装完成后,我们就可以启动脚本了:"scripts":{"start":"next"},Next在安装的同时,也会安装React,所以不用费心了。接下来要做的很简单,只需要在根目录下新建一个pages文件夹,并在其下新建一个index.js文件://./pages/index.js//ImportReactimportReactfrom'react'//Exportananonymousarrowfunction//whichreturnsthetemplateexportdefault()=>(

Thisisjustsoeasy!

)好了,现在你可以直接看到结果了:#StartyourappnpmstarttoverifyIt来自服务器端渲染:就这么简单,新鲜。如果我们通过自己的方式实现这一切,除了NodeJS的繁琐之外,webpack的配置、node_modules的依赖、babel插件等都够折腾半天了。添加页面头部在./pages/index.js文件中,我们可以添加页面头部标签、元信息、样式资源等://./pages/index.jsimportReactfrom'react'//导入头部组件importHeadfrom'next/head'exportdefault()=>(
LeagueTable

这就是这么简单!

)这个head肯定不是指真实DOM,别忘了React虚拟DOM的概念。其实这就是Next提供的Head组件,只不过最后要渲染成真正的head标签。发送Ajax请求Next还提供了一个getInitialProps方法,它支持异步选项并且是服务器/客户端同构的。我们可以使用async/await来处理异步请求。请参见以下示例:importReactfrom'react'importHeadfrom'next/head'importaxiosfrom'axios';exportdefaultclassextendsReact.Component{//使用getInitialProps的异步操作staticasyncgetInitialProps(){//一旦axios//asyncget完成,res就会被分配响应constres=awaitaxios.get('http://api.football-data.org/v1/competitions/426/leagueTable');//返回属性return{data:res.data}}}我们使用axios库发送HTTP请求。网络请求是异步的,所以我们需要在未来某个合适的时间点(请求结果返回时)接收数据。这里使用高级的async/await来同步处理,从而避免了回调嵌套和promises链。我们将异步获取的数据返回,它会自动挂载到props上(注意getInitialProps方法名,顾名思义),可以通过render方法中的this.props.data获取:importReactfrom'react'从'next/head'导入Head'从'axios'导入axios;exportdefaultclassextendsReact.Component{staticasyncgetInitialProps(){constres=awaitaxios.get('http://api.football-data.org/v1/competitions/426/leagueTable');return{data:res.data}}render(){return(
......

巴克莱超级联赛

。.....{this.props.data.standing.map((standing,i)=>{constoddOrNot=i%2==1?“纯表奇数”:“”;返回({standing.position}{standing.points}{standing.goals}{standing.wins}{standing.draws}>{standing.loss});})}
);这样,如果你再次访问我们的页面,你就会有:路由和页面跳转也许你已经有了一种感觉:我们已经有了最基本的路由Next不需要任何额外的路由配置信息,你只需要在pages文件夹下新建文件,每个文件都会是一个独立的页面。让我们创建一个新的团队页面!创建一个新的./pages/details.js文件://./pages/details.jsimportReactfrom'react'exportdefault()=>(

Comingsoon...!

)我们准备好了使用NextGood组件进行页面跳转://./pages/details.jsimportReactfrom'react'//ImportLinkfromnextimportLinkfrom'next/link'exportdefault()=>(

Comingsoon...!

GoHome
)这个页面不能总是“Comingsoon...!”信息,我们会改进它显示更多的内容,通过页面URL的查询id变量,我们会请求并显示当前对应团队的信息:importReactfrom'react'importHeadfrom'next/head'importLinkfrom'next/link'importaxiosfrom'axios';exportdefaultclassextendsReact.Component{staticasyncgetInitialProps({query}){//从查询中获取idconstid=query.id;if(!process.browser){//仍在服务器上,所以发出请求constres=awaitaxios.get('http://api.football-data.org/v1/competitions/426/leagueTable')return{data:res.data,//根据查询排名过滤并返回数据:res.data.standing.filter(s=>s.position==id)}}else{//不在服务器上只是导航所以使用//缓存constbplData=JSON.parse(sessionStorage.getItem('bpl'));//根据查询过滤并返回数据return{standing:bplData.standing.filter(s=>s.position==id)}}}componentDidMount(){//在localStorage中缓存数据if//还没有缓存if(!sessionStorage.getItem('bpl'))sessionStorage.setItem('bpl',JSON.stringify(this.props.data))}//...rendermethodtruncated}此页面根据查询变量动态显示团队信息。具体是getInitialProps方法获取URL查询id,根据id(filter方法)信息过滤显示。有意思的是,因为球队的信息一直比较稳定,所以在客户端使用了sessionStorage来存储。完整的渲染方法://...truncatedexport默认类扩展React.Component{//...截断渲染(){constdetailStyle={ul:{marginTop:'100px'}}return(
LeagueTable

{this.props.standing[0].teamName}

点s:{this.props.standing[0].points}

  • 目标:{this.props.standing[0].goals}
  • 胜利:{this.props.standing[0].wins}
  • li>
  • 损失:{this.props.standing[0].losses}
  • 平局:{this.props.standing[0]].draws
  • 进球数:{this.props.standing[0].goalsAgainst}
  • 进球数:{this.props.standing[0].goalDifference}
  • 玩过:{this.props.standing[0].playedGames}
  • Home)}}注意下面截图中,同一个页面不同的查询值显示的是冠军的信息?切尔西和曼联。不要忘记在我们的主页(领导页面)index.js中使用相应的sessionStorage逻辑。同时在render方法中添加一个链接到详情页:More...错误页面接下来,我们还可以通过error.js文件来定义错误页面。在./pages下创建一个新的error.js://./pages/_error.jsimportReactfrom'react'exportdefaultclassErrorextendsReact.Component{staticgetInitialProps({res,xhr}){conststatusCode=res?水库statusCode:(xhr?xhr.status:null)return{statusCode}}render(){return(

    {this.props.statusCode?`服务器上发生错误${this.props.statusCode}`:'Anerroroccurredonclient'}

    )}}传统情况下页面404时,我们得到:我们设置_error.js后,有:总结本文实现了一个简单的demo,只是介绍了最基本的使用Next.JS构建React同构应用程序的基本步骤。觉得你厌倦了webpack烦人的配置?你是否对Babel的各种插件一头雾水?使用Next.js简单、干净且设计良好。这也是它自推出以来迅速走红的原因之一。另外,Next还有很多功能,可以应用很多先进的概念。例如与prefetch一起使用,预请求资源;另一个例子是组件的动态加载(Next.customizing,按需定制。最后,您是否渴望本文中未展示的某些功能?有兴趣的读者可以关注本文demo的Github项目地址,手动尝试一下~本文转述ChrisNwamba的:ReactUniversalwithNext.js:Server-sideReact,并对原文进行升级以兼容最新的Next设计。我的其他关于React的文章:打造Uber手机网页版还不够极致性能看真章剖析Twitter前端架构学习复杂场景数据设计ReactConf2017干货总结1:React+ESnext=?React+Redux打造“NEWSEARLY”单页应用,一个领悟最前沿技术栈真谛的项目,一个react+redux项目实例HappyCoding!PS:作者Github仓库和知乎问答链接,欢迎各种形式的交流。