在本地(已知警告和CSS呈现良好)运行正常,但在Vercel上,我的Remix应用程序出现以下错误:
由于初始UI与服务器上呈现的不匹配,因此水合作业失败。
业务逻辑运行正常,但CSS完全失效。
更新2022年6月26日15:50
我从头开始新建了一个项目,并逐步添加依赖项,每一步都在Vercel上部署。没有错误。Styled组件呈现良好。因此,依赖关系不是问题所在。
然后,我逐个从我的数据库中通过加载器获取数据,并将它们渲染到Styled组件中。唯一一件始终破坏CSS并产生错误的事情是在呈现之前将datetime对象转换为字符串:
const DateTimeSpan = styled.span`
font-size: 1rem;
`;
const hr = now.getHours();
const min = now.getMinutes();
<DateTimeSpan>
{`${hr}:${min}`}
</DateTimeSpan>
奇怪的是,只有当我将其格式化为仅呈现时间时,它才会出错。使用日期则没有问题:
const yr = now.getFullYear();
const mth = now.getMonth();
const dd = now.getDate();
<DateTimeSpan>
{`${yr}-${mth}-${dd}`}
<DateTimeSpan>
我无法解释这个问题。
2022年7月2日更新,21:55
在使用上述最简项目时,我和朋友发现使用styled components的CSS在尝试渲染小时数时会出现问题:
const hr = now.getHours();
<DateTimeSpan>
{hr}
</DateTimeSpan>
我们怀疑 styled components 出现问题是因为在服务器上以 UTC 时间呈现,但在客户端以本地时间呈现。
我不确定这是否是一个 bug,或者我们是否应该自己处理这个问题。也不确定是否应该在 Remix 或 Styled components 的 GitHub 问题中提出此问题。无论如何,我已经在 Remix 上开了一个issue。
原始帖子
不确定是否与以下问题相关:
我阅读了以上和其他几个页面,所有我能想到的就是更新一些依赖项。以下是可能相关的依赖项:
{
"react": "^18.2.0",
"styled-components": "^5.3.5"
"@remix-run/node": "^1.6.1",
"@remix-run/react": "^1.6.1",
"@remix-run/vercel": "^1.6.1",
"@vercel/node": "^2.2.0",
}
我主要怀疑与styled-components有关,因为我之前在Nextjs上也遇到过类似的问题。但是我的app/root.tsx和app/entry.server.tsx非常接近这个例子中关于styled-components的方式:
// app/root.tsx
export default function App() {
const data = useLoaderData();
return (
<Html lang="en">
<head>
...
{typeof document === "undefined" ? "__STYLES__" : null}
</head>
<Body>
...
</Body>
</Html>
);
}
//app/entry.server.tsx
export default function handleRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext
) {
const sheet = new ServerStyleSheet();
let markup = renderToString(
sheet.collectStyles(
<RemixServer context={remixContext} url={request.url} />
)
);
const styles = sheet.getStyleTags();
markup = markup.replace("__STYLES__", styles);
responseHeaders.set("Content-Type", "text/html");
return new Response("<!DOCTYPE html>" + markup, {
status: responseStatusCode,
headers: responseHeaders,
});
}
与示例最大的不同似乎是,我使用hydrateRoot
而不是hydrate
,这是React 18应该使用的方式。不确定它是否对问题有影响:
// app/entry.client.tsx
import { RemixBrowser } from "@remix-run/react";
import { hydrateRoot } from "react-dom/client";
hydrateRoot(document, <RemixBrowser />);
Remix文档关于CSS-in-JS库中提到:“使用Styled Components时可能会遇到水合警告。希望这个问题很快就会被解决。” 该问题目前尚未解决,因此可能还没有解决方案。
但是,如果示例存储库有效,则可能我错过了什么?
now
;它包含时间(毫秒),在服务器端和客户端渲染之间会发生变化。服务器上的now
与客户端上的now
不同。 - boop_the_snoot