nandorojo / solito

🧍‍♂️ React Native + Next.js, unified.
https://solito.dev
MIT License
3.54k stars 181 forks source link

FOUC on Web (TailwindCSS Starter) #144

Closed agallio closed 2 years ago

agallio commented 2 years ago

Steps to repro:

Update: It's also happening on the basic reload.

https://user-images.githubusercontent.com/22767465/189464937-c541aa63-274a-4b33-84ba-73a1c74e8b4f.mov

nandorojo commented 2 years ago

this is a dev-only problem, it shouldn’t happen on a prod build

cc @marklawlor

nandorojo commented 2 years ago

FWIW, this issue belongs on the nativewind repo

marklawlor commented 2 years ago

To add more information, this is actually caused by @expo/next-adapter and/or react-native-web. If you remove your _document.js file the FOUC will stop. However this will also break some default styles set by Expo and RWN.

nandorojo commented 2 years ago

that’s useful insight. i wonder what the cause is

marklawlor commented 2 years ago

Think I found the issue, same as this https://github.com/vercel/next.js/issues/40122

Expo overrides the getInitialProps, and not does correctly extend it. https://github.com/expo/expo-cli/blob/3d70acb1da2af5a017df51f94eb35aea7aa0ca69/packages/next-adapter/document.js#L52

I think it should be


- export async function getInitialProps({ renderPage }) {
+ export async function getInitialProps(context) {
  AppRegistry.registerComponent('Main', () => Main);
  const { getStyleElement } = AppRegistry.getApplication('Main');
-  const page = await renderPage()
-  const styles = [<style dangerouslySetInnerHTML={{ __html: style }} />, getStyleElement()];
-  return { ...page, styles: React.Children.toArray(styles) };
+  const initialProps = await Document.getInitialProps(context)
+  const styles = [initialProps.styles, <style dangerouslySetInnerHTML={{ __html: style }} />, getStyleElement()];
+  return { ...initialProps, styles: React.Children.toArray(styles) };
}
marklawlor commented 2 years ago

Nope, that's not it. It weirder this css is the cause

html {
  scroll-behavior: smooth;
  /* Prevent text size change on orientation change https://gist.github.com/tfausak/2222823#file-ios-8-web-app-html-L138 */
  -webkit-text-size-adjust: 100%;
  height: 100%;
}

Removing that from Expo seems to fix the issue? Would like someone else to test that

nandorojo commented 2 years ago

as in, removing that from the CSS string itself?

marklawlor commented 2 years ago

Hmm may have been a cache issue.

This is the document I'm testing now, it still has FOUC. Removing <style key="expo" dangerouslySetInnerHTML={{ __html: style }} /> stops the FOUC but removes the default Expo styles.

// Based on https://github.com/zeit/next.js/tree/canary/examples/with-react-native-web
// and https://github.com/expo/expo-cli/blob/main/packages/webpack-config/web-default/index.html
import NextDocument, { Head, Html, Main, NextScript } from 'next/document'
import * as React from 'react'
import { AppRegistry } from 'react-native'

export const style = `
/**
 * Building on the RNWeb reset:
 * https://github.com/necolas/react-native-web/blob/master/packages/react-native-web/src/exports/StyleSheet/initialRules.js
 */
html, body, #__next {
  width: 100%;
  /* To smooth any scrolling behavior */
  -webkit-overflow-scrolling: touch;
  margin: 0px;
  padding: 0px;
  /* Allows content to fill the viewport and go beyond the bottom */
  min-height: 100%;
}
#__next {
  flex-shrink: 0;
  flex-basis: auto;
  flex-direction: column;
  flex-grow: 1;
  display: flex;
  flex: 1;
}
html {
  scroll-behavior: smooth;
  /* Prevent text size change on orientation change https://gist.github.com/tfausak/2222823#file-ios-8-web-app-html-L138 */
  -webkit-text-size-adjust: 100%;
  height: 100%;
}
body {
  display: flex;
  /* Allows you to scroll below the viewport; default value is visible */
  overflow-y: auto;
  overscroll-behavior-y: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -ms-overflow-style: scrollbar;
}
`

export async function getInitialProps(context) {
  AppRegistry.registerComponent('Main', () => Main)
  const { getStyleElement } = AppRegistry.getApplication('Main')
  const page = await context.defaultGetInitialProps(context)
  const styles = [
    <style key="expo" dangerouslySetInnerHTML={{ __html: style }} />,
    getStyleElement(),
    ...page.styles,
  ]
  return { ...page, styles: React.Children.toArray(styles) }
}

export class Document extends NextDocument {
  render() {
    return (
      <Html>
        <Head>
          <meta httpEquiv="X-UA-Compatible" content="IE=edge" />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

Document.getInitialProps = getInitialProps

export default Document
nandorojo commented 2 years ago

@marklawlor does this showtime file help? https://github.com/showtime-xyz/showtime-frontend/blob/staging/apps/next/src/pages/_document.tsx

axeldelafosse commented 2 years ago

Yo guys! Trying a fix here: https://github.com/nandorojo/solito/pull/163