服务器端渲染 + 响应式设计 + 内联样式 -> 使用哪个断点?
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/
我有一个用 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/