6

我开始创建一个基于节点的同构React/Redux应用程序。该项目的一个要求是基于“移动”和“桌面”视图的“adapative”渲染特定组件。我已经实现了Redux动作和缩减器,以在状态中存储关于用户视图的屏幕信息(基于媒体查询 - “小”,“中”,“大”)。在调整状态/商店更新。默认状态是“小”。React/Redux同构/服务器端渲染和媒体查询

const defaultState = { 
    isMobile: true, 
    isTablet: false, 
    isDesktop: false, 
    sizes: { 
     small: true, 
     medium: false, 
     large: false, 
     huge: false, 
    }, 
}; 

在其中需要在基于屏幕尺寸的两个不同版本将被渲染的“自适应”组分,我简单地做一个:

如果(小)返回variation1

如果(中)返回变化2

所有的工作。

现在我面临两个问题:

  1. 我的应用是同构的,这意味着该标记也使得服务器端。服务器不知道用户的浏览器和媒体查询。因此,由于我的默认状态是“小”,服务器将始终呈现“variation1”。节点服务器是该站点的入口点。看起来渲染需要“延迟”(中间件?),并且服务器需要在React应用程序“交付”之前从客户端获取有关浏览器宽度的一些信息。任何想法如何解决这个问题?

  2. 由于渲染基于状态,因此即使浏览器大小为“桌面”,加载“变化1”后总能首先看到几毫秒(闪烁)。这是因为在用当前屏幕宽度更新状态之前,JS检测需要几毫秒。我认为这与上面的问题和默认状态一起玩。

我找不到任何解决方案1,但我想必须有一些同构和响应/自适应。

+0

我很好奇“变体1”是什么。还不确定它是否与你的问题相关,但是变体只是视图的替代渲染,还是还有其他事情发生? –

+0

“变化1”和“变化2”共享相同的数据,但视图看起来不同并且行为也不同。像1是手风琴种类,2只是静态布局。与我认为的问题无关。上述问题更为一般。 – Krad

回答

0

您可以从服务器上的标题获取用户代理,然后使用返回数据的reducer发送带有用户代理信息的redux操作,这样您就可以检测手机/平板电脑/桌面/

+0

我真的觉得,只是检测设备是不够的这些天。您需要检测分辨率,因为设备本身具有不同的分辨率。平板电脑甚至可以与台式机和笔记本电脑战斗。 – ctrlplusb

+0

@ctrlplusb是的,我很同意你有很多设备本身具有不同的分辨率,但有时只是移动,平板电脑,桌面视图可能已经足够取决于使用情况 – alpha

+0

我同意@ctrlplusb。我可以嗅探设备,但这不是未来证明的我认为的方式。那里有太多的设备(以及将来更多)。要求也是在767px处“破”。所有<将呈现'变化1',<'变化2' – Krad

5

一个很难解决的问题在我看来有很多“依赖”的解决方案。 :)

我是react-sizemereact-component-queries的作者,两个库可以帮助响应组件,并且遇到了类似的问题,您在问题中描述了这些问题。根据我的经验,我发现解决您的一个问题往往会影响另一个问题。我会详细说一下我的意思是通过下面的描述我的经历......

我曾试图解决您的“问题2”第一:

渲染由于默认状态的闪烁是我在我最初创建react-sizeme图书馆期间经历过。 react-sizeme是一个更高阶的组件,它获取组件的大小,然后将其传递到组件中。根据您的尺寸,您可以选择渲染不同的组件,因此,除非您碰巧碰到默认状态甜蜜点,否则更新闪烁可能会发生。我通过改变react-sizeme来最初渲染一个空的占位符,以获得可用的宽度/高度,然后只渲染你的组件,给它“适当的”宽度/高度,从而“征服”了这个。这对我来说非常有效。我不再看到ComponentBob被渲染,只能被卸载并让ComponentFoo立即渲染到它的位置。

然后“问题1”来了...

react-sizeme开始得到普及,并最终我不得不谁愿意在一个服务器端渲染上下文中使用该库的消费者。但由于我对问题1采取了修复措施,服务器端渲染会产生大量空白内容(即我所谈论的占位符)。将有效负载传递给浏览器后,占位符逻辑将启动并最终将大小数据发送到组件,并将呈现它。这并不理想,因为您首先从根本上否定了执行SSR的任何好处。我和这个用户一起工作,我们决定最好的方法是让react-sizeme被配置为在“SSR模式”下运行。基本上,这需要放弃占位符呈现并允许呈现默认组件,以便在初始服务器响应中不会获得空白页面,但是您可以轻松地再次遭受组件闪烁问题!

Aaaaaaaaaah!看到这里的影响锯! :(

所以基本上解决一个问题,直接影响了其他。


我继续给这一些思考,我相信这可能做到这一点的最好办法是尝试并获得用户第一次请求时的浏览器宽度/高度,这基本上意味着渲染一个简单的实用程序,它会消除这些信息,然后将其发送回服务器,以便呈现用户的初始请求,然后可以使用宽度/高度并传递它通过你的整个组件树(一路上进行数学计算)继续确定每个组件的可用高度/宽度。这里超级棘手的东西,但可能工作。

当然其他危险是谷歌只是索引空白页的初始请求(即用于消除初始宽度/高度的util的空白渲染)。你将不得不尝试使用一些聪明的HTTP响应代码,如重定向等,以确保谷歌跟踪适当的渲染输出。


对不起,这可能不是你要找的答案,但我希望我的经验可以帮助以某种方式或提供某种启示。如果你想出一些有趣的实验,请保持我的发布。我很乐意在这方面与你一起工作。

+1

感谢您的回复@ctrlplusb。这对我来说是一个严重的问题。我在服务器上呈现的原因是SEO。由于“移动”和“桌面”上的内容相同,在我的情况下,抓取工具读取的版本并不重要。你所描述的'SSR模式'基本上就是我现在所拥有的 - 一种默认状态 - 与闪烁一起出现。在server-hit和react-render之间使用某种中间件的想法听起来有点棘手,也意味着一个额外的请求(性能下降)。如果我找到解决方法,我会在这里发布。 – Krad

+0

只是FYI,我目前没有多少时间找出上述问题的解决方案,所以我在服务器上使用'mobile-detect.js'并将标题信息传递给状态。通过这种方式,我无法通过特定的宽度进行适应性调整,但我这里的员工对此感到满意。 – Krad

+0

我不是SEO专家,但对我来说,闪烁的解决方案并不是一种解决方案,我不认为抓取工具(最近阅读js的人)很高兴看到一个瞬间和不同的内容内容后... – cl0udw4lk3r