部署在 netlify 上的 Gatsby SPA 在第一次加载时应用了错误的情绪 css(精简示例)

Gatsby SPA deployed on netlify applies wrong emotion css on first load (distilled example)

我设法将我的问题提炼成以下代码。它在本地开发服务器上运行良好,但在部署到 Netlify 时会中断。
可以找到源代码库 here(分支 destilled-netlify-problem
分支已部署here


我有一个原始的 Gatsby SPA,通过 Reach Router 进行客户端路由。
它有两页,/app//app/team/:teamName
App 页面应始终呈现 红色背景,而 Team 页面应始终呈现 绿色背景

Ant 就是这样 - 这是所有相关代码:

// src/pages/app.tsx
import React, { FC } from 'react'
import { RouteComponentProps, Router } from '@reach/router'
import { css } from '@emotion/core'
import { sharedCss } from '../styles'

const appCss = css`
  background-color: red;
`
const teamCss = css`
  background-color: green;
`

const AppPage: FC<RouteComponentProps> = () => <div css={[appCss, sharedCss]}>App</div>
const TeamPage: FC<RouteComponentProps> = () => <div css={[teamCss, sharedCss]}>Team</div>

const App = () => (
  <Router>
    <AppPage path="/app/" default />
    <TeamPage path="/app/team/:teamName/" />
  </Router>
)

export default App

gatsby-node.js 按照建议 in Gastsby docs

// /gagsby-node.js
exports.onCreatePage = async ({ page, actions }) => {
  const { createPage } = actions
  if (page.path.match(/^\/app/)) {
    page.matchPath = '/app/*' // eslint-disable-line no-param-reassign
    createPage(page)
  }
}

Netlify _redirects file - 重定向似乎按预期工作

// src/static/_redirects
/app/team/* /app 200

问题:

Team 页面的第一次加载呈现 TeamPage 组件(“Team”一词可见)但背景是红色而不是绿色 - 不知何故 appCss 被应用而不是 teamCss。使用 f5 刷新可以修复此问题,将背景变为绿色。但是使用 ctrl+f5 硬刷新会再次加载损坏的版本。

我注意到当加载损坏的页面时,“App”一词先闪烁,然后变为“Team”,这表明 AppPage 组件首先呈现 - 我想这与重定向有关。我猜 Emotion 不能很好地处理过渡。有什么我可以做的,最好是立即加载 TeamPage

我通过简单地将其中一个组件包装在一个额外的 div 中解决了这个问题。事实证明,这足以防止 Emotion 混淆这两种布局。主页闪烁仍然存在,但现在对我来说已经足够了。

编辑:虽然空 div 解决了提炼示例中的问题,但我 运行 进入更深层次的类似 css 问题我真实应用程序中的组件树。以下 hack 对我有用,虽然不是最优的,但我现在打算接受它。我只是将以下内容添加到我的主页组件中:

// This is a hack to circumvent a problem with emotion. I need to first mount 
// nothing, otherwise wrong css gets applied when redirected via netlify _redirects
const [show, setShow] = useState(false)
useEffect(() => {
  setTimeout(() => setShow(true), 1)
}, [])
if (!show) return null

这样主页永远不会被提交,这可以防止情绪影响它的风格