当前位置: 首页 > 后端技术 > Node.js

从零搭建一个React同构应用(四):搭建KoaServer&提升SSR

时间:2023-04-03 10:57:12 Node.js

从零搭建一个React同构应用(四):搭建KoaServer&提升SSR在上一篇文章中,我们使用CLISSR进行了测试,这篇文章讲的是如何在上一篇文章的基础上搭建一个KoaServer,实现真正的SSR。demo的主要内容是Koa搭建并完善SSR逻辑Koa搭建了一个新的server/index.js:我们使用的是Koav2.0版本;npm我koa@next-S;先搭建最简单的服务器constKoa=require("koa");constapp=newKoa();app.use(ctx=>{ctx.body='HelloKoa';});app.listen(8088,_=>{console.log('服务器启动')});添加一个npm脚本"scripts":{"start":"node--harmonyserver/index",//启动HTTP服务器"watch":"webpack-d-w--progress--colors--bs","test-server":"anywhere-p18341-d./build","dist":"cross-envNODE_ENV='production'webpack-p","test-ssr":"node--harmonytest/cli.js"},执行npmrunstart这样最简单的Koa框架就搭好了,下面填写即可。配置路由器在添加路由器之前,我们需要加载webpack编译好的HTML模板。这里我们不使用EJS、HBS等Nodejs渲染引擎。相反,我们使用cheerio来帮助我们操作HTML。Cheerio允许我们在Node环境中使用它。使用jQuery操作HTML非常容易。这是它的API,和jQuery基本一样。在server/index.js中添加:constcheerio=require("cheerio");constfs=require("fs");constpath=require("path");constPromise=require("bluebird");constserve=require('koa-static-server');constreadFileAsync=Promise.promisify(fs.readFile);/***读取HTML模板并返回cheerio实例*@parampath*@return{Promise.<*>}*/asyncfunctionloadHTMLTemplate(path){try{letcontent=awaitreadFileAsync(path);返回cheerio.load(内容);}catch(e){console.error(e);返回假;}}我们使用koa-better-router中间件作为路由模块。我们添加路由器,在server/index.js中添加:constrouter=require('koa-better-router')().loadMethods();router.get('/',async(ctx,next)=>{让$=awaitloadHTMLTemplate(path.resolve(__dirname,'../build/index.html'));if(!$){returnctx.body=null;}returnctx.body=$.html();});app.use(router.middleware());执行npmrunstart,我们会发现CSS、JS等文件没有加载,因为没有对应的路由。接下来,我们配置静态文件服务。配置静态文件服务我们不可能为所有的资源都写一个路由器,所以我们需要配置一个静态文件服务。这里我使用的是koa-static-server中间件。我们将build目录作为资源文件的根目录,添加到server/index.js中:constserve=require('koa-static-server');constreadFileAsync=Promise.promisify(fs.readFile);constRES_PATH=path.resolve(__dirname,'../build/');//hfsapp.use(serve({rootDir:RES_PATH}));执行npmrunstart资源可以正确加载。为了完善SSR逻辑,我们先添加一个API接口,方便模拟Node端的接口调用,在server/index.js中添加://API接口router.get('/api/todo_list',async(ctx,next)=>{returnctx.body=['11','222'];});我们以Index.jsx为例:复制test/cli.js中的代码。修改/路径constKoa=require("koa");constapp=newKoa();constrouter=require('koa-better-router')().loadMethods();constcheerio=require("cheerio");constfs=require("fs");constpath=require("path");constPromise=require("bluebird");constserve=require('koa-static-server');constreadFileAsync=Promise。promisify(fs.readFile);constRES_PATH=path.resolve(__dirname,'../build/');constfetch=require("isomorphic-fetch");router.get('/',async(ctx,next)=>{let$=awaitloadHTMLTemplate(path.resolve(__dirname,'../build/index.html'));if(!$){returnctx.body=null;}letIndexBundle=require("../build_server/index.bundle.js");//fetch接口数据lettodoList=await(awaitfetch('http://localhost:8088/api/todo_list')).json();letinitialData={todoList};letinstance=React.createElement(IndexBundle.default,initialData);letstr=renderToString(instance);$('#wrap').html(str);//前后端数据要同步letsasyncScript=``;$('head').append(syncScript);返回ctx.body=$.html();});这里需要注意的是前后端数据一定要同步。我把Node端获取到的数据放在window._SERVER_DATA中,前端渲染会优先使用window._SERVER_DATA进行渲染if(process.browser){//初始数据,用于和server渲染数据同步letinitialData=window._SERVER_DATA||{};letstore=createStore(reducers,initialData,window.__REDUX_DEVTOOLS_EXTENSION__&&window.__REDUX_DEVTOOLS_EXTENSION__());letApp=connect(_=>_)(Layout);//用connect包裹起来,这里只用了mapStateToProps,不过滤stateReactDOM.render(,document.getElementById('wrap'));}执行npmrunstart访问http://127.0.0.1:8088/,可以看到#wrap已经填充了渲染好的HTML文本,以及上面的数据Node端和前端也是同步的。^_^至此,一个简单的SSR框架搭建完成,剩下的工作就是根据工作需要为其添砖加瓦了。