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

EggReactSSR服务端渲染开发指南

时间:2023-04-03 22:56:35 Node.js

##1.项目初始化1.1通过easywebpack-cli安装脚手架脚手架初始化npminstalleasywebpack-cli-g命令行,然后就可以使用easywebpack或者easy命令行运行easywebpackinit选择egg+reactserversiderenderboilerplate初始化骨架工程安装依赖npminstall1.2通过骨架工程初始化gitclonehttps://github.com/hubcarl/egg-react-webpack-boilerplate.gitnpminstall初始化的工程提供多页面和SPA(react-router/react-redux)服务端渲染实例,可直接运行。2.项目运行2.1在本地运行npmstartnpmstart做了以下三件事启动egg应用启动Webpack构建,文件没有落地磁盘,构建的文件都在内存中(只在本地启动,release模式为将文件提前构建到磁盘)build会同时启动两个Webpack构建服务,客户端js构建端口9000,服务端端口9001构建完成,Egg应用正式可用,自动开启浏览器2.2版本构建文件登陆磁盘的方式npmrunbuild或easywebpackbuildprod启动Webpack构建,文件登陆磁盘服务器构建的文件放在app/view目录下。客户端构建的文件放在公共目录中。生成的buildConfig.json和manifest.json放在config目录下。构建的文件都是gitignore,部署时请注意,打包这些文件运行应用前,请设置EGG_SERVER_ENV环境变量,测试环境设置test,正式环境设置prodnpmstart3。通过easywebpack-cli统一项目构建,支持dev、test、prod模式。Easywebpack-cli是通过项目根目录下的webpack.config.js配置文件构建Webpack的实际配置文件。配置项参见webpack.config.js获取Webpack的实际配置文件。egg-webpack将使用此功能。build会根据webpackConfigList.length启动相应数量的Webpack编译实例。这里会同时启动两个Webpack构建服务,客户端jsbundle构建,端口9000,服务端jsbundle构建端口9001。默认端口为9000,端口依次递增。//config/config.local.jslocalnpmstartuseconstEasyWebpack=require('easywebpack-react');exports.webpack={webpackConfigList:EasyWebpack.getWebpackConfig()};本项目中,将app/web/page目录下的所有.jsx文件作为webpack构建入口,实现app/web/framework/entry/loader.js模板,需要配合entry.loader使用在webpack.config.js下。entry:{include:['app/web/page',{layout:'app/web/view/layout.jsx?loader=false'},{'spa/redux':'app/web/page/spa/redux.jsx?loader=false'},{'spa/client':'app/web/page/spa/client.jsx?loader=false'},{'spa/ssr':'app/web/page/spa/ssr.jsx?loader=false'}],exclude:['app/web/page/test'],loader:{client:'app/web/framework/entry/loader.js'}}以上{'app/app':'app/web/page/app/app.js?loader=false'}loader=false的意思是app/web/page目录下的app/app.js不使用入口。装载机模板。因为这个app/app.js是SPA服务端渲染的例子,实现逻辑和其他普通页面不一样,不能使用entry.loader模板。在自定义入口文件以构建规范时使用此函数。4.项目规范遵循egg开发规范。React项目代码放在app/web目录下,页面入口目录为page。该目录下的所有.jsx文件默认都会作为Webpack的入口构建入口。建议在每个页面目录下只保留一个.jsx文件,与jsx关联的组件可以放在widget或component目录下。如果非要放到当前状态,请配置webpack.config.jsentry.exclude排除.jsx文件。5、项目开发支持多页/单页服务端渲染、前端渲染、静态页面。5.1多页面服务端渲染实现5.1.1多页面前端页面实现在app/web/page目录下创建home目录,home.jsx文件,Webpack自动根据.jsx文件创建入口entry,具体实现页面逻辑见webpack.config.jshome.jsxlist.jsx';import'./home.css';exportdefaultclassHomeextendsComponent{componentDidMount(){console.log('----componentDidMount-----');}render(){return

;}5.1.2多页面后端渲染实现,通过egg-view-react-ssr插件render方式创建controller文件home.jsexports.index=function*(ctx){yieldctx.render('home/home.js',Model.getPage(1,10));};添加路由配置app.get('/home',app.controller.home.home.index);5.1.3多页面前端渲染(后端路由)实现,通过egg-view-react-ssr插件renderClient方法创建controller文件home.jsexports.client=function*(ctx){yieldctx.renderClient('home/home.js',Model.getPage(1,10));};添加路由配置app.get('/client',app.controller.home.home.client);5.2HTML静态页面前端渲染Easywebpack直接构建静态HTML文件,参考webpack.config.js配置和app/web/page/html代码通过egg-static静态文件访问HTML文件5.3单页面服务端渲染同构实现5.3.1单页前端在app/web/page目录下创建app目录,spa/ssr.jsx文件。ssr.jsx页面调用入口importReact,{Component}from'react'importReactDOMfrom'react-dom'import{Provider}from'react-redux'import{match,RouterContext}from'react-router'import{BrowserRouter,StaticRouter}from'react-router-dom';import{matchRoutes,renderRoutes}from'react-router-config'importHeaderfrom'component/layout/standard/header/header';从'component/spa/ssr/导入SSRssr';从'component/spa/ssr/store'导入{创建};从'component/spa/ssr/routes'导入路由导入'./spa.css';如果(打字fwindow==='object'){//前端渲染构建conststore=create(window.__INITIAL_STATE__);consturl=store.getState().url;ReactDOM.render(
,document.getElementById('app'));}else{//serverRender构建和render入口,这里是导出函数,server会负责处理module.exports=(context,options)=>{consturl=context.state网址;constbranch=matchRoutes(routes,url);//获取组件数据constpromises=branch.map(({route})=>{constfetch=route.component.fetch;returnfetchinstanceofFunction?fetch():Promise.resolve(null)});returnPromise.all(promises).then(data=>{//初始化存储数据constinitState=context.state;data.forEach(item=>{Object.assign(initState,item);});context.state=Object.assign({},context.state,initState);conststore=create(初始化状态);return()=>(
)});};}5.3.2单页后端实现创建控制器文件app.jsexports.ssr=function*(ctx){yieldctx.render('spa/ssr.js',{url:this.url});};添加路由配置app.get('/spa/ssr',app.controller.spa.ssr);构建配置spa单页实现比较复杂,不能使用entry.loader,需要在webpack.config.js中配置{entry:{include:['app/web/page',{layout:'app/web/view/layout.jsx?loader=false'},{'spa/redux':'app/web/page/spa/redux.jsx?loader=false'},{'spa/client':'app/web/page/spa/client.jsx?loader=false'},{'spa/ssr':'app/web/page/spa/ssr.jsx?loader=false'}],exclude:['app/web/页面/测试'],loader:{client:'app/web/framework/entry/loader.js'}},}详细代码参考Skeleton项目实现6.项目部署正式环境部署请设置EGG_SERVER_ENV=prod环境变量。详情参见运行环境构建的app/view目录、public目录和buildConfig.json、manifest.json文件都是gitignore。部署时请注意打包这些文件。7.项目及插件egg-react-webpack-boilerplate基于easywebpack-react的工程骨架项目及egg-view-react(ssr)插件easywebpackWebpack搭建工程.easywebpack-cliWebpack搭建工程脚手架.egg-view-reactreactssr引擎egg-view-react-ssrreactssr解决方案.egg-webpack本地开发热更新使用.egg-webpack-react本地开发渲染内存读取辅助插件