服务器端渲染 + 响应式设计 + 内联样式 -> 使用哪个断点?

Server-side rendering + responsive design + inline styles -> which breakpoint to use?

我有一个用 ReactJS 构建的响应式 Web 应用程序,我希望有一天它能支持服务器端渲染。

根据视口大小,应用程序layout/behavior发生变化。但是所有这些更改不仅可以通过简单的 CSS mediaquery: JS 行为来完成,而且底层的 HTML 结构也必须根据宽度进行更改。

例如我可以:

800px 宽度以下:

<div class="app">
  <div class="menu-mobile">...</div>
  <div class="content">...</div>
  <div class="mobile-left-menu">...</div>
  <div class="footer-mobile">...</div>
</div>

800px以上宽度:

<div class="app">
  <div class="menu">...</div>
  <div class="main">
    <div class="left-menu">...</div>
    <div class="content">...</div>
    <div class="right-menu">...</div>
  </div>
  <div class="footer">...</div>
</div>

现在,我想为该应用程序使用服务器端呈现。但是在服务器上我没有宽度,所以我不知道哪个 HTML 结构到 return 到客户端。

请注意,我不是在寻找使用静态默认服务器端断点的解决方案,而是在客户端更正应用程序。我正在寻找一种解决方案,可以根据其设备 return 向客户端提供正确的 html 结构。因此,如果他在浏览器上禁用 javascript,它应该可以正常工作。


有人可能会争辩说我可以用普通的 CSS 媒体查询和 display: none 渲染两者所需的 html 和 hide/show 所需的部分,但这会使事情复杂化应用程序并使其呈现大量未使用的 html 元素,因为通常用户不太可能移动 above/under 断点(我的意思是如果他有移动设备,桌面的 html 元素永远不会被使用)

此外,如果我想使用内联样式,它会变得很复杂,因为我必须在服务器上为正确的宽度呈现这些内联样式。

seen 有些人正在考虑嗅探浏览器 UA 以估计他们的视口大小。但是即使有一些不安全的屏幕尺寸检测,我不确定我们是否可以在服务器端知道设备屏幕方向。

我能做些什么来解决这个问题吗?

我想这就是你想要的,但这不是完美的解决方案

1.what 重要

您希望移动用户直接获取移动页面,而无需在 PC 版本中使用 html,反之亦然,这样可以确保不需要 css(改为内联样式),并减少网络

2.how我解决了

使用浏览器用户代理检测手机或平板电脑,您可以在您的服务器上进行预测和渲染,当客户端全部加载后,重新检查屏幕解决方案并再次渲染,如果您有错误的预测。

您可以将回调绑定到 window 调整大小和方向更改,更改您的 redux 并自动呈现

3.shot 来了

网络少,少就是非常非常少

可能会发生错误的预测,当它发生时页面可能会在加载时刷新

//server side detect and show different, if got force param, use force solution
const detected = bowser._detect(req.get('User-Agent'))
const initState = req.query.force ? {
  [req.query.force]: true,
} : {
  bowser: {
    mobile: detected.mobile,
    tablet: detected.tablet,
  }
}
const redux = initStore(initState)
serverRender(redux)

//component X, show different content
const X = ({
  mobile
}) => (<div>
  {!!mobile?(<div>mobile</div>):(<div>pc</div>)}
</div>)

export default connect((state) => {
  return {
    mobile: detected.mobile,
    tablet: detected.tablet,
  }
})(X)

//top level component 
componentDidMount() {
  const reflow = () => {
    switch ($(window).width()) {
      case >800:
        this.props.dispatch(setSolution('pc'))
      default:
        this.props.dispatch(setSolution('mobile'))
    }
  }
  if (typeof window != 'undefined') {
    reflow()
  }
  $(window).resize(() => {
    reflow()
  })
  $(window).on("orientationchange", () => {
    reflow()
  })
}

我认为 Artsy 找到了解决这个问题的最佳方法。

他们在服务器上渲染所有内容,然后只在前端渲染需要的布局。

如果在服务器上他们确定设备有一定的边界,他们最终会通过只渲染所需的布局来优化 SSR。

https://artsy.github.io/blog/2019/05/24/server-rendering-responsively/