摘要:之前做的一个应用,最近把首页改成了服务端渲染的形式,过程还是很周折的,踩到了不少坑,记录一些重点,希望有所帮助前端使用的技术栈升级到升级到服务项目地址喜欢的给个,感谢。。。。。。。
之前react做的一个应用,最近把首页改成了服务端渲染的形式,过程还是很周折的,踩到了不少坑,记录一些重点,希望有所帮助前端使用的技术栈
react、react-dom 升级到 v16
react-router-dom v4
redux red-sage
antd-mobile 升级到 v2
ssr服务 express
项目地址,喜欢的给个star,感谢。。。。。。。
访问地址(手机模式) 非服务端渲染 服务端渲染 效果对比 前后处理流程对比 react下ssr的实现方式React下同构的解决方案有next.js、react-server等,这里,因为这个项目之前已经采用create-react-app、redux做完了,只是想在现有系统基础上把首页改成服务端直出的方式,就选择了webpack-isomorphic-tools这个模块
webpack-isomorphic-tools介绍如果我们想在现有React系统中引入同构,首先要解决的一个重要问题是:代码中我们import了图片,svg,css等非js资源,在客户端webpack的各种loader帮我们处理了这些资源,在node环境中单纯的依靠babel-regisiter是不行的,执行renderToString(
而webpack-isomorphic-tools就帮助我们处理了这些非js资源,在客户端webpack构建过程中,webpack-isomorphic-tools作为一个插件,生成了一份json文件,形如:
有了这份映射文件,在同构的服务端,renderToString(
比如我们有一个组件:
const App =()=>{ return ),就生成正确的 ) //得到填满数据的标签
拼接html
注意,上面说的webpack-isomorphic-tools中生成的json文件中有js,css的对应关系,这里我访问那个json文件得到js、css的路径,拼到html中
还要返回store中保存的状态,供客户端js createStore使用
在客户端js中
const sagaMiddleware = createSagaMiddleware() const store = createStore( reducer, window.__INITIAL_STATE__, applyMiddleware(sagaMiddleware) ) sagaMiddleware.run(rootSaga)路由
在做同构的时候不能用BrowserRouter,要使用无状态的StaticRouter,并结合location和context两个属性
有这样的路由结构
//默认跳到/home,其他的该到哪到哪}>
server端的代码要这样
const context = {} const html = renderToString() // 中访问/,重定向到/home路由时 if (context.url) { res.redirect("/home") return }
StaticRouter可以根据request来的url来指定渲染哪个组件,context.url指定重定向到的那个路由
也就是说,要是访问 /,StaticRouter会给我们重定向到/home,并且StaticRouter自动给context对象加了url,context.url就是重定向的/home,当不是重定向时,context.url是undefined
我们还可以自己写逻辑 通过context来处理302、404等。但这里我不需要。。。。。,为什么呢?
我没做全栈的同构,只服务端渲染了主页,渲染一个和多个差不多,全都渲染的话就是在服务端要根据当前请求的路由来决定要发那些请求来填充Store
我对路由的处理流程上面的思维导图有说明,就是在nginx中多配一个代理。
对于访问/、/home这两个路由,代理到ssr服务,来吐首页内容,api代理到后端服务,其他的直接返回(也就是说如果在detail页面或user页面刷新了页面还是之前客户端渲染那套)
对登录操作的处理上面说server端初始化数据的时候还有一个登陆问题没说。
用户初始访问了服务端渲染的首页,然后在客户端转到登录页面登陆了,重新回到首页刷新了页面,喔,又去请求了ssr服务,但服务端不知道当前用户登录了啊,还是原来的流程,返回的__INITIAL_STATE__中还是没有用户的个人信息和已登录状态
所以,在客户端登陆后,要将用户的token存到cookie中,这样,在首页就算用户刷新了页面,重新请求页面请求中也会带上cookie,在服务端,根据request.cookies中是否有token来决定发哪些请求填充store
if (auth) { //要是有token就去查用户信息和是否登录状态(还查是否登录是因为token有可能是被篡改过的) promises = [ getMoviesList(store, auth), getCategory(store), checkLogin(store, auth), getUinfo(store, auth) ] } else { promises = [ getMoviesList(store), getCategory(store), ] } Promise.all(promises).then(x=>{ renderToString(避免客户端js中初始请求的触发) })
到这一步,访问域名,就能够正确展示服务端渲染的页面,跳到别的路由,客户端的js也能正常处理接下来的事,但是,服务端渲染页面展示后,首页那几个ajax请求还是触发了,这是没必要的。
原以为这是react renderToString()生成的标签和客户端js hydrate()的有差异导致的,然而,实际上,js执行了,组件的生命周期该触发还是会触发的,不只是 attach event listeners to the existing markup
所以要手动避免
在App组件中 componentDidMount() { if (!window.__INITIAL_STATE__) { this.props.checkLogin() this.props.loadCategory() } } //当当前页面是服务端返回的(因为window.__INITIAL_STATE__有初始状态),初始的ajax就不触发了总结
服务端渲染的坑还是挺多的,这一个星期就搞它了。。。。这里记录一些比较重要的东西,具体细节有兴趣的可以看下代码.最后,最重要的,喜欢的给个star,感谢。。。。。。。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/92464.html
摘要:所以,这次就来聊聊组件的服务器端渲染。这种模式下,后端只提供接口,传统的服务器端路由模板渲染则都有层接管。这样,前端开发人员可以自由的决定哪些组件需要在服务器端渲染,哪些组件可以放在客户端渲染,前后端完全解耦,但又保留了服务器端渲染的功能。 细说 Vue 组件的服务器端渲染 声明:需要读者对 NodeJs、Vue 服务器端渲染有一定的了解 现在,前后端分离与客户端渲染已经成为前端开发的...
摘要:服务端任需要进行校验来达到数据的可靠性前端的路由可能在服务端并不存在等等这一系列重用性的问题。串行并行,大幅缩短请求时间。关于作者本人主页本文部分图片段落参考文章淘宝前后端分离实践微信公众号会不定期推送前端技术文章,欢迎关注 一、背景 书接上文,浅谈前后端分离与实践(一) 我们用mock服务器搭建起来了自己的前端数据模拟服务,前后端开发过程中只需定义好接口规范,便可以相互进行各自的开发...
阅读 1047·2021-11-22 15:33
阅读 3357·2021-11-08 13:20
阅读 1367·2021-09-22 10:55
阅读 2052·2019-08-29 11:08
阅读 770·2019-08-26 12:24
阅读 3067·2019-08-23 17:15
阅读 2224·2019-08-23 16:12
阅读 1932·2019-08-23 16:09